blob: ebe71ab777b64e35cedd3ae83c238d1f24a47fb9 [file] [log] [blame]
Jeff Brown46b9ac02010-04-22 18:58:52 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "InputManager-JNI"
18
Jeff Brown9c3cda02010-06-15 01:31:58 -070019//#define LOG_NDEBUG 0
20
21// Log debug messages about InputReaderPolicy
Jeff Brown349703e2010-06-22 01:27:15 -070022#define DEBUG_INPUT_READER_POLICY 0
Jeff Brown9c3cda02010-06-15 01:31:58 -070023
24// Log debug messages about InputDispatcherPolicy
Jeff Brown349703e2010-06-22 01:27:15 -070025#define DEBUG_INPUT_DISPATCHER_POLICY 0
Jeff Brown9c3cda02010-06-15 01:31:58 -070026
Jeff Brown349703e2010-06-22 01:27:15 -070027// Log debug messages about input focus tracking
28#define DEBUG_FOCUS 0
Jeff Brown9c3cda02010-06-15 01:31:58 -070029
Jeff Brown46b9ac02010-04-22 18:58:52 -070030#include "JNIHelp.h"
31#include "jni.h"
Jeff Brown349703e2010-06-22 01:27:15 -070032#include <limits.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070033#include <android_runtime/AndroidRuntime.h>
Jeff Brown9c3cda02010-06-15 01:31:58 -070034#include <ui/InputReader.h>
35#include <ui/InputDispatcher.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070036#include <ui/InputManager.h>
37#include <ui/InputTransport.h>
38#include <utils/Log.h>
39#include <utils/threads.h>
40#include "../../core/jni/android_view_KeyEvent.h"
41#include "../../core/jni/android_view_MotionEvent.h"
42#include "../../core/jni/android_view_InputChannel.h"
Jeff Brown00fa7bd2010-07-02 15:37:36 -070043#include "com_android_server_PowerManagerService.h"
Jeff Brown46b9ac02010-04-22 18:58:52 -070044
45namespace android {
46
Jeff Brown349703e2010-06-22 01:27:15 -070047// Window flags from WindowManager.LayoutParams
48enum {
49 FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
50 FLAG_DIM_BEHIND = 0x00000002,
51 FLAG_BLUR_BEHIND = 0x00000004,
52 FLAG_NOT_FOCUSABLE = 0x00000008,
53 FLAG_NOT_TOUCHABLE = 0x00000010,
54 FLAG_NOT_TOUCH_MODAL = 0x00000020,
55 FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
56 FLAG_KEEP_SCREEN_ON = 0x00000080,
57 FLAG_LAYOUT_IN_SCREEN = 0x00000100,
58 FLAG_LAYOUT_NO_LIMITS = 0x00000200,
59 FLAG_FULLSCREEN = 0x00000400,
60 FLAG_FORCE_NOT_FULLSCREEN = 0x00000800,
61 FLAG_DITHER = 0x00001000,
62 FLAG_SECURE = 0x00002000,
63 FLAG_SCALED = 0x00004000,
64 FLAG_IGNORE_CHEEK_PRESSES = 0x00008000,
65 FLAG_LAYOUT_INSET_DECOR = 0x00010000,
66 FLAG_ALT_FOCUSABLE_IM = 0x00020000,
67 FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
68 FLAG_SHOW_WHEN_LOCKED = 0x00080000,
69 FLAG_SHOW_WALLPAPER = 0x00100000,
70 FLAG_TURN_SCREEN_ON = 0x00200000,
71 FLAG_DISMISS_KEYGUARD = 0x00400000,
72 FLAG_IMMERSIVE = 0x00800000,
73 FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000,
74 FLAG_COMPATIBLE_WINDOW = 0x20000000,
75 FLAG_SYSTEM_ERROR = 0x40000000,
76};
77
78// Window types from WindowManager.LayoutParams
79enum {
80 FIRST_APPLICATION_WINDOW = 1,
81 TYPE_BASE_APPLICATION = 1,
82 TYPE_APPLICATION = 2,
83 TYPE_APPLICATION_STARTING = 3,
84 LAST_APPLICATION_WINDOW = 99,
85 FIRST_SUB_WINDOW = 1000,
86 TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW,
87 TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1,
88 TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2,
89 TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3,
90 TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4,
91 LAST_SUB_WINDOW = 1999,
92 FIRST_SYSTEM_WINDOW = 2000,
93 TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW,
94 TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1,
95 TYPE_PHONE = FIRST_SYSTEM_WINDOW+2,
96 TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3,
97 TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4,
98 TYPE_TOAST = FIRST_SYSTEM_WINDOW+5,
99 TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6,
100 TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7,
101 TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8,
102 TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9,
103 TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10,
104 TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11,
105 TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
106 TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13,
107 TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14,
108 LAST_SYSTEM_WINDOW = 2999,
109};
110
Jeff Brown349703e2010-06-22 01:27:15 -0700111// Delay between reporting long touch events to the power manager.
112const nsecs_t EVENT_IGNORE_DURATION = 300 * 1000000LL; // 300 ms
113
114// Default input dispatching timeout if there is no focused application or paused window
115// from which to determine an appropriate dispatching timeout.
116const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
117
118// Minimum amount of time to provide to the input dispatcher for delivery of an event
119// regardless of how long the application window was paused.
120const nsecs_t MIN_INPUT_DISPATCHING_TIMEOUT = 1000 * 1000000LL; // 1 sec
121
Jeff Brown9c3cda02010-06-15 01:31:58 -0700122// ----------------------------------------------------------------------------
Jeff Brown46b9ac02010-04-22 18:58:52 -0700123
124static struct {
125 jclass clazz;
126
Jeff Brown46b9ac02010-04-22 18:58:52 -0700127 jmethodID notifyConfigurationChanged;
128 jmethodID notifyLidSwitchChanged;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700129 jmethodID notifyInputChannelBroken;
130 jmethodID notifyInputChannelANR;
131 jmethodID notifyInputChannelRecoveredFromANR;
Jeff Brown349703e2010-06-22 01:27:15 -0700132 jmethodID notifyANR;
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700133 jmethodID virtualKeyDownFeedback;
Jeff Brown349703e2010-06-22 01:27:15 -0700134 jmethodID interceptKeyBeforeQueueing;
135 jmethodID interceptKeyBeforeDispatching;
136 jmethodID checkInjectEventsPermission;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700137 jmethodID notifyAppSwitchComing;
138 jmethodID filterTouchEvents;
139 jmethodID filterJumpyTouchEvents;
140 jmethodID getVirtualKeyDefinitions;
141 jmethodID getExcludedDeviceNames;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700142} gCallbacksClassInfo;
143
144static struct {
145 jclass clazz;
146
147 jfieldID scanCode;
148 jfieldID centerX;
149 jfieldID centerY;
150 jfieldID width;
151 jfieldID height;
152} gVirtualKeyDefinitionClassInfo;
153
Jeff Brown7fbdc842010-06-17 20:52:56 -0700154static struct {
155 jclass clazz;
156
Jeff Brown349703e2010-06-22 01:27:15 -0700157 jfieldID inputChannel;
158 jfieldID layoutParamsFlags;
159 jfieldID layoutParamsType;
160 jfieldID dispatchingTimeoutNanos;
161 jfieldID frameLeft;
162 jfieldID frameTop;
163 jfieldID touchableAreaLeft;
164 jfieldID touchableAreaTop;
165 jfieldID touchableAreaRight;
166 jfieldID touchableAreaBottom;
167 jfieldID visible;
168 jfieldID hasFocus;
169 jfieldID hasWallpaper;
170 jfieldID paused;
171 jfieldID ownerPid;
172 jfieldID ownerUid;
173} gInputWindowClassInfo;
174
175static struct {
176 jclass clazz;
177
178 jfieldID name;
179 jfieldID dispatchingTimeoutNanos;
180 jfieldID token;
181} gInputApplicationClassInfo;
182
Jeff Brown6ec402b2010-07-28 15:48:59 -0700183static struct {
184 jclass clazz;
185} gKeyEventClassInfo;
186
187static struct {
188 jclass clazz;
189} gMotionEventClassInfo;
190
Jeff Brown349703e2010-06-22 01:27:15 -0700191// ----------------------------------------------------------------------------
192
193static inline nsecs_t now() {
194 return systemTime(SYSTEM_TIME_MONOTONIC);
195}
Jeff Brown7fbdc842010-06-17 20:52:56 -0700196
Jeff Brown9c3cda02010-06-15 01:31:58 -0700197// ----------------------------------------------------------------------------
198
199class NativeInputManager : public virtual RefBase,
200 public virtual InputReaderPolicyInterface,
201 public virtual InputDispatcherPolicyInterface {
202protected:
203 virtual ~NativeInputManager();
204
205public:
206 NativeInputManager(jobject callbacksObj);
207
208 inline sp<InputManager> getInputManager() const { return mInputManager; }
209
Jeff Browne33348b2010-07-15 23:54:05 -0700210 String8 dump();
211
Jeff Brown9c3cda02010-06-15 01:31:58 -0700212 void setDisplaySize(int32_t displayId, int32_t width, int32_t height);
213 void setDisplayOrientation(int32_t displayId, int32_t orientation);
214
Jeff Brown7fbdc842010-06-17 20:52:56 -0700215 status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
Jeff Browna41ca772010-08-11 14:46:32 -0700216 jweak inputChannelObjWeak, bool monitor);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700217 status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
218
Jeff Brown349703e2010-06-22 01:27:15 -0700219 void setInputWindows(JNIEnv* env, jobjectArray windowObjArray);
220 void setFocusedApplication(JNIEnv* env, jobject applicationObj);
221 void setInputDispatchMode(bool enabled, bool frozen);
222 void preemptInputDispatch();
223
Jeff Brown9c3cda02010-06-15 01:31:58 -0700224 /* --- InputReaderPolicyInterface implementation --- */
225
226 virtual bool getDisplayInfo(int32_t displayId,
227 int32_t* width, int32_t* height, int32_t* orientation);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700228 virtual void virtualKeyDownFeedback();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700229 virtual int32_t interceptKey(nsecs_t when, int32_t deviceId,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700230 bool down, int32_t keyCode, int32_t scanCode, uint32_t& policyFlags);
231 virtual int32_t interceptSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
232 uint32_t& policyFlags);
233 virtual int32_t interceptGeneric(nsecs_t when, uint32_t& policyFlags);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700234 virtual bool filterTouchEvents();
235 virtual bool filterJumpyTouchEvents();
236 virtual void getVirtualKeyDefinitions(const String8& deviceName,
237 Vector<InputReaderPolicyInterface::VirtualKeyDefinition>& outVirtualKeyDefinitions);
238 virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames);
239
240 /* --- InputDispatcherPolicyInterface implementation --- */
241
242 virtual void notifyConfigurationChanged(nsecs_t when);
243 virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700244 virtual bool notifyInputChannelANR(const sp<InputChannel>& inputChannel,
245 nsecs_t& outNewTimeout);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700246 virtual void notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel);
247 virtual nsecs_t getKeyRepeatTimeout();
Jeff Brown349703e2010-06-22 01:27:15 -0700248 virtual int32_t waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700249 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brown349703e2010-06-22 01:27:15 -0700250 virtual int32_t waitForMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700251 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700252
253private:
Jeff Brown349703e2010-06-22 01:27:15 -0700254 struct InputWindow {
255 sp<InputChannel> inputChannel;
256 int32_t layoutParamsFlags;
257 int32_t layoutParamsType;
258 nsecs_t dispatchingTimeout;
259 int32_t frameLeft;
260 int32_t frameTop;
261 int32_t touchableAreaLeft;
262 int32_t touchableAreaTop;
263 int32_t touchableAreaRight;
264 int32_t touchableAreaBottom;
265 bool visible;
266 bool hasFocus;
267 bool hasWallpaper;
268 bool paused;
269 int32_t ownerPid;
270 int32_t ownerUid;
271
272 inline bool touchableAreaContainsPoint(int32_t x, int32_t y) {
273 return x >= touchableAreaLeft && x <= touchableAreaRight
274 && y >= touchableAreaTop && y <= touchableAreaBottom;
275 }
276 };
277
278 struct InputApplication {
279 String8 name;
280 nsecs_t dispatchingTimeout;
281 jweak tokenObjWeak;
282 };
283
284 class ANRTimer {
285 enum Budget {
286 SYSTEM = 0,
287 APPLICATION = 1
288 };
289
290 Budget mBudget;
291 nsecs_t mStartTime;
292 bool mFrozen;
293 InputWindow* mPausedWindow;
294
295 public:
296 ANRTimer();
297
298 void dispatchFrozenBySystem();
299 void dispatchPausedByApplication(InputWindow* pausedWindow);
300 bool waitForDispatchStateChangeLd(NativeInputManager* inputManager);
301
302 nsecs_t getTimeSpentWaitingForApplication() const;
303 };
304
Jeff Brown9c3cda02010-06-15 01:31:58 -0700305 sp<InputManager> mInputManager;
306
307 jobject mCallbacksObj;
308
309 // Cached filtering policies.
310 int32_t mFilterTouchEvents;
311 int32_t mFilterJumpyTouchEvents;
312
313 // Cached display state. (lock mDisplayLock)
314 Mutex mDisplayLock;
315 int32_t mDisplayWidth, mDisplayHeight;
316 int32_t mDisplayOrientation;
317
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700318 // Power manager interactions.
Jeff Brown9c3cda02010-06-15 01:31:58 -0700319 bool isScreenOn();
320 bool isScreenBright();
321
Jeff Brown7fbdc842010-06-17 20:52:56 -0700322 // Weak references to all currently registered input channels by receive fd.
323 Mutex mInputChannelRegistryLock;
324 KeyedVector<int, jweak> mInputChannelObjWeakByReceiveFd;
325
326 jobject getInputChannelObjLocal(JNIEnv* env, const sp<InputChannel>& inputChannel);
327
Jeff Brown349703e2010-06-22 01:27:15 -0700328 // Input target and focus tracking. (lock mDispatchLock)
329 Mutex mDispatchLock;
330 Condition mDispatchStateChanged;
331
332 bool mDispatchEnabled;
333 bool mDispatchFrozen;
334 bool mWindowsReady;
335 Vector<InputWindow> mWindows;
336 Vector<InputWindow*> mWallpaperWindows;
Jeff Browna41ca772010-08-11 14:46:32 -0700337 Vector<sp<InputChannel> > mMonitoringChannels;
Jeff Brown349703e2010-06-22 01:27:15 -0700338
339 // Focus tracking for keys, trackball, etc.
340 InputWindow* mFocusedWindow;
341
342 // Focus tracking for touch.
343 bool mTouchDown;
344 InputWindow* mTouchedWindow; // primary target for current down
345 Vector<InputWindow*> mTouchedWallpaperWindows; // wallpaper targets
346
347 Vector<InputWindow*> mTempTouchedOutsideWindows; // temporary outside touch targets
348 Vector<sp<InputChannel> > mTempTouchedWallpaperChannels; // temporary wallpaper targets
349
350 // Focused application.
351 InputApplication* mFocusedApplication;
352 InputApplication mFocusedApplicationStorage; // preallocated storage for mFocusedApplication
353
Jeff Brown6d0fec22010-07-23 21:28:06 -0700354 void dumpDeviceInfo(String8& dump);
Jeff Browne33348b2010-07-15 23:54:05 -0700355 void dumpDispatchStateLd(String8& dump);
356 void logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -0700357
358 bool notifyANR(jobject tokenObj, nsecs_t& outNewTimeout);
359 void releaseFocusedApplicationLd(JNIEnv* env);
360
361 int32_t waitForFocusedWindowLd(uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
362 Vector<InputTarget>& outTargets, InputWindow*& outFocusedWindow);
363 int32_t waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
364 int32_t injectorPid, int32_t injectorUid,
365 Vector<InputTarget>& outTargets, InputWindow*& outTouchedWindow);
366
367 void releaseTouchedWindowLd();
368
Jeff Brownc5ed5912010-07-14 18:48:53 -0700369 int32_t waitForNonTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown349703e2010-06-22 01:27:15 -0700370 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700371 int32_t waitForTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown349703e2010-06-22 01:27:15 -0700372 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
373
Jeff Brownd0097872010-06-30 14:41:59 -0700374 bool interceptKeyBeforeDispatching(const InputTarget& target,
375 const KeyEvent* keyEvent, uint32_t policyFlags);
376
Jeff Brown349703e2010-06-22 01:27:15 -0700377 void pokeUserActivityIfNeeded(int32_t windowType, int32_t eventType);
378 void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
379 bool checkInjectionPermission(const InputWindow* window,
380 int32_t injectorPid, int32_t injectorUid);
381
382 static bool populateWindow(JNIEnv* env, jobject windowObj, InputWindow& outWindow);
383 static void addTarget(const InputWindow* window, int32_t targetFlags,
384 nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets);
385
Jeff Browna41ca772010-08-11 14:46:32 -0700386 void registerMonitoringChannel(const sp<InputChannel>& inputChannel);
387 void unregisterMonitoringChannel(const sp<InputChannel>& inputChannel);
388 void addMonitoringTargetsLd(Vector<InputTarget>& outTargets);
389
Jeff Brown9c3cda02010-06-15 01:31:58 -0700390 static inline JNIEnv* jniEnv() {
391 return AndroidRuntime::getJNIEnv();
392 }
393
394 static bool isAppSwitchKey(int32_t keyCode);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700395 static bool isPolicyKey(int32_t keyCode, bool isScreenOn);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700396 static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700397};
398
399// ----------------------------------------------------------------------------
400
401NativeInputManager::NativeInputManager(jobject callbacksObj) :
402 mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1),
Jeff Brown0b72e822010-06-29 16:52:21 -0700403 mDisplayWidth(-1), mDisplayHeight(-1), mDisplayOrientation(ROTATION_0),
Jeff Brown349703e2010-06-22 01:27:15 -0700404 mDispatchEnabled(true), mDispatchFrozen(false), mWindowsReady(true),
405 mFocusedWindow(NULL), mTouchDown(false), mTouchedWindow(NULL),
406 mFocusedApplication(NULL) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700407 JNIEnv* env = jniEnv();
408
409 mCallbacksObj = env->NewGlobalRef(callbacksObj);
410
411 sp<EventHub> eventHub = new EventHub();
412 mInputManager = new InputManager(eventHub, this, this);
413}
414
415NativeInputManager::~NativeInputManager() {
416 JNIEnv* env = jniEnv();
417
418 env->DeleteGlobalRef(mCallbacksObj);
Jeff Brown349703e2010-06-22 01:27:15 -0700419
420 releaseFocusedApplicationLd(env);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700421}
422
Jeff Browne33348b2010-07-15 23:54:05 -0700423String8 NativeInputManager::dump() {
424 String8 dump;
Jeff Brown00ba8842010-07-16 15:01:56 -0700425 { // acquire lock
426 AutoMutex _l(mDisplayLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700427 dump.append("Native Input Dispatcher State:\n");
Jeff Brown00ba8842010-07-16 15:01:56 -0700428 dumpDispatchStateLd(dump);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700429 dump.append("\n");
Jeff Brown00ba8842010-07-16 15:01:56 -0700430 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -0700431
432 dump.append("Input Devices:\n");
433 dumpDeviceInfo(dump);
434
Jeff Browne33348b2010-07-15 23:54:05 -0700435 return dump;
436}
437
Jeff Brown9c3cda02010-06-15 01:31:58 -0700438bool NativeInputManager::isAppSwitchKey(int32_t keyCode) {
Jeff Brownfd035822010-06-30 16:10:35 -0700439 return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700440}
441
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700442bool NativeInputManager::isPolicyKey(int32_t keyCode, bool isScreenOn) {
443 // Special keys that the WindowManagerPolicy might care about.
444 switch (keyCode) {
Jeff Brownfd035822010-06-30 16:10:35 -0700445 case AKEYCODE_VOLUME_UP:
446 case AKEYCODE_VOLUME_DOWN:
447 case AKEYCODE_ENDCALL:
448 case AKEYCODE_POWER:
449 case AKEYCODE_CALL:
450 case AKEYCODE_HOME:
451 case AKEYCODE_MENU:
452 case AKEYCODE_SEARCH:
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700453 // media keys
Jeff Brownfd035822010-06-30 16:10:35 -0700454 case AKEYCODE_HEADSETHOOK:
455 case AKEYCODE_MEDIA_PLAY_PAUSE:
456 case AKEYCODE_MEDIA_STOP:
457 case AKEYCODE_MEDIA_NEXT:
458 case AKEYCODE_MEDIA_PREVIOUS:
459 case AKEYCODE_MEDIA_REWIND:
460 case AKEYCODE_MEDIA_FAST_FORWARD:
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700461 return true;
462 default:
463 // We need to pass all keys to the policy in the following cases:
464 // - screen is off
465 // - keyguard is visible
466 // - policy is performing key chording
467 //return ! isScreenOn || keyguardVisible || chording;
468 return true; // XXX stubbed out for now
469 }
470}
471
Jeff Brown7fbdc842010-06-17 20:52:56 -0700472bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700473 if (env->ExceptionCheck()) {
474 LOGE("An exception was thrown by callback '%s'.", methodName);
475 LOGE_EX(env);
476 env->ExceptionClear();
477 return true;
478 }
479 return false;
480}
481
482void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height) {
483 if (displayId == 0) {
484 AutoMutex _l(mDisplayLock);
485
486 mDisplayWidth = width;
487 mDisplayHeight = height;
488 }
489}
490
491void NativeInputManager::setDisplayOrientation(int32_t displayId, int32_t orientation) {
492 if (displayId == 0) {
493 AutoMutex _l(mDisplayLock);
494
495 mDisplayOrientation = orientation;
496 }
497}
498
Jeff Brown7fbdc842010-06-17 20:52:56 -0700499status_t NativeInputManager::registerInputChannel(JNIEnv* env,
Jeff Browna41ca772010-08-11 14:46:32 -0700500 const sp<InputChannel>& inputChannel, jobject inputChannelObj, bool monitor) {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700501 jweak inputChannelObjWeak = env->NewWeakGlobalRef(inputChannelObj);
502 if (! inputChannelObjWeak) {
503 LOGE("Could not create weak reference for input channel.");
504 LOGE_EX(env);
505 return NO_MEMORY;
506 }
507
508 status_t status;
509 {
510 AutoMutex _l(mInputChannelRegistryLock);
511
512 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
513 inputChannel->getReceivePipeFd());
514 if (index >= 0) {
515 LOGE("Input channel object '%s' has already been registered",
516 inputChannel->getName().string());
517 status = INVALID_OPERATION;
518 goto DeleteWeakRef;
519 }
520
521 mInputChannelObjWeakByReceiveFd.add(inputChannel->getReceivePipeFd(),
522 inputChannelObjWeak);
523 }
524
525 status = mInputManager->registerInputChannel(inputChannel);
526 if (! status) {
Jeff Browna41ca772010-08-11 14:46:32 -0700527 // Success.
528 if (monitor) {
529 registerMonitoringChannel(inputChannel);
530 }
Jeff Brown7fbdc842010-06-17 20:52:56 -0700531 return OK;
532 }
533
Jeff Browna41ca772010-08-11 14:46:32 -0700534 // Failed!
Jeff Brown7fbdc842010-06-17 20:52:56 -0700535 {
536 AutoMutex _l(mInputChannelRegistryLock);
537 mInputChannelObjWeakByReceiveFd.removeItem(inputChannel->getReceivePipeFd());
538 }
539
540DeleteWeakRef:
541 env->DeleteWeakGlobalRef(inputChannelObjWeak);
542 return status;
543}
544
545status_t NativeInputManager::unregisterInputChannel(JNIEnv* env,
546 const sp<InputChannel>& inputChannel) {
547 jweak inputChannelObjWeak;
548 {
549 AutoMutex _l(mInputChannelRegistryLock);
550
551 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
552 inputChannel->getReceivePipeFd());
553 if (index < 0) {
554 LOGE("Input channel object '%s' is not currently registered",
555 inputChannel->getName().string());
556 return INVALID_OPERATION;
557 }
558
559 inputChannelObjWeak = mInputChannelObjWeakByReceiveFd.valueAt(index);
560 mInputChannelObjWeakByReceiveFd.removeItemsAt(index);
561 }
562
563 env->DeleteWeakGlobalRef(inputChannelObjWeak);
564
Jeff Browna41ca772010-08-11 14:46:32 -0700565 unregisterMonitoringChannel(inputChannel);
566
Jeff Brown7fbdc842010-06-17 20:52:56 -0700567 return mInputManager->unregisterInputChannel(inputChannel);
568}
569
570jobject NativeInputManager::getInputChannelObjLocal(JNIEnv* env,
571 const sp<InputChannel>& inputChannel) {
572 {
573 AutoMutex _l(mInputChannelRegistryLock);
574
575 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
576 inputChannel->getReceivePipeFd());
577 if (index < 0) {
578 return NULL;
579 }
580
581 jweak inputChannelObjWeak = mInputChannelObjWeakByReceiveFd.valueAt(index);
582 return env->NewLocalRef(inputChannelObjWeak);
583 }
584}
585
Jeff Brown9c3cda02010-06-15 01:31:58 -0700586bool NativeInputManager::getDisplayInfo(int32_t displayId,
587 int32_t* width, int32_t* height, int32_t* orientation) {
588 bool result = false;
589 if (displayId == 0) {
590 AutoMutex _l(mDisplayLock);
591
592 if (mDisplayWidth > 0) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700593 if (width) {
594 *width = mDisplayWidth;
595 }
596 if (height) {
597 *height = mDisplayHeight;
598 }
599 if (orientation) {
600 *orientation = mDisplayOrientation;
601 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700602 result = true;
603 }
604 }
605 return result;
606}
607
608bool NativeInputManager::isScreenOn() {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700609 return android_server_PowerManagerService_isScreenOn();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700610}
611
612bool NativeInputManager::isScreenBright() {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700613 return android_server_PowerManagerService_isScreenBright();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700614}
615
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700616void NativeInputManager::virtualKeyDownFeedback() {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700617#if DEBUG_INPUT_READER_POLICY
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700618 LOGD("virtualKeyDownFeedback");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700619#endif
620
621 JNIEnv* env = jniEnv();
622
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700623 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.virtualKeyDownFeedback);
624 checkAndClearExceptionFromCallback(env, "virtualKeyDownFeedback");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700625}
626
627int32_t NativeInputManager::interceptKey(nsecs_t when,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700628 int32_t deviceId, bool down, int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700629#if DEBUG_INPUT_READER_POLICY
630 LOGD("interceptKey - when=%lld, deviceId=%d, down=%d, keyCode=%d, scanCode=%d, "
Jeff Brown349703e2010-06-22 01:27:15 -0700631 "policyFlags=0x%x",
Jeff Brown9c3cda02010-06-15 01:31:58 -0700632 when, deviceId, down, keyCode, scanCode, policyFlags);
633#endif
634
635 const int32_t WM_ACTION_PASS_TO_USER = 1;
636 const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2;
637 const int32_t WM_ACTION_GO_TO_SLEEP = 4;
638
Jeff Brown9c3cda02010-06-15 01:31:58 -0700639 bool isScreenOn = this->isScreenOn();
640 bool isScreenBright = this->isScreenBright();
641
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700642 jint wmActions = 0;
643 if (isPolicyKey(keyCode, isScreenOn)) {
644 JNIEnv* env = jniEnv();
645
646 wmActions = env->CallIntMethod(mCallbacksObj,
647 gCallbacksClassInfo.interceptKeyBeforeQueueing,
648 when, keyCode, down, policyFlags, isScreenOn);
649 if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
650 wmActions = 0;
651 }
652 } else {
653 wmActions = WM_ACTION_PASS_TO_USER;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700654 }
655
656 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
657 if (! isScreenOn) {
658 // Key presses and releases wake the device.
Jeff Brown6d0fec22010-07-23 21:28:06 -0700659 policyFlags |= POLICY_FLAG_WOKE_HERE;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700660 }
661
662 if (! isScreenBright) {
663 // Key presses and releases brighten the screen if dimmed.
Jeff Brown6d0fec22010-07-23 21:28:06 -0700664 policyFlags |= POLICY_FLAG_BRIGHT_HERE;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700665 }
666
667 if (wmActions & WM_ACTION_GO_TO_SLEEP) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700668 android_server_PowerManagerService_goToSleep(when);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700669 }
670
671 if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
Jeff Brown349703e2010-06-22 01:27:15 -0700672 pokeUserActivity(when, POWER_MANAGER_BUTTON_EVENT);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700673 }
674
675 if (wmActions & WM_ACTION_PASS_TO_USER) {
676 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700677
Jeff Brown9c3cda02010-06-15 01:31:58 -0700678 if (down && isAppSwitchKey(keyCode)) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700679 JNIEnv* env = jniEnv();
680
Jeff Brown9c3cda02010-06-15 01:31:58 -0700681 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyAppSwitchComing);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700682 checkAndClearExceptionFromCallback(env, "notifyAppSwitchComing");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700683
684 actions |= InputReaderPolicyInterface::ACTION_APP_SWITCH_COMING;
685 }
686 }
Jeff Brown349703e2010-06-22 01:27:15 -0700687
Jeff Brown9c3cda02010-06-15 01:31:58 -0700688 return actions;
689}
690
Jeff Brown6d0fec22010-07-23 21:28:06 -0700691int32_t NativeInputManager::interceptGeneric(nsecs_t when, uint32_t& policyFlags) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700692#if DEBUG_INPUT_READER_POLICY
Jeff Brown6d0fec22010-07-23 21:28:06 -0700693 LOGD("interceptGeneric - when=%lld, policyFlags=0x%x", when, policyFlags);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700694#endif
695
Jeff Brown5c225b12010-06-16 01:53:36 -0700696 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
697 if (isScreenOn()) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700698 // Only dispatch events when the device is awake.
Jeff Brown349703e2010-06-22 01:27:15 -0700699 // Do not wake the device.
Jeff Brown5c225b12010-06-16 01:53:36 -0700700 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700701
Jeff Brown349703e2010-06-22 01:27:15 -0700702 if (! isScreenBright()) {
703 // Brighten the screen if dimmed.
Jeff Brown6d0fec22010-07-23 21:28:06 -0700704 policyFlags |= POLICY_FLAG_BRIGHT_HERE;
Jeff Brown349703e2010-06-22 01:27:15 -0700705 }
Jeff Brown5c225b12010-06-16 01:53:36 -0700706 }
707
708 return actions;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700709}
710
711int32_t NativeInputManager::interceptSwitch(nsecs_t when, int32_t switchCode,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700712 int32_t switchValue, uint32_t& policyFlags) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700713#if DEBUG_INPUT_READER_POLICY
Jeff Brown6d0fec22010-07-23 21:28:06 -0700714 LOGD("interceptSwitch - when=%lld, switchCode=%d, switchValue=%d, policyFlags=0x%x",
715 when, switchCode, switchValue, policyFlags);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700716#endif
717
718 JNIEnv* env = jniEnv();
719
720 switch (switchCode) {
721 case SW_LID:
722 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyLidSwitchChanged,
723 when, switchValue == 0);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700724 checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700725 break;
726 }
727
728 return InputReaderPolicyInterface::ACTION_NONE;
729}
730
731bool NativeInputManager::filterTouchEvents() {
732 if (mFilterTouchEvents < 0) {
733 JNIEnv* env = jniEnv();
734
735 jboolean result = env->CallBooleanMethod(mCallbacksObj,
736 gCallbacksClassInfo.filterTouchEvents);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700737 if (checkAndClearExceptionFromCallback(env, "filterTouchEvents")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700738 result = false;
739 }
740
741 mFilterTouchEvents = result ? 1 : 0;
742 }
743 return mFilterTouchEvents;
744}
745
746bool NativeInputManager::filterJumpyTouchEvents() {
747 if (mFilterJumpyTouchEvents < 0) {
748 JNIEnv* env = jniEnv();
749
750 jboolean result = env->CallBooleanMethod(mCallbacksObj,
751 gCallbacksClassInfo.filterJumpyTouchEvents);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700752 if (checkAndClearExceptionFromCallback(env, "filterJumpyTouchEvents")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700753 result = false;
754 }
755
756 mFilterJumpyTouchEvents = result ? 1 : 0;
757 }
758 return mFilterJumpyTouchEvents;
759}
760
761void NativeInputManager::getVirtualKeyDefinitions(const String8& deviceName,
762 Vector<InputReaderPolicyInterface::VirtualKeyDefinition>& outVirtualKeyDefinitions) {
763 JNIEnv* env = jniEnv();
764
765 jstring deviceNameStr = env->NewStringUTF(deviceName.string());
Jeff Brown7fbdc842010-06-17 20:52:56 -0700766 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700767 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
768 gCallbacksClassInfo.getVirtualKeyDefinitions, deviceNameStr));
Jeff Brown7fbdc842010-06-17 20:52:56 -0700769 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions") && result) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700770 jsize length = env->GetArrayLength(result);
771 for (jsize i = 0; i < length; i++) {
772 jobject item = env->GetObjectArrayElement(result, i);
773
774 outVirtualKeyDefinitions.add();
775 outVirtualKeyDefinitions.editTop().scanCode =
776 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.scanCode));
777 outVirtualKeyDefinitions.editTop().centerX =
778 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerX));
779 outVirtualKeyDefinitions.editTop().centerY =
780 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerY));
781 outVirtualKeyDefinitions.editTop().width =
782 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.width));
783 outVirtualKeyDefinitions.editTop().height =
784 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.height));
785
786 env->DeleteLocalRef(item);
787 }
788 env->DeleteLocalRef(result);
789 }
790 env->DeleteLocalRef(deviceNameStr);
791 }
792}
793
794void NativeInputManager::getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
795 JNIEnv* env = jniEnv();
796
797 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
798 gCallbacksClassInfo.getExcludedDeviceNames));
Jeff Brown7fbdc842010-06-17 20:52:56 -0700799 if (! checkAndClearExceptionFromCallback(env, "getExcludedDeviceNames") && result) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700800 jsize length = env->GetArrayLength(result);
801 for (jsize i = 0; i < length; i++) {
802 jstring item = jstring(env->GetObjectArrayElement(result, i));
803
804 const char* deviceNameChars = env->GetStringUTFChars(item, NULL);
805 outExcludedDeviceNames.add(String8(deviceNameChars));
806 env->ReleaseStringUTFChars(item, deviceNameChars);
807
808 env->DeleteLocalRef(item);
809 }
810 env->DeleteLocalRef(result);
811 }
812}
813
814void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
815#if DEBUG_INPUT_DISPATCHER_POLICY
816 LOGD("notifyConfigurationChanged - when=%lld", when);
817#endif
818
819 JNIEnv* env = jniEnv();
820
821 InputConfiguration config;
822 mInputManager->getInputConfiguration(& config);
823
824 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyConfigurationChanged,
825 when, config.touchScreen, config.keyboard, config.navigation);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700826 checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700827}
828
829void NativeInputManager::notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
830#if DEBUG_INPUT_DISPATCHER_POLICY
831 LOGD("notifyInputChannelBroken - inputChannel='%s'", inputChannel->getName().string());
832#endif
833
Jeff Brown7fbdc842010-06-17 20:52:56 -0700834 JNIEnv* env = jniEnv();
835
836 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
837 if (inputChannelObjLocal) {
838 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelBroken,
839 inputChannelObjLocal);
840 checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken");
841
842 env->DeleteLocalRef(inputChannelObjLocal);
843 }
Jeff Browna41ca772010-08-11 14:46:32 -0700844
845 unregisterMonitoringChannel(inputChannel);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700846}
847
Jeff Brown7fbdc842010-06-17 20:52:56 -0700848bool NativeInputManager::notifyInputChannelANR(const sp<InputChannel>& inputChannel,
849 nsecs_t& outNewTimeout) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700850#if DEBUG_INPUT_DISPATCHER_POLICY
851 LOGD("notifyInputChannelANR - inputChannel='%s'",
852 inputChannel->getName().string());
853#endif
854
Jeff Brown7fbdc842010-06-17 20:52:56 -0700855 JNIEnv* env = jniEnv();
856
857 jlong newTimeout;
858 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
859 if (inputChannelObjLocal) {
860 newTimeout = env->CallLongMethod(mCallbacksObj,
861 gCallbacksClassInfo.notifyInputChannelANR, inputChannelObjLocal);
862 if (checkAndClearExceptionFromCallback(env, "notifyInputChannelANR")) {
863 newTimeout = -2;
864 }
865
866 env->DeleteLocalRef(inputChannelObjLocal);
867 } else {
868 newTimeout = -2;
869 }
870
871 if (newTimeout == -2) {
872 return false; // abort
873 }
874
875 outNewTimeout = newTimeout;
876 return true; // resume
Jeff Brown9c3cda02010-06-15 01:31:58 -0700877}
878
879void NativeInputManager::notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel) {
880#if DEBUG_INPUT_DISPATCHER_POLICY
881 LOGD("notifyInputChannelRecoveredFromANR - inputChannel='%s'",
882 inputChannel->getName().string());
883#endif
884
Jeff Brown7fbdc842010-06-17 20:52:56 -0700885 JNIEnv* env = jniEnv();
886
887 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
888 if (inputChannelObjLocal) {
889 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelRecoveredFromANR,
890 inputChannelObjLocal);
891 checkAndClearExceptionFromCallback(env, "notifyInputChannelRecoveredFromANR");
892
893 env->DeleteLocalRef(inputChannelObjLocal);
894 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700895}
896
Jeff Brown349703e2010-06-22 01:27:15 -0700897bool NativeInputManager::notifyANR(jobject tokenObj, nsecs_t& outNewTimeout) {
898#if DEBUG_INPUT_DISPATCHER_POLICY
899 LOGD("notifyANR");
900#endif
901
902 JNIEnv* env = jniEnv();
903
904 jlong newTimeout = env->CallLongMethod(mCallbacksObj,
905 gCallbacksClassInfo.notifyANR, tokenObj);
906 if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
907 newTimeout = -2;
908 }
909
910 if (newTimeout == -2) {
911 return false; // abort
912 }
913
914 outNewTimeout = newTimeout;
915 return true; // resume
916}
917
Jeff Brown9c3cda02010-06-15 01:31:58 -0700918nsecs_t NativeInputManager::getKeyRepeatTimeout() {
919 if (! isScreenOn()) {
920 // Disable key repeat when the screen is off.
921 return -1;
922 } else {
923 // TODO use ViewConfiguration.getLongPressTimeout()
924 return milliseconds_to_nanoseconds(500);
925 }
926}
927
Jeff Brown349703e2010-06-22 01:27:15 -0700928void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArray) {
929#if DEBUG_FOCUS
930 LOGD("setInputWindows");
931#endif
932 { // acquire lock
933 AutoMutex _l(mDispatchLock);
934
935 sp<InputChannel> touchedWindowChannel;
936 if (mTouchedWindow) {
937 touchedWindowChannel = mTouchedWindow->inputChannel;
938 mTouchedWindow = NULL;
939 }
940 size_t numTouchedWallpapers = mTouchedWallpaperWindows.size();
941 if (numTouchedWallpapers != 0) {
942 for (size_t i = 0; i < numTouchedWallpapers; i++) {
943 mTempTouchedWallpaperChannels.push(mTouchedWallpaperWindows[i]->inputChannel);
944 }
945 mTouchedWallpaperWindows.clear();
946 }
947
Jeff Browne33348b2010-07-15 23:54:05 -0700948 bool hadFocusedWindow = mFocusedWindow != NULL;
949
Jeff Brown349703e2010-06-22 01:27:15 -0700950 mWindows.clear();
951 mFocusedWindow = NULL;
952 mWallpaperWindows.clear();
953
954 if (windowObjArray) {
955 mWindowsReady = true;
956
957 jsize length = env->GetArrayLength(windowObjArray);
958 for (jsize i = 0; i < length; i++) {
959 jobject inputTargetObj = env->GetObjectArrayElement(windowObjArray, i);
960 if (! inputTargetObj) {
961 break; // found null element indicating end of used portion of the array
962 }
963
964 mWindows.push();
965 InputWindow& window = mWindows.editTop();
966 bool valid = populateWindow(env, inputTargetObj, window);
967 if (! valid) {
968 mWindows.pop();
969 }
970
971 env->DeleteLocalRef(inputTargetObj);
972 }
973
974 size_t numWindows = mWindows.size();
975 for (size_t i = 0; i < numWindows; i++) {
976 InputWindow* window = & mWindows.editItemAt(i);
977 if (window->hasFocus) {
978 mFocusedWindow = window;
979 }
980
981 if (window->layoutParamsType == TYPE_WALLPAPER) {
982 mWallpaperWindows.push(window);
983
984 for (size_t j = 0; j < numTouchedWallpapers; j++) {
985 if (window->inputChannel == mTempTouchedWallpaperChannels[i]) {
986 mTouchedWallpaperWindows.push(window);
987 }
988 }
989 }
990
991 if (window->inputChannel == touchedWindowChannel) {
992 mTouchedWindow = window;
993 }
994 }
995 } else {
996 mWindowsReady = false;
997 }
998
999 mTempTouchedWallpaperChannels.clear();
1000
Jeff Brown00ba8842010-07-16 15:01:56 -07001001 if ((hadFocusedWindow && ! mFocusedWindow)
1002 || (mFocusedWindow && ! mFocusedWindow->visible)) {
Jeff Browne33348b2010-07-15 23:54:05 -07001003 preemptInputDispatch();
1004 }
1005
Jeff Brown349703e2010-06-22 01:27:15 -07001006 mDispatchStateChanged.broadcast();
1007
1008#if DEBUG_FOCUS
Jeff Browne33348b2010-07-15 23:54:05 -07001009 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001010#endif
1011 } // release lock
1012}
1013
1014bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj,
1015 InputWindow& outWindow) {
1016 bool valid = false;
1017
1018 jobject inputChannelObj = env->GetObjectField(windowObj,
1019 gInputWindowClassInfo.inputChannel);
1020 if (inputChannelObj) {
1021 sp<InputChannel> inputChannel =
1022 android_view_InputChannel_getInputChannel(env, inputChannelObj);
1023 if (inputChannel != NULL) {
1024 jint layoutParamsFlags = env->GetIntField(windowObj,
1025 gInputWindowClassInfo.layoutParamsFlags);
1026 jint layoutParamsType = env->GetIntField(windowObj,
1027 gInputWindowClassInfo.layoutParamsType);
1028 jlong dispatchingTimeoutNanos = env->GetLongField(windowObj,
1029 gInputWindowClassInfo.dispatchingTimeoutNanos);
1030 jint frameLeft = env->GetIntField(windowObj,
1031 gInputWindowClassInfo.frameLeft);
1032 jint frameTop = env->GetIntField(windowObj,
1033 gInputWindowClassInfo.frameTop);
1034 jint touchableAreaLeft = env->GetIntField(windowObj,
1035 gInputWindowClassInfo.touchableAreaLeft);
1036 jint touchableAreaTop = env->GetIntField(windowObj,
1037 gInputWindowClassInfo.touchableAreaTop);
1038 jint touchableAreaRight = env->GetIntField(windowObj,
1039 gInputWindowClassInfo.touchableAreaRight);
1040 jint touchableAreaBottom = env->GetIntField(windowObj,
1041 gInputWindowClassInfo.touchableAreaBottom);
1042 jboolean visible = env->GetBooleanField(windowObj,
1043 gInputWindowClassInfo.visible);
1044 jboolean hasFocus = env->GetBooleanField(windowObj,
1045 gInputWindowClassInfo.hasFocus);
1046 jboolean hasWallpaper = env->GetBooleanField(windowObj,
1047 gInputWindowClassInfo.hasWallpaper);
1048 jboolean paused = env->GetBooleanField(windowObj,
1049 gInputWindowClassInfo.paused);
1050 jint ownerPid = env->GetIntField(windowObj,
1051 gInputWindowClassInfo.ownerPid);
1052 jint ownerUid = env->GetIntField(windowObj,
1053 gInputWindowClassInfo.ownerUid);
1054
1055 outWindow.inputChannel = inputChannel;
1056 outWindow.layoutParamsFlags = layoutParamsFlags;
1057 outWindow.layoutParamsType = layoutParamsType;
1058 outWindow.dispatchingTimeout = dispatchingTimeoutNanos;
1059 outWindow.frameLeft = frameLeft;
1060 outWindow.frameTop = frameTop;
1061 outWindow.touchableAreaLeft = touchableAreaLeft;
1062 outWindow.touchableAreaTop = touchableAreaTop;
1063 outWindow.touchableAreaRight = touchableAreaRight;
1064 outWindow.touchableAreaBottom = touchableAreaBottom;
1065 outWindow.visible = visible;
1066 outWindow.hasFocus = hasFocus;
1067 outWindow.hasWallpaper = hasWallpaper;
1068 outWindow.paused = paused;
1069 outWindow.ownerPid = ownerPid;
1070 outWindow.ownerUid = ownerUid;
1071 valid = true;
1072 } else {
1073 LOGW("Dropping input target because its input channel is not initialized.");
1074 }
1075
1076 env->DeleteLocalRef(inputChannelObj);
1077 } else {
1078 LOGW("Dropping input target because the input channel object was null.");
1079 }
1080 return valid;
1081}
1082
1083void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) {
1084#if DEBUG_FOCUS
1085 LOGD("setFocusedApplication");
1086#endif
1087 { // acquire lock
1088 AutoMutex _l(mDispatchLock);
1089
1090 releaseFocusedApplicationLd(env);
1091
1092 if (applicationObj) {
1093 jstring nameObj = jstring(env->GetObjectField(applicationObj,
1094 gInputApplicationClassInfo.name));
1095 jlong dispatchingTimeoutNanos = env->GetLongField(applicationObj,
1096 gInputApplicationClassInfo.dispatchingTimeoutNanos);
1097 jobject tokenObj = env->GetObjectField(applicationObj,
1098 gInputApplicationClassInfo.token);
1099 jweak tokenObjWeak = env->NewWeakGlobalRef(tokenObj);
1100 if (! tokenObjWeak) {
1101 LOGE("Could not create weak reference for application token.");
1102 LOGE_EX(env);
1103 env->ExceptionClear();
1104 }
1105 env->DeleteLocalRef(tokenObj);
1106
1107 mFocusedApplication = & mFocusedApplicationStorage;
1108
1109 if (nameObj) {
1110 const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
1111 mFocusedApplication->name.setTo(nameStr);
1112 env->ReleaseStringUTFChars(nameObj, nameStr);
1113 env->DeleteLocalRef(nameObj);
1114 } else {
1115 LOGE("InputApplication.name should not be null.");
1116 mFocusedApplication->name.setTo("unknown");
1117 }
1118
1119 mFocusedApplication->dispatchingTimeout = dispatchingTimeoutNanos;
1120 mFocusedApplication->tokenObjWeak = tokenObjWeak;
1121 }
1122
1123 mDispatchStateChanged.broadcast();
1124
1125#if DEBUG_FOCUS
Jeff Browne33348b2010-07-15 23:54:05 -07001126 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001127#endif
1128 } // release lock
1129}
1130
1131void NativeInputManager::releaseFocusedApplicationLd(JNIEnv* env) {
1132 if (mFocusedApplication) {
1133 env->DeleteWeakGlobalRef(mFocusedApplication->tokenObjWeak);
1134 mFocusedApplication = NULL;
1135 }
1136}
1137
1138void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
1139#if DEBUG_FOCUS
1140 LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001141#endif
1142
Jeff Brown349703e2010-06-22 01:27:15 -07001143 { // acquire lock
1144 AutoMutex _l(mDispatchLock);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001145
Jeff Brown349703e2010-06-22 01:27:15 -07001146 if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
1147 mDispatchEnabled = enabled;
1148 mDispatchFrozen = frozen;
1149
1150 mDispatchStateChanged.broadcast();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001151 }
Jeff Brown349703e2010-06-22 01:27:15 -07001152
1153#if DEBUG_FOCUS
Jeff Browne33348b2010-07-15 23:54:05 -07001154 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001155#endif
1156 } // release lock
1157}
1158
1159void NativeInputManager::preemptInputDispatch() {
1160#if DEBUG_FOCUS
1161 LOGD("preemptInputDispatch");
1162#endif
1163
1164 mInputManager->preemptInputDispatch();
1165}
1166
1167int32_t NativeInputManager::waitForFocusedWindowLd(uint32_t policyFlags,
1168 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
1169 InputWindow*& outFocusedWindow) {
1170
1171 int32_t injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1172 bool firstIteration = true;
1173 ANRTimer anrTimer;
1174 for (;;) {
1175 if (firstIteration) {
1176 firstIteration = false;
1177 } else {
1178 if (! anrTimer.waitForDispatchStateChangeLd(this)) {
1179 LOGW("Dropping event because the dispatcher timed out waiting to identify "
1180 "the window that should receive it.");
1181 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1182 break;
1183 }
1184 }
1185
1186 // If dispatch is not enabled then fail.
1187 if (! mDispatchEnabled) {
1188 LOGI("Dropping event because input dispatch is disabled.");
1189 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1190 break;
1191 }
1192
1193 // If dispatch is frozen or we don't have valid window data yet then wait.
1194 if (mDispatchFrozen || ! mWindowsReady) {
1195#if DEBUG_FOCUS
1196 LOGD("Waiting because dispatch is frozen or windows are not ready.");
1197#endif
1198 anrTimer.dispatchFrozenBySystem();
1199 continue;
1200 }
1201
1202 // If there is no currently focused window and no focused application
1203 // then drop the event.
1204 if (! mFocusedWindow) {
1205 if (mFocusedApplication) {
1206#if DEBUG_FOCUS
1207 LOGD("Waiting because there is no focused window but there is a "
1208 "focused application that may yet introduce a new target: '%s'.",
1209 mFocusedApplication->name.string());
1210#endif
1211 continue;
1212 }
1213
1214 LOGI("Dropping event because there is no focused window or focused application.");
1215 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1216 break;
1217 }
1218
1219 // Check permissions.
1220 if (! checkInjectionPermission(mFocusedWindow, injectorPid, injectorUid)) {
1221 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1222 break;
1223 }
1224
1225 // If the currently focused window is paused then keep waiting.
1226 if (mFocusedWindow->paused) {
1227#if DEBUG_FOCUS
1228 LOGD("Waiting because focused window is paused.");
1229#endif
1230 anrTimer.dispatchPausedByApplication(mFocusedWindow);
1231 continue;
1232 }
1233
1234 // Success!
1235 break; // done waiting, exit loop
Jeff Brown9c3cda02010-06-15 01:31:58 -07001236 }
Jeff Brown349703e2010-06-22 01:27:15 -07001237
1238 // Output targets.
1239 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
1240 addTarget(mFocusedWindow, InputTarget::FLAG_SYNC,
1241 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
1242
1243 outFocusedWindow = mFocusedWindow;
1244 } else {
1245 outFocusedWindow = NULL;
1246 }
1247
1248#if DEBUG_FOCUS
1249 LOGD("waitForFocusedWindow finished: injectionResult=%d",
1250 injectionResult);
Jeff Browne33348b2010-07-15 23:54:05 -07001251 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001252#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001253 return injectionResult;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001254}
1255
Jeff Brownc5ed5912010-07-14 18:48:53 -07001256enum InjectionPermission {
1257 INJECTION_PERMISSION_UNKNOWN,
1258 INJECTION_PERMISSION_GRANTED,
1259 INJECTION_PERMISSION_DENIED
1260};
1261
Jeff Brown349703e2010-06-22 01:27:15 -07001262int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
1263 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
1264 InputWindow*& outTouchedWindow) {
1265 nsecs_t startTime = now();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001266
Jeff Brown349703e2010-06-22 01:27:15 -07001267 // For security reasons, we defer updating the touch state until we are sure that
1268 // event injection will be allowed.
1269 //
1270 // FIXME In the original code, screenWasOff could never be set to true.
1271 // The reason is that the POLICY_FLAG_WOKE_HERE
1272 // and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
1273 // EV_KEY, EV_REL and EV_ABS events. As it happens, the touch event was
1274 // actually enqueued using the policyFlags that appeared in the final EV_SYN
1275 // events upon which no preprocessing took place. So policyFlags was always 0.
1276 // In the new native input dispatcher we're a bit more careful about event
1277 // preprocessing so the touches we receive can actually have non-zero policyFlags.
1278 // Unfortunately we obtain undesirable behavior.
1279 //
1280 // Here's what happens:
1281 //
1282 // When the device dims in anticipation of going to sleep, touches
1283 // in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
1284 // the device to brighten and reset the user activity timer.
1285 // Touches on other windows (such as the launcher window)
1286 // are dropped. Then after a moment, the device goes to sleep. Oops.
1287 //
1288 // Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
1289 // instead of POLICY_FLAG_WOKE_HERE...
1290 //
1291 bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001292
1293 int32_t action = motionEvent->getAction();
1294
Jeff Brown349703e2010-06-22 01:27:15 -07001295 bool firstIteration = true;
1296 ANRTimer anrTimer;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001297 int32_t injectionResult;
1298 InjectionPermission injectionPermission;
Jeff Brown349703e2010-06-22 01:27:15 -07001299 for (;;) {
1300 if (firstIteration) {
1301 firstIteration = false;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001302 } else {
Jeff Brown349703e2010-06-22 01:27:15 -07001303 if (! anrTimer.waitForDispatchStateChangeLd(this)) {
1304 LOGW("Dropping event because the dispatcher timed out waiting to identify "
1305 "the window that should receive it.");
1306 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001307 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
1308 break; // timed out, exit wait loop
Jeff Brown349703e2010-06-22 01:27:15 -07001309 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001310 }
Jeff Brown349703e2010-06-22 01:27:15 -07001311
1312 // If dispatch is not enabled then fail.
1313 if (! mDispatchEnabled) {
1314 LOGI("Dropping event because input dispatch is disabled.");
1315 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001316 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
Jeff Brown349703e2010-06-22 01:27:15 -07001317 break; // failed, exit wait loop
1318 }
1319
1320 // If dispatch is frozen or we don't have valid window data yet then wait.
1321 if (mDispatchFrozen || ! mWindowsReady) {
1322#if DEBUG_INPUT_DISPATCHER_POLICY
1323 LOGD("Waiting because dispatch is frozen or windows are not ready.");
1324#endif
1325 anrTimer.dispatchFrozenBySystem();
1326 continue;
1327 }
1328
1329 // Update the touch state as needed based on the properties of the touch event.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001330 if (action == AMOTION_EVENT_ACTION_DOWN) {
1331 /* Case 1: ACTION_DOWN */
1332
Jeff Brown349703e2010-06-22 01:27:15 -07001333 InputWindow* newTouchedWindow = NULL;
1334 mTempTouchedOutsideWindows.clear();
1335
1336 int32_t x = int32_t(motionEvent->getX(0));
1337 int32_t y = int32_t(motionEvent->getY(0));
1338 InputWindow* topErrorWindow = NULL;
1339
1340 // Traverse windows from front to back to find touched window and outside targets.
1341 size_t numWindows = mWindows.size();
1342 for (size_t i = 0; i < numWindows; i++) {
1343 InputWindow* window = & mWindows.editItemAt(i);
1344 int32_t flags = window->layoutParamsFlags;
1345
1346 if (flags & FLAG_SYSTEM_ERROR) {
1347 if (! topErrorWindow) {
1348 topErrorWindow = window;
1349 }
1350 }
1351
1352 if (window->visible) {
1353 if (! (flags & FLAG_NOT_TOUCHABLE)) {
1354 bool isTouchModal = (flags &
1355 (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL)) == 0;
1356 if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
1357 if (! screenWasOff || flags & FLAG_TOUCHABLE_WHEN_WAKING) {
1358 newTouchedWindow = window;
1359 }
1360 break; // found touched window, exit window loop
1361 }
1362 }
1363
1364 if (flags & FLAG_WATCH_OUTSIDE_TOUCH) {
1365 mTempTouchedOutsideWindows.push(window);
1366 }
1367 }
1368 }
1369
1370 // If there is an error window but it is not taking focus (typically because
1371 // it is invisible) then wait for it. Any other focused window may in
1372 // fact be in ANR state.
1373 if (topErrorWindow && newTouchedWindow != topErrorWindow) {
1374#if DEBUG_INPUT_DISPATCHER_POLICY
1375 LOGD("Waiting because system error window is pending.");
1376#endif
1377 anrTimer.dispatchFrozenBySystem();
1378 continue; // wait some more
1379 }
1380
1381 // If we did not find a touched window then fail.
1382 if (! newTouchedWindow) {
1383 if (mFocusedApplication) {
1384#if DEBUG_FOCUS
1385 LOGD("Waiting because there is no focused window but there is a "
1386 "focused application that may yet introduce a new target: '%s'.",
1387 mFocusedApplication->name.string());
1388#endif
1389 continue;
1390 }
1391
1392 LOGI("Dropping event because there is no touched window or focused application.");
1393 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001394 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
Jeff Brown349703e2010-06-22 01:27:15 -07001395 break; // failed, exit wait loop
1396 }
1397
1398 // Check permissions.
1399 if (! checkInjectionPermission(newTouchedWindow, injectorPid, injectorUid)) {
1400 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001401 injectionPermission = INJECTION_PERMISSION_DENIED;
Jeff Brown349703e2010-06-22 01:27:15 -07001402 break; // failed, exit wait loop
1403 }
1404
1405 // If the touched window is paused then keep waiting.
1406 if (newTouchedWindow->paused) {
1407#if DEBUG_INPUT_DISPATCHER_POLICY
1408 LOGD("Waiting because touched window is paused.");
1409#endif
1410 anrTimer.dispatchPausedByApplication(newTouchedWindow);
1411 continue; // wait some more
1412 }
1413
1414 // Success! Update the touch dispatch state for real.
1415 releaseTouchedWindowLd();
1416
1417 mTouchedWindow = newTouchedWindow;
1418
1419 if (newTouchedWindow->hasWallpaper) {
1420 mTouchedWallpaperWindows.appendVector(mWallpaperWindows);
1421 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001422
1423 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1424 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001425 break; // done
1426 } else {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001427 /* Case 2: Everything but ACTION_DOWN */
1428
Jeff Brown349703e2010-06-22 01:27:15 -07001429 // Check permissions.
1430 if (! checkInjectionPermission(mTouchedWindow, injectorPid, injectorUid)) {
1431 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001432 injectionPermission = INJECTION_PERMISSION_DENIED;
1433 break; // failed, exit wait loop
1434 }
1435
1436 // If the pointer is not currently down, then ignore the event.
1437 if (! mTouchDown) {
1438 LOGI("Dropping event because the pointer is not down.");
1439 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1440 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001441 break; // failed, exit wait loop
1442 }
1443
1444 // If there is no currently touched window then fail.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001445 if (! mTouchedWindow) {
Jeff Browna41ca772010-08-11 14:46:32 -07001446#if DEBUG_INPUT_DISPATCHER_POLICY
1447 LOGD("Dropping event because there is no touched window to receive it.");
1448#endif
Jeff Brown349703e2010-06-22 01:27:15 -07001449 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001450 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001451 break; // failed, exit wait loop
1452 }
1453
1454 // If the touched window is paused then keep waiting.
1455 if (mTouchedWindow->paused) {
1456#if DEBUG_INPUT_DISPATCHER_POLICY
1457 LOGD("Waiting because touched window is paused.");
1458#endif
1459 anrTimer.dispatchPausedByApplication(mTouchedWindow);
1460 continue; // wait some more
1461 }
1462
1463 // Success!
Jeff Brownc5ed5912010-07-14 18:48:53 -07001464 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1465 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001466 break; // done
1467 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001468 }
Jeff Brown349703e2010-06-22 01:27:15 -07001469
1470 // Output targets.
Jeff Brown349703e2010-06-22 01:27:15 -07001471 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
Jeff Brown349703e2010-06-22 01:27:15 -07001472 size_t numWallpaperWindows = mTouchedWallpaperWindows.size();
1473 for (size_t i = 0; i < numWallpaperWindows; i++) {
1474 addTarget(mTouchedWallpaperWindows[i], 0, 0, outTargets);
1475 }
1476
1477 size_t numOutsideWindows = mTempTouchedOutsideWindows.size();
1478 for (size_t i = 0; i < numOutsideWindows; i++) {
1479 addTarget(mTempTouchedOutsideWindows[i], InputTarget::FLAG_OUTSIDE, 0, outTargets);
1480 }
1481
1482 addTarget(mTouchedWindow, InputTarget::FLAG_SYNC,
1483 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
1484 outTouchedWindow = mTouchedWindow;
1485 } else {
Jeff Brown349703e2010-06-22 01:27:15 -07001486 outTouchedWindow = NULL;
1487 }
1488 mTempTouchedOutsideWindows.clear();
1489
Jeff Brownc5ed5912010-07-14 18:48:53 -07001490 // Check injection permission once and for all.
1491 if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
1492 if (checkInjectionPermission(action == AMOTION_EVENT_ACTION_DOWN ? NULL : mTouchedWindow,
1493 injectorPid, injectorUid)) {
1494 injectionPermission = INJECTION_PERMISSION_GRANTED;
1495 } else {
1496 injectionPermission = INJECTION_PERMISSION_DENIED;
1497 }
1498 }
1499
1500 // Update final pieces of touch state if the injector had permission.
1501 if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
1502 if (action == AMOTION_EVENT_ACTION_DOWN) {
Jeff Brown349703e2010-06-22 01:27:15 -07001503 if (mTouchDown) {
1504 // This is weird. We got a down but we thought it was already down!
1505 LOGW("Pointer down received while already down.");
1506 } else {
1507 mTouchDown = true;
1508 }
1509
1510 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1511 // Since we failed to identify a target for this touch down, we may still
1512 // be holding on to an earlier target from a previous touch down. Release it.
1513 releaseTouchedWindowLd();
1514 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001515 } else if (action == AMOTION_EVENT_ACTION_UP) {
Jeff Brown349703e2010-06-22 01:27:15 -07001516 mTouchDown = false;
1517 releaseTouchedWindowLd();
1518 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001519 } else {
1520 LOGW("Not updating touch focus because injection was denied.");
Jeff Brown349703e2010-06-22 01:27:15 -07001521 }
1522
1523#if DEBUG_FOCUS
1524 LOGD("waitForTouchedWindow finished: injectionResult=%d",
1525 injectionResult);
Jeff Browne33348b2010-07-15 23:54:05 -07001526 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001527#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001528 return injectionResult;
1529}
1530
Jeff Brown349703e2010-06-22 01:27:15 -07001531void NativeInputManager::releaseTouchedWindowLd() {
1532 mTouchedWindow = NULL;
1533 mTouchedWallpaperWindows.clear();
1534}
1535
1536void NativeInputManager::addTarget(const InputWindow* window, int32_t targetFlags,
1537 nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets) {
1538 nsecs_t timeout = window->dispatchingTimeout - timeSpentWaitingForApplication;
1539 if (timeout < MIN_INPUT_DISPATCHING_TIMEOUT) {
1540 timeout = MIN_INPUT_DISPATCHING_TIMEOUT;
1541 }
1542
1543 outTargets.push();
1544
1545 InputTarget& target = outTargets.editTop();
1546 target.inputChannel = window->inputChannel;
1547 target.flags = targetFlags;
1548 target.timeout = timeout;
1549 target.xOffset = - window->frameLeft;
1550 target.yOffset = - window->frameTop;
1551}
1552
1553bool NativeInputManager::checkInjectionPermission(const InputWindow* window,
1554 int32_t injectorPid, int32_t injectorUid) {
1555 if (injectorUid > 0 && (window == NULL || window->ownerUid != injectorUid)) {
1556 JNIEnv* env = jniEnv();
1557 jboolean result = env->CallBooleanMethod(mCallbacksObj,
1558 gCallbacksClassInfo.checkInjectEventsPermission, injectorPid, injectorUid);
1559 checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission");
1560
1561 if (! result) {
1562 if (window) {
1563 LOGW("Permission denied: injecting event from pid %d uid %d to window "
1564 "with input channel %s owned by uid %d",
1565 injectorPid, injectorUid, window->inputChannel->getName().string(),
1566 window->ownerUid);
1567 } else {
1568 LOGW("Permission denied: injecting event from pid %d uid %d",
1569 injectorPid, injectorUid);
1570 }
1571 return false;
1572 }
1573 }
1574
1575 return true;
1576}
1577
1578int32_t NativeInputManager::waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
1579 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets) {
1580#if DEBUG_INPUT_DISPATCHER_POLICY
1581 LOGD("waitForKeyEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1582 policyFlags, injectorPid, injectorUid);
1583#endif
1584
1585 int32_t windowType;
1586 { // acquire lock
1587 AutoMutex _l(mDispatchLock);
1588
1589 InputWindow* focusedWindow;
1590 int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
1591 injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
1592 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1593 return injectionResult;
1594 }
1595
1596 windowType = focusedWindow->layoutParamsType;
1597 } // release lock
1598
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001599 if (isPolicyKey(keyEvent->getKeyCode(), isScreenOn())) {
1600 const InputTarget& target = outTargets.top();
1601 bool consumed = interceptKeyBeforeDispatching(target, keyEvent, policyFlags);
1602 if (consumed) {
1603 outTargets.clear();
1604 return INPUT_EVENT_INJECTION_SUCCEEDED;
1605 }
Jeff Browna41ca772010-08-11 14:46:32 -07001606
1607 addMonitoringTargetsLd(outTargets);
Jeff Brown349703e2010-06-22 01:27:15 -07001608 }
1609
1610 pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
1611 return INPUT_EVENT_INJECTION_SUCCEEDED;
1612}
1613
1614int32_t NativeInputManager::waitForMotionEventTargets(MotionEvent* motionEvent,
1615 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001616 Vector<InputTarget>& outTargets) {
Jeff Brown349703e2010-06-22 01:27:15 -07001617#if DEBUG_INPUT_DISPATCHER_POLICY
1618 LOGD("waitForMotionEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1619 policyFlags, injectorPid, injectorUid);
1620#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001621
Jeff Brownc5ed5912010-07-14 18:48:53 -07001622 int32_t source = motionEvent->getSource();
1623 if (source & AINPUT_SOURCE_CLASS_POINTER) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001624 return waitForTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
Jeff Brown349703e2010-06-22 01:27:15 -07001625 outTargets);
Jeff Brownc5ed5912010-07-14 18:48:53 -07001626 } else {
1627 return waitForNonTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
1628 outTargets);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001629 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001630}
1631
Jeff Brownc5ed5912010-07-14 18:48:53 -07001632int32_t NativeInputManager::waitForNonTouchEventTargets(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 Brownc5ed5912010-07-14 18:48:53 -07001636 LOGD("waitForNonTouchEventTargets - 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* focusedWindow;
1645 int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
1646 injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
1647 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1648 return injectionResult;
1649 }
1650
1651 windowType = focusedWindow->layoutParamsType;
Jeff Browna41ca772010-08-11 14:46:32 -07001652
1653 addMonitoringTargetsLd(outTargets);
Jeff Brown349703e2010-06-22 01:27:15 -07001654 } // release lock
1655
1656 pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
1657 return INPUT_EVENT_INJECTION_SUCCEEDED;
1658}
1659
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001660int32_t NativeInputManager::waitForTouchEventTargets(MotionEvent* motionEvent,
Jeff Brown349703e2010-06-22 01:27:15 -07001661 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
1662 Vector<InputTarget>& outTargets) {
1663#if DEBUG_INPUT_DISPATCHER_POLICY
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001664 LOGD("waitForTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
Jeff Brown349703e2010-06-22 01:27:15 -07001665 policyFlags, injectorPid, injectorUid);
1666#endif
1667
1668 int32_t windowType;
1669 { // acquire lock
1670 AutoMutex _l(mDispatchLock);
1671
1672 InputWindow* touchedWindow;
1673 int32_t injectionResult = waitForTouchedWindowLd(motionEvent, policyFlags,
1674 injectorPid, injectorUid, outTargets, /*out*/ touchedWindow);
1675 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1676 return injectionResult;
1677 }
1678
1679 windowType = touchedWindow->layoutParamsType;
Jeff Browna41ca772010-08-11 14:46:32 -07001680
1681 addMonitoringTargetsLd(outTargets);
Jeff Brown349703e2010-06-22 01:27:15 -07001682 } // release lock
1683
1684 int32_t eventType;
1685 switch (motionEvent->getAction()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001686 case AMOTION_EVENT_ACTION_DOWN:
Jeff Brown349703e2010-06-22 01:27:15 -07001687 eventType = POWER_MANAGER_TOUCH_EVENT;
1688 break;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001689 case AMOTION_EVENT_ACTION_UP:
Jeff Brown349703e2010-06-22 01:27:15 -07001690 eventType = POWER_MANAGER_TOUCH_UP_EVENT;
1691 break;
1692 default:
1693 if (motionEvent->getEventTime() - motionEvent->getDownTime()
1694 >= EVENT_IGNORE_DURATION) {
1695 eventType = POWER_MANAGER_TOUCH_EVENT;
1696 } else {
1697 eventType = POWER_MANAGER_LONG_TOUCH_EVENT;
1698 }
1699 break;
1700 }
1701 pokeUserActivityIfNeeded(windowType, eventType);
1702 return INPUT_EVENT_INJECTION_SUCCEEDED;
1703}
1704
Jeff Brownd0097872010-06-30 14:41:59 -07001705bool NativeInputManager::interceptKeyBeforeDispatching(const InputTarget& target,
1706 const KeyEvent* keyEvent, uint32_t policyFlags) {
1707 JNIEnv* env = jniEnv();
1708
1709 jobject inputChannelObj = getInputChannelObjLocal(env, target.inputChannel);
1710 if (inputChannelObj) {
1711 jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
1712 gCallbacksClassInfo.interceptKeyBeforeDispatching,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001713 inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(),
1714 keyEvent->getKeyCode(), keyEvent->getMetaState(),
Jeff Brownd0097872010-06-30 14:41:59 -07001715 keyEvent->getRepeatCount(), policyFlags);
1716 bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
1717
1718 env->DeleteLocalRef(inputChannelObj);
1719
1720 return consumed && ! error;
1721 } else {
1722 LOGW("Could not apply key dispatch policy because input channel '%s' is "
1723 "no longer valid.", target.inputChannel->getName().string());
1724 return false;
1725 }
1726}
1727
Jeff Brown349703e2010-06-22 01:27:15 -07001728void NativeInputManager::pokeUserActivityIfNeeded(int32_t windowType, int32_t eventType) {
1729 if (windowType != TYPE_KEYGUARD) {
1730 nsecs_t eventTime = now();
1731 pokeUserActivity(eventTime, eventType);
1732 }
1733}
1734
1735void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001736 android_server_PowerManagerService_userActivity(eventTime, eventType);
Jeff Brown349703e2010-06-22 01:27:15 -07001737}
1738
Jeff Browna41ca772010-08-11 14:46:32 -07001739void NativeInputManager::registerMonitoringChannel(const sp<InputChannel>& inputChannel) {
1740 { // acquire lock
1741 AutoMutex _l(mDispatchLock);
1742 mMonitoringChannels.push(inputChannel);
1743 } // release lock
1744}
1745
1746void NativeInputManager::unregisterMonitoringChannel(const sp<InputChannel>& inputChannel) {
1747 { // acquire lock
1748 AutoMutex _l(mDispatchLock);
1749
1750 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
1751 if (mMonitoringChannels[i] == inputChannel) {
1752 mMonitoringChannels.removeAt(i);
1753 break;
1754 }
1755 }
1756 } // release lock
1757}
1758
1759void NativeInputManager::addMonitoringTargetsLd(Vector<InputTarget>& outTargets) {
1760 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
1761 outTargets.push();
1762
1763 InputTarget& target = outTargets.editTop();
1764 target.inputChannel = mMonitoringChannels[i];
1765 target.flags = 0;
1766 target.timeout = -1;
1767 target.xOffset = 0;
1768 target.yOffset = 0;
1769 }
1770}
1771
Jeff Brown6d0fec22010-07-23 21:28:06 -07001772static void dumpMotionRange(String8& dump,
1773 const char* name, const InputDeviceInfo::MotionRange* range) {
1774 if (range) {
1775 dump.appendFormat(" %s = { min: %0.3f, max: %0.3f, flat: %0.3f, fuzz: %0.3f }\n",
1776 name, range->min, range->max, range->flat, range->fuzz);
1777 }
1778}
1779
1780#define DUMP_MOTION_RANGE(range) \
1781 dumpMotionRange(dump, #range, deviceInfo.getMotionRange(AINPUT_MOTION_RANGE_##range));
1782
1783void NativeInputManager::dumpDeviceInfo(String8& dump) {
1784 Vector<int32_t> deviceIds;
1785 mInputManager->getInputDeviceIds(deviceIds);
1786
1787 InputDeviceInfo deviceInfo;
1788 for (size_t i = 0; i < deviceIds.size(); i++) {
1789 int32_t deviceId = deviceIds[i];
1790
1791 status_t result = mInputManager->getInputDeviceInfo(deviceId, & deviceInfo);
1792 if (result == NAME_NOT_FOUND) {
1793 continue;
1794 } else if (result != OK) {
1795 dump.appendFormat(" ** Unexpected error %d getting information about input devices.\n",
1796 result);
1797 continue;
1798 }
1799
1800 dump.appendFormat(" Device %d: '%s'\n",
1801 deviceInfo.getId(), deviceInfo.getName().string());
1802 dump.appendFormat(" sources = 0x%08x\n",
1803 deviceInfo.getSources());
1804 dump.appendFormat(" keyboardType = %d\n",
1805 deviceInfo.getKeyboardType());
1806
1807 dump.append(" motion ranges:\n");
1808 DUMP_MOTION_RANGE(X);
1809 DUMP_MOTION_RANGE(Y);
1810 DUMP_MOTION_RANGE(PRESSURE);
1811 DUMP_MOTION_RANGE(SIZE);
1812 DUMP_MOTION_RANGE(TOUCH_MAJOR);
1813 DUMP_MOTION_RANGE(TOUCH_MINOR);
1814 DUMP_MOTION_RANGE(TOOL_MAJOR);
1815 DUMP_MOTION_RANGE(TOOL_MINOR);
1816 DUMP_MOTION_RANGE(ORIENTATION);
1817 }
1818}
1819
1820#undef DUMP_MOTION_RANGE
1821
Jeff Browne33348b2010-07-15 23:54:05 -07001822void NativeInputManager::logDispatchStateLd() {
1823 String8 dump;
1824 dumpDispatchStateLd(dump);
1825 LOGD("%s", dump.string());
1826}
1827
1828void NativeInputManager::dumpDispatchStateLd(String8& dump) {
1829 dump.appendFormat(" dispatchEnabled: %d\n", mDispatchEnabled);
1830 dump.appendFormat(" dispatchFrozen: %d\n", mDispatchFrozen);
1831 dump.appendFormat(" windowsReady: %d\n", mWindowsReady);
1832
Jeff Brown349703e2010-06-22 01:27:15 -07001833 if (mFocusedApplication) {
Jeff Browne33348b2010-07-15 23:54:05 -07001834 dump.appendFormat(" focusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001835 mFocusedApplication->name.string(),
1836 mFocusedApplication->dispatchingTimeout / 1000000.0);
1837 } else {
Jeff Browne33348b2010-07-15 23:54:05 -07001838 dump.append(" focusedApplication: <null>\n");
Jeff Brown349703e2010-06-22 01:27:15 -07001839 }
Jeff Browne33348b2010-07-15 23:54:05 -07001840 dump.appendFormat(" focusedWindow: '%s'\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001841 mFocusedWindow != NULL ? mFocusedWindow->inputChannel->getName().string() : "<null>");
Jeff Browne33348b2010-07-15 23:54:05 -07001842 dump.appendFormat(" touchedWindow: '%s', touchDown=%d\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001843 mTouchedWindow != NULL ? mTouchedWindow->inputChannel->getName().string() : "<null>",
1844 mTouchDown);
1845 for (size_t i = 0; i < mTouchedWallpaperWindows.size(); i++) {
Jeff Browne33348b2010-07-15 23:54:05 -07001846 dump.appendFormat(" touchedWallpaperWindows[%d]: '%s'\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001847 i, mTouchedWallpaperWindows[i]->inputChannel->getName().string());
1848 }
1849 for (size_t i = 0; i < mWindows.size(); i++) {
Jeff Browne33348b2010-07-15 23:54:05 -07001850 dump.appendFormat(" windows[%d]: '%s', paused=%d, hasFocus=%d, hasWallpaper=%d, "
1851 "visible=%d, flags=0x%08x, type=0x%08x, "
Jeff Brown349703e2010-06-22 01:27:15 -07001852 "frame=[%d,%d], touchableArea=[%d,%d][%d,%d], "
Jeff Browne33348b2010-07-15 23:54:05 -07001853 "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001854 i, mWindows[i].inputChannel->getName().string(),
1855 mWindows[i].paused, mWindows[i].hasFocus, mWindows[i].hasWallpaper,
1856 mWindows[i].visible, mWindows[i].layoutParamsFlags, mWindows[i].layoutParamsType,
1857 mWindows[i].frameLeft, mWindows[i].frameTop,
1858 mWindows[i].touchableAreaLeft, mWindows[i].touchableAreaTop,
1859 mWindows[i].touchableAreaRight, mWindows[i].touchableAreaBottom,
1860 mWindows[i].ownerPid, mWindows[i].ownerUid,
1861 mWindows[i].dispatchingTimeout / 1000000.0);
1862 }
Jeff Browna41ca772010-08-11 14:46:32 -07001863
1864 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
1865 dump.appendFormat(" monitoringChannel[%d]: '%s'\n",
1866 i, mMonitoringChannels[i]->getName().string());
1867 }
Jeff Brown349703e2010-06-22 01:27:15 -07001868}
1869
1870// ----------------------------------------------------------------------------
1871
1872NativeInputManager::ANRTimer::ANRTimer() :
1873 mBudget(APPLICATION), mStartTime(now()), mFrozen(false), mPausedWindow(NULL) {
1874}
1875
1876void NativeInputManager::ANRTimer::dispatchFrozenBySystem() {
1877 mFrozen = true;
1878}
1879
1880void NativeInputManager::ANRTimer::dispatchPausedByApplication(InputWindow* pausedWindow) {
1881 mPausedWindow = pausedWindow;
1882}
1883
1884bool NativeInputManager::ANRTimer::waitForDispatchStateChangeLd(NativeInputManager* inputManager) {
1885 nsecs_t currentTime = now();
1886
1887 Budget newBudget;
1888 nsecs_t dispatchingTimeout;
1889 sp<InputChannel> pausedChannel = NULL;
1890 jobject tokenObj = NULL;
1891 if (mFrozen) {
1892 newBudget = SYSTEM;
1893 dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
1894 mFrozen = false;
1895 } else if (mPausedWindow) {
1896 newBudget = APPLICATION;
1897 dispatchingTimeout = mPausedWindow->dispatchingTimeout;
1898 pausedChannel = mPausedWindow->inputChannel;
1899 mPausedWindow = NULL;
1900 } else if (inputManager->mFocusedApplication) {
1901 newBudget = APPLICATION;
1902 dispatchingTimeout = inputManager->mFocusedApplication->dispatchingTimeout;
1903 tokenObj = jniEnv()->NewLocalRef(inputManager->mFocusedApplication->tokenObjWeak);
1904 } else {
1905 newBudget = APPLICATION;
1906 dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
1907 }
1908
1909 if (mBudget != newBudget) {
1910 mBudget = newBudget;
1911 mStartTime = currentTime;
1912 }
1913
1914 bool result = false;
1915 nsecs_t timeoutRemaining = mStartTime + dispatchingTimeout - currentTime;
1916 if (timeoutRemaining > 0
1917 && inputManager->mDispatchStateChanged.waitRelative(inputManager->mDispatchLock,
1918 timeoutRemaining) == OK) {
1919 result = true;
1920 } else {
1921 if (pausedChannel != NULL || tokenObj != NULL) {
1922 bool resumed;
1923 nsecs_t newTimeout = 0;
1924
1925 inputManager->mDispatchLock.unlock(); // release lock
1926 if (pausedChannel != NULL) {
1927 resumed = inputManager->notifyInputChannelANR(pausedChannel, /*out*/ newTimeout);
1928 } else {
1929 resumed = inputManager->notifyANR(tokenObj, /*out*/ newTimeout);
1930 }
1931 inputManager->mDispatchLock.lock(); // re-acquire lock
1932
1933 if (resumed) {
1934 mStartTime = now() - dispatchingTimeout + newTimeout;
1935 result = true;
1936 }
1937 }
1938 }
1939
1940 if (tokenObj) {
1941 jniEnv()->DeleteLocalRef(tokenObj);
1942 }
1943
1944 return result;
1945}
1946
1947nsecs_t NativeInputManager::ANRTimer::getTimeSpentWaitingForApplication() const {
1948 return mBudget == APPLICATION ? now() - mStartTime : 0;
1949}
Jeff Brown9c3cda02010-06-15 01:31:58 -07001950
1951// ----------------------------------------------------------------------------
1952
1953static sp<NativeInputManager> gNativeInputManager;
1954
Jeff Brown46b9ac02010-04-22 18:58:52 -07001955static bool checkInputManagerUnitialized(JNIEnv* env) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001956 if (gNativeInputManager == NULL) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001957 LOGE("Input manager not initialized.");
1958 jniThrowRuntimeException(env, "Input manager not initialized.");
1959 return true;
1960 }
1961 return false;
1962}
1963
1964static void android_server_InputManager_nativeInit(JNIEnv* env, jclass clazz,
1965 jobject callbacks) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001966 if (gNativeInputManager == NULL) {
1967 gNativeInputManager = new NativeInputManager(callbacks);
1968 } else {
1969 LOGE("Input manager already initialized.");
1970 jniThrowRuntimeException(env, "Input manager already initialized.");
Jeff Brown46b9ac02010-04-22 18:58:52 -07001971 }
1972}
1973
1974static void android_server_InputManager_nativeStart(JNIEnv* env, jclass clazz) {
1975 if (checkInputManagerUnitialized(env)) {
1976 return;
1977 }
1978
Jeff Brown9c3cda02010-06-15 01:31:58 -07001979 status_t result = gNativeInputManager->getInputManager()->start();
Jeff Brown46b9ac02010-04-22 18:58:52 -07001980 if (result) {
1981 jniThrowRuntimeException(env, "Input manager could not be started.");
1982 }
1983}
1984
1985static void android_server_InputManager_nativeSetDisplaySize(JNIEnv* env, jclass clazz,
1986 jint displayId, jint width, jint height) {
1987 if (checkInputManagerUnitialized(env)) {
1988 return;
1989 }
1990
1991 // XXX we could get this from the SurfaceFlinger directly instead of requiring it
1992 // to be passed in like this, not sure which is better but leaving it like this
1993 // keeps the window manager in direct control of when display transitions propagate down
1994 // to the input dispatcher
Jeff Brown9c3cda02010-06-15 01:31:58 -07001995 gNativeInputManager->setDisplaySize(displayId, width, height);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001996}
1997
1998static void android_server_InputManager_nativeSetDisplayOrientation(JNIEnv* env, jclass clazz,
1999 jint displayId, jint orientation) {
2000 if (checkInputManagerUnitialized(env)) {
2001 return;
2002 }
2003
Jeff Brown9c3cda02010-06-15 01:31:58 -07002004 gNativeInputManager->setDisplayOrientation(displayId, orientation);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002005}
2006
2007static jint android_server_InputManager_nativeGetScanCodeState(JNIEnv* env, jclass clazz,
Jeff Brown6d0fec22010-07-23 21:28:06 -07002008 jint deviceId, jint sourceMask, jint scanCode) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002009 if (checkInputManagerUnitialized(env)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002010 return AKEY_STATE_UNKNOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002011 }
2012
Jeff Brown9c3cda02010-06-15 01:31:58 -07002013 return gNativeInputManager->getInputManager()->getScanCodeState(
Jeff Brown6d0fec22010-07-23 21:28:06 -07002014 deviceId, uint32_t(sourceMask), scanCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002015}
2016
2017static jint android_server_InputManager_nativeGetKeyCodeState(JNIEnv* env, jclass clazz,
Jeff Brown6d0fec22010-07-23 21:28:06 -07002018 jint deviceId, jint sourceMask, jint keyCode) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002019 if (checkInputManagerUnitialized(env)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002020 return AKEY_STATE_UNKNOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002021 }
2022
Jeff Brown9c3cda02010-06-15 01:31:58 -07002023 return gNativeInputManager->getInputManager()->getKeyCodeState(
Jeff Brown6d0fec22010-07-23 21:28:06 -07002024 deviceId, uint32_t(sourceMask), keyCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002025}
2026
2027static jint android_server_InputManager_nativeGetSwitchState(JNIEnv* env, jclass clazz,
Jeff Brown6d0fec22010-07-23 21:28:06 -07002028 jint deviceId, jint sourceMask, jint sw) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002029 if (checkInputManagerUnitialized(env)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002030 return AKEY_STATE_UNKNOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002031 }
2032
Jeff Brown6d0fec22010-07-23 21:28:06 -07002033 return gNativeInputManager->getInputManager()->getSwitchState(
2034 deviceId, uint32_t(sourceMask), sw);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002035}
2036
2037static jboolean android_server_InputManager_nativeHasKeys(JNIEnv* env, jclass clazz,
Jeff Brown6d0fec22010-07-23 21:28:06 -07002038 jint deviceId, jint sourceMask, jintArray keyCodes, jbooleanArray outFlags) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002039 if (checkInputManagerUnitialized(env)) {
2040 return JNI_FALSE;
2041 }
2042
2043 int32_t* codes = env->GetIntArrayElements(keyCodes, NULL);
2044 uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL);
2045 jsize numCodes = env->GetArrayLength(keyCodes);
2046 jboolean result;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002047 if (numCodes == env->GetArrayLength(keyCodes)) {
2048 result = gNativeInputManager->getInputManager()->hasKeys(
2049 deviceId, uint32_t(sourceMask), numCodes, codes, flags);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002050 } else {
2051 result = JNI_FALSE;
2052 }
2053
2054 env->ReleaseBooleanArrayElements(outFlags, flags, 0);
2055 env->ReleaseIntArrayElements(keyCodes, codes, 0);
2056 return result;
2057}
2058
2059static void throwInputChannelNotInitialized(JNIEnv* env) {
2060 jniThrowException(env, "java/lang/IllegalStateException",
2061 "inputChannel is not initialized");
2062}
2063
2064static void android_server_InputManager_handleInputChannelDisposed(JNIEnv* env,
2065 jobject inputChannelObj, const sp<InputChannel>& inputChannel, void* data) {
2066 LOGW("Input channel object '%s' was disposed without first being unregistered with "
2067 "the input manager!", inputChannel->getName().string());
2068
Jeff Brown9c3cda02010-06-15 01:31:58 -07002069 if (gNativeInputManager != NULL) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07002070 gNativeInputManager->unregisterInputChannel(env, inputChannel);
Jeff Brown9c3cda02010-06-15 01:31:58 -07002071 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002072}
2073
2074static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
Jeff Browna41ca772010-08-11 14:46:32 -07002075 jobject inputChannelObj, jboolean monitor) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002076 if (checkInputManagerUnitialized(env)) {
2077 return;
2078 }
2079
2080 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
2081 inputChannelObj);
2082 if (inputChannel == NULL) {
2083 throwInputChannelNotInitialized(env);
2084 return;
2085 }
2086
Jeff Brown7fbdc842010-06-17 20:52:56 -07002087
2088 status_t status = gNativeInputManager->registerInputChannel(
Jeff Browna41ca772010-08-11 14:46:32 -07002089 env, inputChannel, inputChannelObj, monitor);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002090 if (status) {
2091 jniThrowRuntimeException(env, "Failed to register input channel. "
2092 "Check logs for details.");
2093 return;
2094 }
2095
Jeff Browna41ca772010-08-11 14:46:32 -07002096 if (! monitor) {
2097 android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
2098 android_server_InputManager_handleInputChannelDisposed, NULL);
2099 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002100}
2101
2102static void android_server_InputManager_nativeUnregisterInputChannel(JNIEnv* env, jclass clazz,
2103 jobject inputChannelObj) {
2104 if (checkInputManagerUnitialized(env)) {
2105 return;
2106 }
2107
2108 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
2109 inputChannelObj);
2110 if (inputChannel == NULL) {
2111 throwInputChannelNotInitialized(env);
2112 return;
2113 }
2114
2115 android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL);
2116
Jeff Brown7fbdc842010-06-17 20:52:56 -07002117 status_t status = gNativeInputManager->unregisterInputChannel(env, inputChannel);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002118 if (status) {
2119 jniThrowRuntimeException(env, "Failed to unregister input channel. "
2120 "Check logs for details.");
2121 }
2122}
2123
Jeff Brown6ec402b2010-07-28 15:48:59 -07002124static jint android_server_InputManager_nativeInjectInputEvent(JNIEnv* env, jclass clazz,
2125 jobject inputEventObj, jint injectorPid, jint injectorUid,
2126 jint syncMode, jint timeoutMillis) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07002127 if (checkInputManagerUnitialized(env)) {
2128 return INPUT_EVENT_INJECTION_FAILED;
2129 }
2130
Jeff Brown6ec402b2010-07-28 15:48:59 -07002131 if (env->IsInstanceOf(inputEventObj, gKeyEventClassInfo.clazz)) {
2132 KeyEvent keyEvent;
2133 android_view_KeyEvent_toNative(env, inputEventObj, & keyEvent);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002134
Jeff Brown6ec402b2010-07-28 15:48:59 -07002135 return gNativeInputManager->getInputManager()->injectInputEvent(& keyEvent,
2136 injectorPid, injectorUid, syncMode, timeoutMillis);
2137 } else if (env->IsInstanceOf(inputEventObj, gMotionEventClassInfo.clazz)) {
2138 MotionEvent motionEvent;
2139 android_view_MotionEvent_toNative(env, inputEventObj, & motionEvent);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002140
Jeff Brown6ec402b2010-07-28 15:48:59 -07002141 return gNativeInputManager->getInputManager()->injectInputEvent(& motionEvent,
2142 injectorPid, injectorUid, syncMode, timeoutMillis);
2143 } else {
2144 jniThrowRuntimeException(env, "Invalid input event type.");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002145 return INPUT_EVENT_INJECTION_FAILED;
2146 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07002147}
2148
Jeff Brown349703e2010-06-22 01:27:15 -07002149static void android_server_InputManager_nativeSetInputWindows(JNIEnv* env, jclass clazz,
2150 jobjectArray windowObjArray) {
2151 if (checkInputManagerUnitialized(env)) {
2152 return;
2153 }
2154
2155 gNativeInputManager->setInputWindows(env, windowObjArray);
2156}
2157
2158static void android_server_InputManager_nativeSetFocusedApplication(JNIEnv* env, jclass clazz,
2159 jobject applicationObj) {
2160 if (checkInputManagerUnitialized(env)) {
2161 return;
2162 }
2163
2164 gNativeInputManager->setFocusedApplication(env, applicationObj);
2165}
2166
2167static void android_server_InputManager_nativeSetInputDispatchMode(JNIEnv* env,
2168 jclass clazz, jboolean enabled, jboolean frozen) {
2169 if (checkInputManagerUnitialized(env)) {
2170 return;
2171 }
2172
2173 gNativeInputManager->setInputDispatchMode(enabled, frozen);
2174}
2175
2176static void android_server_InputManager_nativePreemptInputDispatch(JNIEnv* env,
2177 jclass clazz) {
2178 if (checkInputManagerUnitialized(env)) {
2179 return;
2180 }
2181
2182 gNativeInputManager->preemptInputDispatch();
2183}
2184
Jeff Browne33348b2010-07-15 23:54:05 -07002185static jstring android_server_InputManager_nativeDump(JNIEnv* env, jclass clazz) {
2186 if (checkInputManagerUnitialized(env)) {
2187 return NULL;
2188 }
2189
2190 String8 dump(gNativeInputManager->dump());
2191 return env->NewStringUTF(dump.string());
2192}
2193
Jeff Brown9c3cda02010-06-15 01:31:58 -07002194// ----------------------------------------------------------------------------
2195
Jeff Brown46b9ac02010-04-22 18:58:52 -07002196static JNINativeMethod gInputManagerMethods[] = {
2197 /* name, signature, funcPtr */
2198 { "nativeInit", "(Lcom/android/server/InputManager$Callbacks;)V",
2199 (void*) android_server_InputManager_nativeInit },
2200 { "nativeStart", "()V",
2201 (void*) android_server_InputManager_nativeStart },
2202 { "nativeSetDisplaySize", "(III)V",
2203 (void*) android_server_InputManager_nativeSetDisplaySize },
2204 { "nativeSetDisplayOrientation", "(II)V",
2205 (void*) android_server_InputManager_nativeSetDisplayOrientation },
2206 { "nativeGetScanCodeState", "(III)I",
2207 (void*) android_server_InputManager_nativeGetScanCodeState },
2208 { "nativeGetKeyCodeState", "(III)I",
2209 (void*) android_server_InputManager_nativeGetKeyCodeState },
2210 { "nativeGetSwitchState", "(III)I",
2211 (void*) android_server_InputManager_nativeGetSwitchState },
Jeff Brown6d0fec22010-07-23 21:28:06 -07002212 { "nativeHasKeys", "(II[I[Z)Z",
Jeff Brown46b9ac02010-04-22 18:58:52 -07002213 (void*) android_server_InputManager_nativeHasKeys },
Jeff Browna41ca772010-08-11 14:46:32 -07002214 { "nativeRegisterInputChannel", "(Landroid/view/InputChannel;Z)V",
Jeff Brown46b9ac02010-04-22 18:58:52 -07002215 (void*) android_server_InputManager_nativeRegisterInputChannel },
2216 { "nativeUnregisterInputChannel", "(Landroid/view/InputChannel;)V",
Jeff Brown7fbdc842010-06-17 20:52:56 -07002217 (void*) android_server_InputManager_nativeUnregisterInputChannel },
Jeff Brown6ec402b2010-07-28 15:48:59 -07002218 { "nativeInjectInputEvent", "(Landroid/view/InputEvent;IIII)I",
2219 (void*) android_server_InputManager_nativeInjectInputEvent },
Jeff Brown349703e2010-06-22 01:27:15 -07002220 { "nativeSetInputWindows", "([Lcom/android/server/InputWindow;)V",
2221 (void*) android_server_InputManager_nativeSetInputWindows },
2222 { "nativeSetFocusedApplication", "(Lcom/android/server/InputApplication;)V",
2223 (void*) android_server_InputManager_nativeSetFocusedApplication },
2224 { "nativeSetInputDispatchMode", "(ZZ)V",
2225 (void*) android_server_InputManager_nativeSetInputDispatchMode },
2226 { "nativePreemptInputDispatch", "()V",
Jeff Browne33348b2010-07-15 23:54:05 -07002227 (void*) android_server_InputManager_nativePreemptInputDispatch },
2228 { "nativeDump", "()Ljava/lang/String;",
2229 (void*) android_server_InputManager_nativeDump },
Jeff Brown46b9ac02010-04-22 18:58:52 -07002230};
2231
2232#define FIND_CLASS(var, className) \
2233 var = env->FindClass(className); \
2234 LOG_FATAL_IF(! var, "Unable to find class " className); \
2235 var = jclass(env->NewGlobalRef(var));
2236
2237#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
2238 var = env->GetMethodID(clazz, methodName, methodDescriptor); \
2239 LOG_FATAL_IF(! var, "Unable to find method " methodName);
2240
2241#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
2242 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
2243 LOG_FATAL_IF(! var, "Unable to find field " fieldName);
2244
2245int register_android_server_InputManager(JNIEnv* env) {
2246 int res = jniRegisterNativeMethods(env, "com/android/server/InputManager",
2247 gInputManagerMethods, NELEM(gInputManagerMethods));
2248 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
2249
Jeff Brown9c3cda02010-06-15 01:31:58 -07002250 // Callbacks
Jeff Brown46b9ac02010-04-22 18:58:52 -07002251
2252 FIND_CLASS(gCallbacksClassInfo.clazz, "com/android/server/InputManager$Callbacks");
2253
Jeff Brown46b9ac02010-04-22 18:58:52 -07002254 GET_METHOD_ID(gCallbacksClassInfo.notifyConfigurationChanged, gCallbacksClassInfo.clazz,
2255 "notifyConfigurationChanged", "(JIII)V");
2256
2257 GET_METHOD_ID(gCallbacksClassInfo.notifyLidSwitchChanged, gCallbacksClassInfo.clazz,
2258 "notifyLidSwitchChanged", "(JZ)V");
2259
Jeff Brown7fbdc842010-06-17 20:52:56 -07002260 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelBroken, gCallbacksClassInfo.clazz,
2261 "notifyInputChannelBroken", "(Landroid/view/InputChannel;)V");
2262
2263 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelANR, gCallbacksClassInfo.clazz,
2264 "notifyInputChannelANR", "(Landroid/view/InputChannel;)J");
2265
2266 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelRecoveredFromANR, gCallbacksClassInfo.clazz,
2267 "notifyInputChannelRecoveredFromANR", "(Landroid/view/InputChannel;)V");
2268
Jeff Brown349703e2010-06-22 01:27:15 -07002269 GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
2270 "notifyANR", "(Ljava/lang/Object;)J");
2271
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002272 GET_METHOD_ID(gCallbacksClassInfo.virtualKeyDownFeedback, gCallbacksClassInfo.clazz,
2273 "virtualKeyDownFeedback", "()V");
Jeff Brown46b9ac02010-04-22 18:58:52 -07002274
Jeff Brown349703e2010-06-22 01:27:15 -07002275 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002276 "interceptKeyBeforeQueueing", "(JIZIZ)I");
Jeff Brown349703e2010-06-22 01:27:15 -07002277
2278 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002279 "interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIIIII)Z");
Jeff Brown349703e2010-06-22 01:27:15 -07002280
2281 GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,
2282 "checkInjectEventsPermission", "(II)Z");
Jeff Brown46b9ac02010-04-22 18:58:52 -07002283
Jeff Brown46b9ac02010-04-22 18:58:52 -07002284 GET_METHOD_ID(gCallbacksClassInfo.notifyAppSwitchComing, gCallbacksClassInfo.clazz,
2285 "notifyAppSwitchComing", "()V");
2286
2287 GET_METHOD_ID(gCallbacksClassInfo.filterTouchEvents, gCallbacksClassInfo.clazz,
2288 "filterTouchEvents", "()Z");
2289
2290 GET_METHOD_ID(gCallbacksClassInfo.filterJumpyTouchEvents, gCallbacksClassInfo.clazz,
2291 "filterJumpyTouchEvents", "()Z");
2292
2293 GET_METHOD_ID(gCallbacksClassInfo.getVirtualKeyDefinitions, gCallbacksClassInfo.clazz,
2294 "getVirtualKeyDefinitions",
2295 "(Ljava/lang/String;)[Lcom/android/server/InputManager$VirtualKeyDefinition;");
2296
2297 GET_METHOD_ID(gCallbacksClassInfo.getExcludedDeviceNames, gCallbacksClassInfo.clazz,
2298 "getExcludedDeviceNames", "()[Ljava/lang/String;");
2299
Jeff Brown46b9ac02010-04-22 18:58:52 -07002300 // VirtualKeyDefinition
2301
2302 FIND_CLASS(gVirtualKeyDefinitionClassInfo.clazz,
2303 "com/android/server/InputManager$VirtualKeyDefinition");
2304
2305 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.scanCode, gVirtualKeyDefinitionClassInfo.clazz,
2306 "scanCode", "I");
2307
2308 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerX, gVirtualKeyDefinitionClassInfo.clazz,
2309 "centerX", "I");
2310
2311 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerY, gVirtualKeyDefinitionClassInfo.clazz,
2312 "centerY", "I");
2313
2314 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.width, gVirtualKeyDefinitionClassInfo.clazz,
2315 "width", "I");
2316
2317 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.height, gVirtualKeyDefinitionClassInfo.clazz,
2318 "height", "I");
2319
Jeff Brown349703e2010-06-22 01:27:15 -07002320 // InputWindow
Jeff Brown7fbdc842010-06-17 20:52:56 -07002321
Jeff Brown349703e2010-06-22 01:27:15 -07002322 FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002323
Jeff Brown349703e2010-06-22 01:27:15 -07002324 GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
2325 "inputChannel", "Landroid/view/InputChannel;");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002326
Jeff Brown349703e2010-06-22 01:27:15 -07002327 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
2328 "layoutParamsFlags", "I");
2329
2330 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
2331 "layoutParamsType", "I");
2332
2333 GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
2334 "dispatchingTimeoutNanos", "J");
2335
2336 GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
2337 "frameLeft", "I");
2338
2339 GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
2340 "frameTop", "I");
2341
2342 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
2343 "touchableAreaLeft", "I");
2344
2345 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
2346 "touchableAreaTop", "I");
2347
2348 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
2349 "touchableAreaRight", "I");
2350
2351 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
2352 "touchableAreaBottom", "I");
2353
2354 GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
2355 "visible", "Z");
2356
2357 GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
2358 "hasFocus", "Z");
2359
2360 GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
2361 "hasWallpaper", "Z");
2362
2363 GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
2364 "paused", "Z");
2365
2366 GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
2367 "ownerPid", "I");
2368
2369 GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
2370 "ownerUid", "I");
2371
2372 // InputApplication
2373
2374 FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication");
2375
2376 GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
2377 "name", "Ljava/lang/String;");
2378
2379 GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
2380 gInputApplicationClassInfo.clazz,
2381 "dispatchingTimeoutNanos", "J");
2382
2383 GET_FIELD_ID(gInputApplicationClassInfo.token, gInputApplicationClassInfo.clazz,
2384 "token", "Ljava/lang/Object;");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002385
Jeff Brown6ec402b2010-07-28 15:48:59 -07002386 // KeyEvent
2387
2388 FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
2389
2390 // MotionEVent
2391
2392 FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent");
2393
Jeff Brown46b9ac02010-04-22 18:58:52 -07002394 return 0;
2395}
2396
Jeff Brown46b9ac02010-04-22 18:58:52 -07002397} /* namespace android */