blob: a237ee94bfb3d3594ecf8587b6dd74df057fb681 [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;
Jeff Brown8d608662010-08-30 03:02:23 -0700141 jmethodID getInputDeviceCalibration;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700142 jmethodID getExcludedDeviceNames;
Jeff Brownae9fc032010-08-18 15:51:08 -0700143 jmethodID getMaxEventsPerSecond;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700144} gCallbacksClassInfo;
145
146static struct {
147 jclass clazz;
148
149 jfieldID scanCode;
150 jfieldID centerX;
151 jfieldID centerY;
152 jfieldID width;
153 jfieldID height;
154} gVirtualKeyDefinitionClassInfo;
155
Jeff Brown7fbdc842010-06-17 20:52:56 -0700156static struct {
157 jclass clazz;
158
Jeff Brown8d608662010-08-30 03:02:23 -0700159 jfieldID keys;
160 jfieldID values;
161} gInputDeviceCalibrationClassInfo;
162
163static struct {
164 jclass clazz;
165
Jeff Brown349703e2010-06-22 01:27:15 -0700166 jfieldID inputChannel;
167 jfieldID layoutParamsFlags;
168 jfieldID layoutParamsType;
169 jfieldID dispatchingTimeoutNanos;
170 jfieldID frameLeft;
171 jfieldID frameTop;
172 jfieldID touchableAreaLeft;
173 jfieldID touchableAreaTop;
174 jfieldID touchableAreaRight;
175 jfieldID touchableAreaBottom;
176 jfieldID visible;
177 jfieldID hasFocus;
178 jfieldID hasWallpaper;
179 jfieldID paused;
180 jfieldID ownerPid;
181 jfieldID ownerUid;
182} gInputWindowClassInfo;
183
184static struct {
185 jclass clazz;
186
187 jfieldID name;
188 jfieldID dispatchingTimeoutNanos;
189 jfieldID token;
190} gInputApplicationClassInfo;
191
Jeff Brown6ec402b2010-07-28 15:48:59 -0700192static struct {
193 jclass clazz;
194} gKeyEventClassInfo;
195
196static struct {
197 jclass clazz;
198} gMotionEventClassInfo;
199
Jeff Brown8d608662010-08-30 03:02:23 -0700200static struct {
201 jclass clazz;
202
203 jmethodID ctor;
204 jmethodID addMotionRange;
205
206 jfieldID mId;
207 jfieldID mName;
208 jfieldID mSources;
209 jfieldID mKeyboardType;
210 jfieldID mMotionRanges;
211} gInputDeviceClassInfo;
212
Jeff Brown349703e2010-06-22 01:27:15 -0700213// ----------------------------------------------------------------------------
214
215static inline nsecs_t now() {
216 return systemTime(SYSTEM_TIME_MONOTONIC);
217}
Jeff Brown7fbdc842010-06-17 20:52:56 -0700218
Jeff Brown9c3cda02010-06-15 01:31:58 -0700219// ----------------------------------------------------------------------------
220
221class NativeInputManager : public virtual RefBase,
222 public virtual InputReaderPolicyInterface,
223 public virtual InputDispatcherPolicyInterface {
224protected:
225 virtual ~NativeInputManager();
226
227public:
228 NativeInputManager(jobject callbacksObj);
229
230 inline sp<InputManager> getInputManager() const { return mInputManager; }
231
Jeff Browne33348b2010-07-15 23:54:05 -0700232 String8 dump();
233
Jeff Brown9c3cda02010-06-15 01:31:58 -0700234 void setDisplaySize(int32_t displayId, int32_t width, int32_t height);
235 void setDisplayOrientation(int32_t displayId, int32_t orientation);
236
Jeff Brown7fbdc842010-06-17 20:52:56 -0700237 status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
Jeff Browna41ca772010-08-11 14:46:32 -0700238 jweak inputChannelObjWeak, bool monitor);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700239 status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
240
Jeff Brown349703e2010-06-22 01:27:15 -0700241 void setInputWindows(JNIEnv* env, jobjectArray windowObjArray);
242 void setFocusedApplication(JNIEnv* env, jobject applicationObj);
243 void setInputDispatchMode(bool enabled, bool frozen);
244 void preemptInputDispatch();
245
Jeff Brown9c3cda02010-06-15 01:31:58 -0700246 /* --- InputReaderPolicyInterface implementation --- */
247
248 virtual bool getDisplayInfo(int32_t displayId,
249 int32_t* width, int32_t* height, int32_t* orientation);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700250 virtual void virtualKeyDownFeedback();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700251 virtual int32_t interceptKey(nsecs_t when, int32_t deviceId,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700252 bool down, int32_t keyCode, int32_t scanCode, uint32_t& policyFlags);
253 virtual int32_t interceptSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
254 uint32_t& policyFlags);
255 virtual int32_t interceptGeneric(nsecs_t when, uint32_t& policyFlags);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700256 virtual bool filterTouchEvents();
257 virtual bool filterJumpyTouchEvents();
258 virtual void getVirtualKeyDefinitions(const String8& deviceName,
Jeff Brown8d608662010-08-30 03:02:23 -0700259 Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions);
260 virtual void getInputDeviceCalibration(const String8& deviceName,
261 InputDeviceCalibration& outCalibration);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700262 virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames);
263
264 /* --- InputDispatcherPolicyInterface implementation --- */
265
266 virtual void notifyConfigurationChanged(nsecs_t when);
267 virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700268 virtual bool notifyInputChannelANR(const sp<InputChannel>& inputChannel,
269 nsecs_t& outNewTimeout);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700270 virtual void notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel);
271 virtual nsecs_t getKeyRepeatTimeout();
Jeff Brown349703e2010-06-22 01:27:15 -0700272 virtual int32_t waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700273 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brown349703e2010-06-22 01:27:15 -0700274 virtual int32_t waitForMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700275 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brownae9fc032010-08-18 15:51:08 -0700276 virtual int32_t getMaxEventsPerSecond();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700277
278private:
Jeff Brown349703e2010-06-22 01:27:15 -0700279 struct InputWindow {
280 sp<InputChannel> inputChannel;
281 int32_t layoutParamsFlags;
282 int32_t layoutParamsType;
283 nsecs_t dispatchingTimeout;
284 int32_t frameLeft;
285 int32_t frameTop;
286 int32_t touchableAreaLeft;
287 int32_t touchableAreaTop;
288 int32_t touchableAreaRight;
289 int32_t touchableAreaBottom;
290 bool visible;
291 bool hasFocus;
292 bool hasWallpaper;
293 bool paused;
294 int32_t ownerPid;
295 int32_t ownerUid;
296
297 inline bool touchableAreaContainsPoint(int32_t x, int32_t y) {
298 return x >= touchableAreaLeft && x <= touchableAreaRight
299 && y >= touchableAreaTop && y <= touchableAreaBottom;
300 }
301 };
302
303 struct InputApplication {
304 String8 name;
305 nsecs_t dispatchingTimeout;
306 jweak tokenObjWeak;
307 };
308
309 class ANRTimer {
310 enum Budget {
311 SYSTEM = 0,
312 APPLICATION = 1
313 };
314
315 Budget mBudget;
316 nsecs_t mStartTime;
317 bool mFrozen;
318 InputWindow* mPausedWindow;
319
320 public:
321 ANRTimer();
322
323 void dispatchFrozenBySystem();
324 void dispatchPausedByApplication(InputWindow* pausedWindow);
325 bool waitForDispatchStateChangeLd(NativeInputManager* inputManager);
326
327 nsecs_t getTimeSpentWaitingForApplication() const;
328 };
329
Jeff Brown9c3cda02010-06-15 01:31:58 -0700330 sp<InputManager> mInputManager;
331
332 jobject mCallbacksObj;
333
334 // Cached filtering policies.
335 int32_t mFilterTouchEvents;
336 int32_t mFilterJumpyTouchEvents;
337
Jeff Brownae9fc032010-08-18 15:51:08 -0700338 // Cached throttling policy.
339 int32_t mMaxEventsPerSecond;
340
Jeff Brown9c3cda02010-06-15 01:31:58 -0700341 // Cached display state. (lock mDisplayLock)
342 Mutex mDisplayLock;
343 int32_t mDisplayWidth, mDisplayHeight;
344 int32_t mDisplayOrientation;
345
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700346 // Power manager interactions.
Jeff Brown9c3cda02010-06-15 01:31:58 -0700347 bool isScreenOn();
348 bool isScreenBright();
349
Jeff Brown2cbecea2010-08-17 15:59:26 -0700350 // Weak references to all currently registered input channels by connection pointer.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700351 Mutex mInputChannelRegistryLock;
Jeff Brown2cbecea2010-08-17 15:59:26 -0700352 KeyedVector<InputChannel*, jweak> mInputChannelObjWeakTable;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700353
354 jobject getInputChannelObjLocal(JNIEnv* env, const sp<InputChannel>& inputChannel);
355
Jeff Brown349703e2010-06-22 01:27:15 -0700356 // Input target and focus tracking. (lock mDispatchLock)
357 Mutex mDispatchLock;
358 Condition mDispatchStateChanged;
359
360 bool mDispatchEnabled;
361 bool mDispatchFrozen;
362 bool mWindowsReady;
363 Vector<InputWindow> mWindows;
364 Vector<InputWindow*> mWallpaperWindows;
Jeff Browna41ca772010-08-11 14:46:32 -0700365 Vector<sp<InputChannel> > mMonitoringChannels;
Jeff Brown349703e2010-06-22 01:27:15 -0700366
367 // Focus tracking for keys, trackball, etc.
368 InputWindow* mFocusedWindow;
369
370 // Focus tracking for touch.
371 bool mTouchDown;
372 InputWindow* mTouchedWindow; // primary target for current down
373 Vector<InputWindow*> mTouchedWallpaperWindows; // wallpaper targets
374
375 Vector<InputWindow*> mTempTouchedOutsideWindows; // temporary outside touch targets
376 Vector<sp<InputChannel> > mTempTouchedWallpaperChannels; // temporary wallpaper targets
377
378 // Focused application.
379 InputApplication* mFocusedApplication;
380 InputApplication mFocusedApplicationStorage; // preallocated storage for mFocusedApplication
381
Jeff Brown6d0fec22010-07-23 21:28:06 -0700382 void dumpDeviceInfo(String8& dump);
Jeff Browne33348b2010-07-15 23:54:05 -0700383 void dumpDispatchStateLd(String8& dump);
384 void logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -0700385
386 bool notifyANR(jobject tokenObj, nsecs_t& outNewTimeout);
387 void releaseFocusedApplicationLd(JNIEnv* env);
388
389 int32_t waitForFocusedWindowLd(uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
390 Vector<InputTarget>& outTargets, InputWindow*& outFocusedWindow);
391 int32_t waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
392 int32_t injectorPid, int32_t injectorUid,
393 Vector<InputTarget>& outTargets, InputWindow*& outTouchedWindow);
394
395 void releaseTouchedWindowLd();
396
Jeff Brownc5ed5912010-07-14 18:48:53 -0700397 int32_t waitForNonTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown349703e2010-06-22 01:27:15 -0700398 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700399 int32_t waitForTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown349703e2010-06-22 01:27:15 -0700400 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
401
Jeff Brownd0097872010-06-30 14:41:59 -0700402 bool interceptKeyBeforeDispatching(const InputTarget& target,
403 const KeyEvent* keyEvent, uint32_t policyFlags);
404
Jeff Brown349703e2010-06-22 01:27:15 -0700405 void pokeUserActivityIfNeeded(int32_t windowType, int32_t eventType);
406 void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
407 bool checkInjectionPermission(const InputWindow* window,
408 int32_t injectorPid, int32_t injectorUid);
409
410 static bool populateWindow(JNIEnv* env, jobject windowObj, InputWindow& outWindow);
411 static void addTarget(const InputWindow* window, int32_t targetFlags,
412 nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets);
413
Jeff Browna41ca772010-08-11 14:46:32 -0700414 void registerMonitoringChannel(const sp<InputChannel>& inputChannel);
415 void unregisterMonitoringChannel(const sp<InputChannel>& inputChannel);
416 void addMonitoringTargetsLd(Vector<InputTarget>& outTargets);
417
Jeff Brown9c3cda02010-06-15 01:31:58 -0700418 static inline JNIEnv* jniEnv() {
419 return AndroidRuntime::getJNIEnv();
420 }
421
422 static bool isAppSwitchKey(int32_t keyCode);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700423 static bool isPolicyKey(int32_t keyCode, bool isScreenOn);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700424 static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700425};
426
427// ----------------------------------------------------------------------------
428
429NativeInputManager::NativeInputManager(jobject callbacksObj) :
430 mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1),
Jeff Brownae9fc032010-08-18 15:51:08 -0700431 mMaxEventsPerSecond(-1),
Jeff Brown0b72e822010-06-29 16:52:21 -0700432 mDisplayWidth(-1), mDisplayHeight(-1), mDisplayOrientation(ROTATION_0),
Jeff Brown349703e2010-06-22 01:27:15 -0700433 mDispatchEnabled(true), mDispatchFrozen(false), mWindowsReady(true),
434 mFocusedWindow(NULL), mTouchDown(false), mTouchedWindow(NULL),
435 mFocusedApplication(NULL) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700436 JNIEnv* env = jniEnv();
437
438 mCallbacksObj = env->NewGlobalRef(callbacksObj);
439
440 sp<EventHub> eventHub = new EventHub();
441 mInputManager = new InputManager(eventHub, this, this);
442}
443
444NativeInputManager::~NativeInputManager() {
445 JNIEnv* env = jniEnv();
446
447 env->DeleteGlobalRef(mCallbacksObj);
Jeff Brown349703e2010-06-22 01:27:15 -0700448
449 releaseFocusedApplicationLd(env);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700450}
451
Jeff Browne33348b2010-07-15 23:54:05 -0700452String8 NativeInputManager::dump() {
453 String8 dump;
Jeff Brown00ba8842010-07-16 15:01:56 -0700454 { // acquire lock
455 AutoMutex _l(mDisplayLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700456 dump.append("Native Input Dispatcher State:\n");
Jeff Brown00ba8842010-07-16 15:01:56 -0700457 dumpDispatchStateLd(dump);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700458 dump.append("\n");
Jeff Brown00ba8842010-07-16 15:01:56 -0700459 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -0700460
461 dump.append("Input Devices:\n");
462 dumpDeviceInfo(dump);
463
Jeff Browne33348b2010-07-15 23:54:05 -0700464 return dump;
465}
466
Jeff Brown9c3cda02010-06-15 01:31:58 -0700467bool NativeInputManager::isAppSwitchKey(int32_t keyCode) {
Jeff Brownfd035822010-06-30 16:10:35 -0700468 return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700469}
470
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700471bool NativeInputManager::isPolicyKey(int32_t keyCode, bool isScreenOn) {
472 // Special keys that the WindowManagerPolicy might care about.
473 switch (keyCode) {
Jeff Brownfd035822010-06-30 16:10:35 -0700474 case AKEYCODE_VOLUME_UP:
475 case AKEYCODE_VOLUME_DOWN:
476 case AKEYCODE_ENDCALL:
477 case AKEYCODE_POWER:
478 case AKEYCODE_CALL:
479 case AKEYCODE_HOME:
480 case AKEYCODE_MENU:
481 case AKEYCODE_SEARCH:
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700482 // media keys
Jeff Brownfd035822010-06-30 16:10:35 -0700483 case AKEYCODE_HEADSETHOOK:
484 case AKEYCODE_MEDIA_PLAY_PAUSE:
485 case AKEYCODE_MEDIA_STOP:
486 case AKEYCODE_MEDIA_NEXT:
487 case AKEYCODE_MEDIA_PREVIOUS:
488 case AKEYCODE_MEDIA_REWIND:
489 case AKEYCODE_MEDIA_FAST_FORWARD:
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700490 return true;
491 default:
492 // We need to pass all keys to the policy in the following cases:
493 // - screen is off
494 // - keyguard is visible
495 // - policy is performing key chording
496 //return ! isScreenOn || keyguardVisible || chording;
497 return true; // XXX stubbed out for now
498 }
499}
500
Jeff Brown7fbdc842010-06-17 20:52:56 -0700501bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700502 if (env->ExceptionCheck()) {
503 LOGE("An exception was thrown by callback '%s'.", methodName);
504 LOGE_EX(env);
505 env->ExceptionClear();
506 return true;
507 }
508 return false;
509}
510
511void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height) {
512 if (displayId == 0) {
513 AutoMutex _l(mDisplayLock);
514
515 mDisplayWidth = width;
516 mDisplayHeight = height;
517 }
518}
519
520void NativeInputManager::setDisplayOrientation(int32_t displayId, int32_t orientation) {
521 if (displayId == 0) {
522 AutoMutex _l(mDisplayLock);
523
524 mDisplayOrientation = orientation;
525 }
526}
527
Jeff Brown7fbdc842010-06-17 20:52:56 -0700528status_t NativeInputManager::registerInputChannel(JNIEnv* env,
Jeff Browna41ca772010-08-11 14:46:32 -0700529 const sp<InputChannel>& inputChannel, jobject inputChannelObj, bool monitor) {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700530 jweak inputChannelObjWeak = env->NewWeakGlobalRef(inputChannelObj);
531 if (! inputChannelObjWeak) {
532 LOGE("Could not create weak reference for input channel.");
533 LOGE_EX(env);
534 return NO_MEMORY;
535 }
536
537 status_t status;
538 {
539 AutoMutex _l(mInputChannelRegistryLock);
540
Jeff Brown2cbecea2010-08-17 15:59:26 -0700541 ssize_t index = mInputChannelObjWeakTable.indexOfKey(inputChannel.get());
Jeff Brown7fbdc842010-06-17 20:52:56 -0700542 if (index >= 0) {
543 LOGE("Input channel object '%s' has already been registered",
544 inputChannel->getName().string());
545 status = INVALID_OPERATION;
546 goto DeleteWeakRef;
547 }
548
Jeff Brown2cbecea2010-08-17 15:59:26 -0700549 mInputChannelObjWeakTable.add(inputChannel.get(), inputChannelObjWeak);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700550 }
551
552 status = mInputManager->registerInputChannel(inputChannel);
553 if (! status) {
Jeff Browna41ca772010-08-11 14:46:32 -0700554 // Success.
555 if (monitor) {
556 registerMonitoringChannel(inputChannel);
557 }
Jeff Brown7fbdc842010-06-17 20:52:56 -0700558 return OK;
559 }
560
Jeff Browna41ca772010-08-11 14:46:32 -0700561 // Failed!
Jeff Brown7fbdc842010-06-17 20:52:56 -0700562 {
563 AutoMutex _l(mInputChannelRegistryLock);
Jeff Brown2cbecea2010-08-17 15:59:26 -0700564 mInputChannelObjWeakTable.removeItem(inputChannel.get());
Jeff Brown7fbdc842010-06-17 20:52:56 -0700565 }
566
567DeleteWeakRef:
568 env->DeleteWeakGlobalRef(inputChannelObjWeak);
569 return status;
570}
571
572status_t NativeInputManager::unregisterInputChannel(JNIEnv* env,
573 const sp<InputChannel>& inputChannel) {
574 jweak inputChannelObjWeak;
575 {
576 AutoMutex _l(mInputChannelRegistryLock);
577
Jeff Brown2cbecea2010-08-17 15:59:26 -0700578 ssize_t index = mInputChannelObjWeakTable.indexOfKey(inputChannel.get());
Jeff Brown7fbdc842010-06-17 20:52:56 -0700579 if (index < 0) {
580 LOGE("Input channel object '%s' is not currently registered",
581 inputChannel->getName().string());
582 return INVALID_OPERATION;
583 }
584
Jeff Brown2cbecea2010-08-17 15:59:26 -0700585 inputChannelObjWeak = mInputChannelObjWeakTable.valueAt(index);
586 mInputChannelObjWeakTable.removeItemsAt(index);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700587 }
588
589 env->DeleteWeakGlobalRef(inputChannelObjWeak);
590
Jeff Browna41ca772010-08-11 14:46:32 -0700591 unregisterMonitoringChannel(inputChannel);
592
Jeff Brown7fbdc842010-06-17 20:52:56 -0700593 return mInputManager->unregisterInputChannel(inputChannel);
594}
595
596jobject NativeInputManager::getInputChannelObjLocal(JNIEnv* env,
597 const sp<InputChannel>& inputChannel) {
598 {
599 AutoMutex _l(mInputChannelRegistryLock);
600
Jeff Brown2cbecea2010-08-17 15:59:26 -0700601 ssize_t index = mInputChannelObjWeakTable.indexOfKey(inputChannel.get());
Jeff Brown7fbdc842010-06-17 20:52:56 -0700602 if (index < 0) {
603 return NULL;
604 }
605
Jeff Brown2cbecea2010-08-17 15:59:26 -0700606 jweak inputChannelObjWeak = mInputChannelObjWeakTable.valueAt(index);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700607 return env->NewLocalRef(inputChannelObjWeak);
608 }
609}
610
Jeff Brown9c3cda02010-06-15 01:31:58 -0700611bool NativeInputManager::getDisplayInfo(int32_t displayId,
612 int32_t* width, int32_t* height, int32_t* orientation) {
613 bool result = false;
614 if (displayId == 0) {
615 AutoMutex _l(mDisplayLock);
616
617 if (mDisplayWidth > 0) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700618 if (width) {
619 *width = mDisplayWidth;
620 }
621 if (height) {
622 *height = mDisplayHeight;
623 }
624 if (orientation) {
625 *orientation = mDisplayOrientation;
626 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700627 result = true;
628 }
629 }
630 return result;
631}
632
633bool NativeInputManager::isScreenOn() {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700634 return android_server_PowerManagerService_isScreenOn();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700635}
636
637bool NativeInputManager::isScreenBright() {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700638 return android_server_PowerManagerService_isScreenBright();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700639}
640
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700641void NativeInputManager::virtualKeyDownFeedback() {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700642#if DEBUG_INPUT_READER_POLICY
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700643 LOGD("virtualKeyDownFeedback");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700644#endif
645
646 JNIEnv* env = jniEnv();
647
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700648 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.virtualKeyDownFeedback);
649 checkAndClearExceptionFromCallback(env, "virtualKeyDownFeedback");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700650}
651
652int32_t NativeInputManager::interceptKey(nsecs_t when,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700653 int32_t deviceId, bool down, int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700654#if DEBUG_INPUT_READER_POLICY
655 LOGD("interceptKey - when=%lld, deviceId=%d, down=%d, keyCode=%d, scanCode=%d, "
Jeff Brown349703e2010-06-22 01:27:15 -0700656 "policyFlags=0x%x",
Jeff Brown9c3cda02010-06-15 01:31:58 -0700657 when, deviceId, down, keyCode, scanCode, policyFlags);
658#endif
659
660 const int32_t WM_ACTION_PASS_TO_USER = 1;
661 const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2;
662 const int32_t WM_ACTION_GO_TO_SLEEP = 4;
663
Jeff Brown9c3cda02010-06-15 01:31:58 -0700664 bool isScreenOn = this->isScreenOn();
665 bool isScreenBright = this->isScreenBright();
666
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700667 jint wmActions = 0;
668 if (isPolicyKey(keyCode, isScreenOn)) {
669 JNIEnv* env = jniEnv();
670
671 wmActions = env->CallIntMethod(mCallbacksObj,
672 gCallbacksClassInfo.interceptKeyBeforeQueueing,
673 when, keyCode, down, policyFlags, isScreenOn);
674 if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
675 wmActions = 0;
676 }
677 } else {
678 wmActions = WM_ACTION_PASS_TO_USER;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700679 }
680
681 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
682 if (! isScreenOn) {
683 // Key presses and releases wake the device.
Jeff Brown6d0fec22010-07-23 21:28:06 -0700684 policyFlags |= POLICY_FLAG_WOKE_HERE;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700685 }
686
687 if (! isScreenBright) {
688 // Key presses and releases brighten the screen if dimmed.
Jeff Brown6d0fec22010-07-23 21:28:06 -0700689 policyFlags |= POLICY_FLAG_BRIGHT_HERE;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700690 }
691
692 if (wmActions & WM_ACTION_GO_TO_SLEEP) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700693 android_server_PowerManagerService_goToSleep(when);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700694 }
695
696 if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
Jeff Brown349703e2010-06-22 01:27:15 -0700697 pokeUserActivity(when, POWER_MANAGER_BUTTON_EVENT);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700698 }
699
700 if (wmActions & WM_ACTION_PASS_TO_USER) {
701 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700702
Jeff Brown9c3cda02010-06-15 01:31:58 -0700703 if (down && isAppSwitchKey(keyCode)) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700704 JNIEnv* env = jniEnv();
705
Jeff Brown9c3cda02010-06-15 01:31:58 -0700706 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyAppSwitchComing);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700707 checkAndClearExceptionFromCallback(env, "notifyAppSwitchComing");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700708
709 actions |= InputReaderPolicyInterface::ACTION_APP_SWITCH_COMING;
710 }
711 }
Jeff Brown349703e2010-06-22 01:27:15 -0700712
Jeff Brown9c3cda02010-06-15 01:31:58 -0700713 return actions;
714}
715
Jeff Brown6d0fec22010-07-23 21:28:06 -0700716int32_t NativeInputManager::interceptGeneric(nsecs_t when, uint32_t& policyFlags) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700717#if DEBUG_INPUT_READER_POLICY
Jeff Brown6d0fec22010-07-23 21:28:06 -0700718 LOGD("interceptGeneric - when=%lld, policyFlags=0x%x", when, policyFlags);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700719#endif
720
Jeff Brown5c225b12010-06-16 01:53:36 -0700721 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
722 if (isScreenOn()) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700723 // Only dispatch events when the device is awake.
Jeff Brown349703e2010-06-22 01:27:15 -0700724 // Do not wake the device.
Jeff Brown5c225b12010-06-16 01:53:36 -0700725 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700726
Jeff Brown349703e2010-06-22 01:27:15 -0700727 if (! isScreenBright()) {
728 // Brighten the screen if dimmed.
Jeff Brown6d0fec22010-07-23 21:28:06 -0700729 policyFlags |= POLICY_FLAG_BRIGHT_HERE;
Jeff Brown349703e2010-06-22 01:27:15 -0700730 }
Jeff Brown5c225b12010-06-16 01:53:36 -0700731 }
732
733 return actions;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700734}
735
736int32_t NativeInputManager::interceptSwitch(nsecs_t when, int32_t switchCode,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700737 int32_t switchValue, uint32_t& policyFlags) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700738#if DEBUG_INPUT_READER_POLICY
Jeff Brown6d0fec22010-07-23 21:28:06 -0700739 LOGD("interceptSwitch - when=%lld, switchCode=%d, switchValue=%d, policyFlags=0x%x",
740 when, switchCode, switchValue, policyFlags);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700741#endif
742
743 JNIEnv* env = jniEnv();
744
745 switch (switchCode) {
746 case SW_LID:
747 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyLidSwitchChanged,
748 when, switchValue == 0);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700749 checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700750 break;
751 }
752
753 return InputReaderPolicyInterface::ACTION_NONE;
754}
755
756bool NativeInputManager::filterTouchEvents() {
757 if (mFilterTouchEvents < 0) {
758 JNIEnv* env = jniEnv();
759
760 jboolean result = env->CallBooleanMethod(mCallbacksObj,
761 gCallbacksClassInfo.filterTouchEvents);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700762 if (checkAndClearExceptionFromCallback(env, "filterTouchEvents")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700763 result = false;
764 }
765
766 mFilterTouchEvents = result ? 1 : 0;
767 }
768 return mFilterTouchEvents;
769}
770
771bool NativeInputManager::filterJumpyTouchEvents() {
772 if (mFilterJumpyTouchEvents < 0) {
773 JNIEnv* env = jniEnv();
774
775 jboolean result = env->CallBooleanMethod(mCallbacksObj,
776 gCallbacksClassInfo.filterJumpyTouchEvents);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700777 if (checkAndClearExceptionFromCallback(env, "filterJumpyTouchEvents")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700778 result = false;
779 }
780
781 mFilterJumpyTouchEvents = result ? 1 : 0;
782 }
783 return mFilterJumpyTouchEvents;
784}
785
786void NativeInputManager::getVirtualKeyDefinitions(const String8& deviceName,
Jeff Brown8d608662010-08-30 03:02:23 -0700787 Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) {
788 outVirtualKeyDefinitions.clear();
789
Jeff Brown9c3cda02010-06-15 01:31:58 -0700790 JNIEnv* env = jniEnv();
791
792 jstring deviceNameStr = env->NewStringUTF(deviceName.string());
Jeff Brown7fbdc842010-06-17 20:52:56 -0700793 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700794 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
795 gCallbacksClassInfo.getVirtualKeyDefinitions, deviceNameStr));
Jeff Brown7fbdc842010-06-17 20:52:56 -0700796 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions") && result) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700797 jsize length = env->GetArrayLength(result);
798 for (jsize i = 0; i < length; i++) {
799 jobject item = env->GetObjectArrayElement(result, i);
800
801 outVirtualKeyDefinitions.add();
802 outVirtualKeyDefinitions.editTop().scanCode =
803 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.scanCode));
804 outVirtualKeyDefinitions.editTop().centerX =
805 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerX));
806 outVirtualKeyDefinitions.editTop().centerY =
807 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerY));
808 outVirtualKeyDefinitions.editTop().width =
809 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.width));
810 outVirtualKeyDefinitions.editTop().height =
811 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.height));
812
813 env->DeleteLocalRef(item);
814 }
815 env->DeleteLocalRef(result);
816 }
817 env->DeleteLocalRef(deviceNameStr);
818 }
819}
820
Jeff Brown8d608662010-08-30 03:02:23 -0700821void NativeInputManager::getInputDeviceCalibration(const String8& deviceName,
822 InputDeviceCalibration& outCalibration) {
823 outCalibration.clear();
824
825 JNIEnv* env = jniEnv();
826
827 jstring deviceNameStr = env->NewStringUTF(deviceName.string());
828 if (! checkAndClearExceptionFromCallback(env, "getInputDeviceCalibration")) {
829 jobject result = env->CallObjectMethod(mCallbacksObj,
830 gCallbacksClassInfo.getInputDeviceCalibration, deviceNameStr);
831 if (! checkAndClearExceptionFromCallback(env, "getInputDeviceCalibration") && result) {
832 jobjectArray keys = jobjectArray(env->GetObjectField(result,
833 gInputDeviceCalibrationClassInfo.keys));
834 jobjectArray values = jobjectArray(env->GetObjectField(result,
835 gInputDeviceCalibrationClassInfo.values));
836
837 jsize length = env->GetArrayLength(keys);
838 for (jsize i = 0; i < length; i++) {
839 jstring keyStr = jstring(env->GetObjectArrayElement(keys, i));
840 jstring valueStr = jstring(env->GetObjectArrayElement(values, i));
841
842 const char* keyChars = env->GetStringUTFChars(keyStr, NULL);
843 String8 key(keyChars);
844 env->ReleaseStringUTFChars(keyStr, keyChars);
845
846 const char* valueChars = env->GetStringUTFChars(valueStr, NULL);
847 String8 value(valueChars);
848 env->ReleaseStringUTFChars(valueStr, valueChars);
849
850 outCalibration.addProperty(key, value);
851
852 env->DeleteLocalRef(keyStr);
853 env->DeleteLocalRef(valueStr);
854 }
855 env->DeleteLocalRef(keys);
856 env->DeleteLocalRef(values);
857 env->DeleteLocalRef(result);
858 }
859 env->DeleteLocalRef(deviceNameStr);
860 }
861}
862
Jeff Brown9c3cda02010-06-15 01:31:58 -0700863void NativeInputManager::getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
Jeff Brown8d608662010-08-30 03:02:23 -0700864 outExcludedDeviceNames.clear();
865
Jeff Brown9c3cda02010-06-15 01:31:58 -0700866 JNIEnv* env = jniEnv();
867
868 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
869 gCallbacksClassInfo.getExcludedDeviceNames));
Jeff Brown7fbdc842010-06-17 20:52:56 -0700870 if (! checkAndClearExceptionFromCallback(env, "getExcludedDeviceNames") && result) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700871 jsize length = env->GetArrayLength(result);
872 for (jsize i = 0; i < length; i++) {
873 jstring item = jstring(env->GetObjectArrayElement(result, i));
874
875 const char* deviceNameChars = env->GetStringUTFChars(item, NULL);
876 outExcludedDeviceNames.add(String8(deviceNameChars));
877 env->ReleaseStringUTFChars(item, deviceNameChars);
878
879 env->DeleteLocalRef(item);
880 }
881 env->DeleteLocalRef(result);
882 }
883}
884
885void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
886#if DEBUG_INPUT_DISPATCHER_POLICY
887 LOGD("notifyConfigurationChanged - when=%lld", when);
888#endif
889
890 JNIEnv* env = jniEnv();
891
892 InputConfiguration config;
893 mInputManager->getInputConfiguration(& config);
894
895 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyConfigurationChanged,
896 when, config.touchScreen, config.keyboard, config.navigation);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700897 checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700898}
899
900void NativeInputManager::notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
901#if DEBUG_INPUT_DISPATCHER_POLICY
902 LOGD("notifyInputChannelBroken - inputChannel='%s'", inputChannel->getName().string());
903#endif
904
Jeff Brown7fbdc842010-06-17 20:52:56 -0700905 JNIEnv* env = jniEnv();
906
907 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
908 if (inputChannelObjLocal) {
909 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelBroken,
910 inputChannelObjLocal);
911 checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken");
912
913 env->DeleteLocalRef(inputChannelObjLocal);
914 }
Jeff Browna41ca772010-08-11 14:46:32 -0700915
916 unregisterMonitoringChannel(inputChannel);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700917}
918
Jeff Brown7fbdc842010-06-17 20:52:56 -0700919bool NativeInputManager::notifyInputChannelANR(const sp<InputChannel>& inputChannel,
920 nsecs_t& outNewTimeout) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700921#if DEBUG_INPUT_DISPATCHER_POLICY
922 LOGD("notifyInputChannelANR - inputChannel='%s'",
923 inputChannel->getName().string());
924#endif
925
Jeff Brown7fbdc842010-06-17 20:52:56 -0700926 JNIEnv* env = jniEnv();
927
928 jlong newTimeout;
929 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
930 if (inputChannelObjLocal) {
931 newTimeout = env->CallLongMethod(mCallbacksObj,
932 gCallbacksClassInfo.notifyInputChannelANR, inputChannelObjLocal);
933 if (checkAndClearExceptionFromCallback(env, "notifyInputChannelANR")) {
934 newTimeout = -2;
935 }
936
937 env->DeleteLocalRef(inputChannelObjLocal);
938 } else {
939 newTimeout = -2;
940 }
941
942 if (newTimeout == -2) {
943 return false; // abort
944 }
945
946 outNewTimeout = newTimeout;
947 return true; // resume
Jeff Brown9c3cda02010-06-15 01:31:58 -0700948}
949
950void NativeInputManager::notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel) {
951#if DEBUG_INPUT_DISPATCHER_POLICY
952 LOGD("notifyInputChannelRecoveredFromANR - inputChannel='%s'",
953 inputChannel->getName().string());
954#endif
955
Jeff Brown7fbdc842010-06-17 20:52:56 -0700956 JNIEnv* env = jniEnv();
957
958 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
959 if (inputChannelObjLocal) {
960 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelRecoveredFromANR,
961 inputChannelObjLocal);
962 checkAndClearExceptionFromCallback(env, "notifyInputChannelRecoveredFromANR");
963
964 env->DeleteLocalRef(inputChannelObjLocal);
965 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700966}
967
Jeff Brown349703e2010-06-22 01:27:15 -0700968bool NativeInputManager::notifyANR(jobject tokenObj, nsecs_t& outNewTimeout) {
969#if DEBUG_INPUT_DISPATCHER_POLICY
970 LOGD("notifyANR");
971#endif
972
973 JNIEnv* env = jniEnv();
974
975 jlong newTimeout = env->CallLongMethod(mCallbacksObj,
976 gCallbacksClassInfo.notifyANR, tokenObj);
977 if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
978 newTimeout = -2;
979 }
980
981 if (newTimeout == -2) {
982 return false; // abort
983 }
984
985 outNewTimeout = newTimeout;
986 return true; // resume
987}
988
Jeff Brown9c3cda02010-06-15 01:31:58 -0700989nsecs_t NativeInputManager::getKeyRepeatTimeout() {
990 if (! isScreenOn()) {
991 // Disable key repeat when the screen is off.
992 return -1;
993 } else {
994 // TODO use ViewConfiguration.getLongPressTimeout()
995 return milliseconds_to_nanoseconds(500);
996 }
997}
998
Jeff Brownae9fc032010-08-18 15:51:08 -0700999int32_t NativeInputManager::getMaxEventsPerSecond() {
1000 if (mMaxEventsPerSecond < 0) {
1001 JNIEnv* env = jniEnv();
1002
1003 jint result = env->CallIntMethod(mCallbacksObj,
1004 gCallbacksClassInfo.getMaxEventsPerSecond);
1005 if (checkAndClearExceptionFromCallback(env, "getMaxEventsPerSecond")) {
Jeff Brown3d8c9bd2010-08-18 17:48:53 -07001006 result = 60;
Jeff Brownae9fc032010-08-18 15:51:08 -07001007 }
1008
1009 mMaxEventsPerSecond = result;
1010 }
1011 return mMaxEventsPerSecond;
1012}
1013
Jeff Brown349703e2010-06-22 01:27:15 -07001014void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArray) {
1015#if DEBUG_FOCUS
1016 LOGD("setInputWindows");
1017#endif
1018 { // acquire lock
1019 AutoMutex _l(mDispatchLock);
1020
1021 sp<InputChannel> touchedWindowChannel;
1022 if (mTouchedWindow) {
1023 touchedWindowChannel = mTouchedWindow->inputChannel;
1024 mTouchedWindow = NULL;
1025 }
1026 size_t numTouchedWallpapers = mTouchedWallpaperWindows.size();
1027 if (numTouchedWallpapers != 0) {
1028 for (size_t i = 0; i < numTouchedWallpapers; i++) {
1029 mTempTouchedWallpaperChannels.push(mTouchedWallpaperWindows[i]->inputChannel);
1030 }
1031 mTouchedWallpaperWindows.clear();
1032 }
1033
Jeff Browne33348b2010-07-15 23:54:05 -07001034 bool hadFocusedWindow = mFocusedWindow != NULL;
1035
Jeff Brown349703e2010-06-22 01:27:15 -07001036 mWindows.clear();
1037 mFocusedWindow = NULL;
1038 mWallpaperWindows.clear();
1039
1040 if (windowObjArray) {
1041 mWindowsReady = true;
1042
1043 jsize length = env->GetArrayLength(windowObjArray);
1044 for (jsize i = 0; i < length; i++) {
1045 jobject inputTargetObj = env->GetObjectArrayElement(windowObjArray, i);
1046 if (! inputTargetObj) {
1047 break; // found null element indicating end of used portion of the array
1048 }
1049
1050 mWindows.push();
1051 InputWindow& window = mWindows.editTop();
1052 bool valid = populateWindow(env, inputTargetObj, window);
1053 if (! valid) {
1054 mWindows.pop();
1055 }
1056
1057 env->DeleteLocalRef(inputTargetObj);
1058 }
1059
1060 size_t numWindows = mWindows.size();
1061 for (size_t i = 0; i < numWindows; i++) {
1062 InputWindow* window = & mWindows.editItemAt(i);
1063 if (window->hasFocus) {
1064 mFocusedWindow = window;
1065 }
1066
1067 if (window->layoutParamsType == TYPE_WALLPAPER) {
1068 mWallpaperWindows.push(window);
1069
1070 for (size_t j = 0; j < numTouchedWallpapers; j++) {
1071 if (window->inputChannel == mTempTouchedWallpaperChannels[i]) {
1072 mTouchedWallpaperWindows.push(window);
1073 }
1074 }
1075 }
1076
1077 if (window->inputChannel == touchedWindowChannel) {
1078 mTouchedWindow = window;
1079 }
1080 }
1081 } else {
1082 mWindowsReady = false;
1083 }
1084
1085 mTempTouchedWallpaperChannels.clear();
1086
Jeff Brown00ba8842010-07-16 15:01:56 -07001087 if ((hadFocusedWindow && ! mFocusedWindow)
1088 || (mFocusedWindow && ! mFocusedWindow->visible)) {
Jeff Browne33348b2010-07-15 23:54:05 -07001089 preemptInputDispatch();
1090 }
1091
Jeff Brown349703e2010-06-22 01:27:15 -07001092 mDispatchStateChanged.broadcast();
1093
1094#if DEBUG_FOCUS
Jeff Browne33348b2010-07-15 23:54:05 -07001095 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001096#endif
1097 } // release lock
1098}
1099
1100bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj,
1101 InputWindow& outWindow) {
1102 bool valid = false;
1103
1104 jobject inputChannelObj = env->GetObjectField(windowObj,
1105 gInputWindowClassInfo.inputChannel);
1106 if (inputChannelObj) {
1107 sp<InputChannel> inputChannel =
1108 android_view_InputChannel_getInputChannel(env, inputChannelObj);
1109 if (inputChannel != NULL) {
1110 jint layoutParamsFlags = env->GetIntField(windowObj,
1111 gInputWindowClassInfo.layoutParamsFlags);
1112 jint layoutParamsType = env->GetIntField(windowObj,
1113 gInputWindowClassInfo.layoutParamsType);
1114 jlong dispatchingTimeoutNanos = env->GetLongField(windowObj,
1115 gInputWindowClassInfo.dispatchingTimeoutNanos);
1116 jint frameLeft = env->GetIntField(windowObj,
1117 gInputWindowClassInfo.frameLeft);
1118 jint frameTop = env->GetIntField(windowObj,
1119 gInputWindowClassInfo.frameTop);
1120 jint touchableAreaLeft = env->GetIntField(windowObj,
1121 gInputWindowClassInfo.touchableAreaLeft);
1122 jint touchableAreaTop = env->GetIntField(windowObj,
1123 gInputWindowClassInfo.touchableAreaTop);
1124 jint touchableAreaRight = env->GetIntField(windowObj,
1125 gInputWindowClassInfo.touchableAreaRight);
1126 jint touchableAreaBottom = env->GetIntField(windowObj,
1127 gInputWindowClassInfo.touchableAreaBottom);
1128 jboolean visible = env->GetBooleanField(windowObj,
1129 gInputWindowClassInfo.visible);
1130 jboolean hasFocus = env->GetBooleanField(windowObj,
1131 gInputWindowClassInfo.hasFocus);
1132 jboolean hasWallpaper = env->GetBooleanField(windowObj,
1133 gInputWindowClassInfo.hasWallpaper);
1134 jboolean paused = env->GetBooleanField(windowObj,
1135 gInputWindowClassInfo.paused);
1136 jint ownerPid = env->GetIntField(windowObj,
1137 gInputWindowClassInfo.ownerPid);
1138 jint ownerUid = env->GetIntField(windowObj,
1139 gInputWindowClassInfo.ownerUid);
1140
1141 outWindow.inputChannel = inputChannel;
1142 outWindow.layoutParamsFlags = layoutParamsFlags;
1143 outWindow.layoutParamsType = layoutParamsType;
1144 outWindow.dispatchingTimeout = dispatchingTimeoutNanos;
1145 outWindow.frameLeft = frameLeft;
1146 outWindow.frameTop = frameTop;
1147 outWindow.touchableAreaLeft = touchableAreaLeft;
1148 outWindow.touchableAreaTop = touchableAreaTop;
1149 outWindow.touchableAreaRight = touchableAreaRight;
1150 outWindow.touchableAreaBottom = touchableAreaBottom;
1151 outWindow.visible = visible;
1152 outWindow.hasFocus = hasFocus;
1153 outWindow.hasWallpaper = hasWallpaper;
1154 outWindow.paused = paused;
1155 outWindow.ownerPid = ownerPid;
1156 outWindow.ownerUid = ownerUid;
1157 valid = true;
1158 } else {
1159 LOGW("Dropping input target because its input channel is not initialized.");
1160 }
1161
1162 env->DeleteLocalRef(inputChannelObj);
1163 } else {
1164 LOGW("Dropping input target because the input channel object was null.");
1165 }
1166 return valid;
1167}
1168
1169void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) {
1170#if DEBUG_FOCUS
1171 LOGD("setFocusedApplication");
1172#endif
1173 { // acquire lock
1174 AutoMutex _l(mDispatchLock);
1175
1176 releaseFocusedApplicationLd(env);
1177
1178 if (applicationObj) {
1179 jstring nameObj = jstring(env->GetObjectField(applicationObj,
1180 gInputApplicationClassInfo.name));
1181 jlong dispatchingTimeoutNanos = env->GetLongField(applicationObj,
1182 gInputApplicationClassInfo.dispatchingTimeoutNanos);
1183 jobject tokenObj = env->GetObjectField(applicationObj,
1184 gInputApplicationClassInfo.token);
1185 jweak tokenObjWeak = env->NewWeakGlobalRef(tokenObj);
1186 if (! tokenObjWeak) {
1187 LOGE("Could not create weak reference for application token.");
1188 LOGE_EX(env);
1189 env->ExceptionClear();
1190 }
1191 env->DeleteLocalRef(tokenObj);
1192
1193 mFocusedApplication = & mFocusedApplicationStorage;
1194
1195 if (nameObj) {
1196 const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
1197 mFocusedApplication->name.setTo(nameStr);
1198 env->ReleaseStringUTFChars(nameObj, nameStr);
1199 env->DeleteLocalRef(nameObj);
1200 } else {
1201 LOGE("InputApplication.name should not be null.");
1202 mFocusedApplication->name.setTo("unknown");
1203 }
1204
1205 mFocusedApplication->dispatchingTimeout = dispatchingTimeoutNanos;
1206 mFocusedApplication->tokenObjWeak = tokenObjWeak;
1207 }
1208
1209 mDispatchStateChanged.broadcast();
1210
1211#if DEBUG_FOCUS
Jeff Browne33348b2010-07-15 23:54:05 -07001212 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001213#endif
1214 } // release lock
1215}
1216
1217void NativeInputManager::releaseFocusedApplicationLd(JNIEnv* env) {
1218 if (mFocusedApplication) {
1219 env->DeleteWeakGlobalRef(mFocusedApplication->tokenObjWeak);
1220 mFocusedApplication = NULL;
1221 }
1222}
1223
1224void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
1225#if DEBUG_FOCUS
1226 LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001227#endif
1228
Jeff Brown349703e2010-06-22 01:27:15 -07001229 { // acquire lock
1230 AutoMutex _l(mDispatchLock);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001231
Jeff Brown349703e2010-06-22 01:27:15 -07001232 if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
1233 mDispatchEnabled = enabled;
1234 mDispatchFrozen = frozen;
1235
1236 mDispatchStateChanged.broadcast();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001237 }
Jeff Brown349703e2010-06-22 01:27:15 -07001238
1239#if DEBUG_FOCUS
Jeff Browne33348b2010-07-15 23:54:05 -07001240 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001241#endif
1242 } // release lock
1243}
1244
1245void NativeInputManager::preemptInputDispatch() {
1246#if DEBUG_FOCUS
1247 LOGD("preemptInputDispatch");
1248#endif
1249
1250 mInputManager->preemptInputDispatch();
1251}
1252
1253int32_t NativeInputManager::waitForFocusedWindowLd(uint32_t policyFlags,
1254 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
1255 InputWindow*& outFocusedWindow) {
1256
1257 int32_t injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1258 bool firstIteration = true;
1259 ANRTimer anrTimer;
1260 for (;;) {
1261 if (firstIteration) {
1262 firstIteration = false;
1263 } else {
1264 if (! anrTimer.waitForDispatchStateChangeLd(this)) {
1265 LOGW("Dropping event because the dispatcher timed out waiting to identify "
1266 "the window that should receive it.");
1267 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1268 break;
1269 }
1270 }
1271
1272 // If dispatch is not enabled then fail.
1273 if (! mDispatchEnabled) {
1274 LOGI("Dropping event because input dispatch is disabled.");
1275 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1276 break;
1277 }
1278
1279 // If dispatch is frozen or we don't have valid window data yet then wait.
1280 if (mDispatchFrozen || ! mWindowsReady) {
1281#if DEBUG_FOCUS
1282 LOGD("Waiting because dispatch is frozen or windows are not ready.");
1283#endif
1284 anrTimer.dispatchFrozenBySystem();
1285 continue;
1286 }
1287
1288 // If there is no currently focused window and no focused application
1289 // then drop the event.
1290 if (! mFocusedWindow) {
1291 if (mFocusedApplication) {
1292#if DEBUG_FOCUS
1293 LOGD("Waiting because there is no focused window but there is a "
1294 "focused application that may yet introduce a new target: '%s'.",
1295 mFocusedApplication->name.string());
1296#endif
1297 continue;
1298 }
1299
1300 LOGI("Dropping event because there is no focused window or focused application.");
1301 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1302 break;
1303 }
1304
1305 // Check permissions.
1306 if (! checkInjectionPermission(mFocusedWindow, injectorPid, injectorUid)) {
1307 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1308 break;
1309 }
1310
1311 // If the currently focused window is paused then keep waiting.
1312 if (mFocusedWindow->paused) {
1313#if DEBUG_FOCUS
1314 LOGD("Waiting because focused window is paused.");
1315#endif
1316 anrTimer.dispatchPausedByApplication(mFocusedWindow);
1317 continue;
1318 }
1319
1320 // Success!
1321 break; // done waiting, exit loop
Jeff Brown9c3cda02010-06-15 01:31:58 -07001322 }
Jeff Brown349703e2010-06-22 01:27:15 -07001323
1324 // Output targets.
1325 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
1326 addTarget(mFocusedWindow, InputTarget::FLAG_SYNC,
1327 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
1328
1329 outFocusedWindow = mFocusedWindow;
1330 } else {
1331 outFocusedWindow = NULL;
1332 }
1333
1334#if DEBUG_FOCUS
1335 LOGD("waitForFocusedWindow finished: injectionResult=%d",
1336 injectionResult);
Jeff Browne33348b2010-07-15 23:54:05 -07001337 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001338#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001339 return injectionResult;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001340}
1341
Jeff Brownc5ed5912010-07-14 18:48:53 -07001342enum InjectionPermission {
1343 INJECTION_PERMISSION_UNKNOWN,
1344 INJECTION_PERMISSION_GRANTED,
1345 INJECTION_PERMISSION_DENIED
1346};
1347
Jeff Brown349703e2010-06-22 01:27:15 -07001348int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
1349 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
1350 InputWindow*& outTouchedWindow) {
1351 nsecs_t startTime = now();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001352
Jeff Brown349703e2010-06-22 01:27:15 -07001353 // For security reasons, we defer updating the touch state until we are sure that
1354 // event injection will be allowed.
1355 //
1356 // FIXME In the original code, screenWasOff could never be set to true.
1357 // The reason is that the POLICY_FLAG_WOKE_HERE
1358 // and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
1359 // EV_KEY, EV_REL and EV_ABS events. As it happens, the touch event was
1360 // actually enqueued using the policyFlags that appeared in the final EV_SYN
1361 // events upon which no preprocessing took place. So policyFlags was always 0.
1362 // In the new native input dispatcher we're a bit more careful about event
1363 // preprocessing so the touches we receive can actually have non-zero policyFlags.
1364 // Unfortunately we obtain undesirable behavior.
1365 //
1366 // Here's what happens:
1367 //
1368 // When the device dims in anticipation of going to sleep, touches
1369 // in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
1370 // the device to brighten and reset the user activity timer.
1371 // Touches on other windows (such as the launcher window)
1372 // are dropped. Then after a moment, the device goes to sleep. Oops.
1373 //
1374 // Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
1375 // instead of POLICY_FLAG_WOKE_HERE...
1376 //
1377 bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001378
1379 int32_t action = motionEvent->getAction();
1380
Jeff Brown349703e2010-06-22 01:27:15 -07001381 bool firstIteration = true;
1382 ANRTimer anrTimer;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001383 int32_t injectionResult;
1384 InjectionPermission injectionPermission;
Jeff Brown349703e2010-06-22 01:27:15 -07001385 for (;;) {
1386 if (firstIteration) {
1387 firstIteration = false;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001388 } else {
Jeff Brown349703e2010-06-22 01:27:15 -07001389 if (! anrTimer.waitForDispatchStateChangeLd(this)) {
1390 LOGW("Dropping event because the dispatcher timed out waiting to identify "
1391 "the window that should receive it.");
1392 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001393 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
1394 break; // timed out, exit wait loop
Jeff Brown349703e2010-06-22 01:27:15 -07001395 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001396 }
Jeff Brown349703e2010-06-22 01:27:15 -07001397
1398 // If dispatch is not enabled then fail.
1399 if (! mDispatchEnabled) {
1400 LOGI("Dropping event because input dispatch is disabled.");
1401 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001402 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
Jeff Brown349703e2010-06-22 01:27:15 -07001403 break; // failed, exit wait loop
1404 }
1405
1406 // If dispatch is frozen or we don't have valid window data yet then wait.
1407 if (mDispatchFrozen || ! mWindowsReady) {
1408#if DEBUG_INPUT_DISPATCHER_POLICY
1409 LOGD("Waiting because dispatch is frozen or windows are not ready.");
1410#endif
1411 anrTimer.dispatchFrozenBySystem();
1412 continue;
1413 }
1414
1415 // Update the touch state as needed based on the properties of the touch event.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001416 if (action == AMOTION_EVENT_ACTION_DOWN) {
1417 /* Case 1: ACTION_DOWN */
1418
Jeff Brown349703e2010-06-22 01:27:15 -07001419 InputWindow* newTouchedWindow = NULL;
1420 mTempTouchedOutsideWindows.clear();
1421
1422 int32_t x = int32_t(motionEvent->getX(0));
1423 int32_t y = int32_t(motionEvent->getY(0));
1424 InputWindow* topErrorWindow = NULL;
1425
1426 // Traverse windows from front to back to find touched window and outside targets.
1427 size_t numWindows = mWindows.size();
1428 for (size_t i = 0; i < numWindows; i++) {
1429 InputWindow* window = & mWindows.editItemAt(i);
1430 int32_t flags = window->layoutParamsFlags;
1431
1432 if (flags & FLAG_SYSTEM_ERROR) {
1433 if (! topErrorWindow) {
1434 topErrorWindow = window;
1435 }
1436 }
1437
1438 if (window->visible) {
1439 if (! (flags & FLAG_NOT_TOUCHABLE)) {
1440 bool isTouchModal = (flags &
1441 (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL)) == 0;
1442 if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
1443 if (! screenWasOff || flags & FLAG_TOUCHABLE_WHEN_WAKING) {
1444 newTouchedWindow = window;
1445 }
1446 break; // found touched window, exit window loop
1447 }
1448 }
1449
1450 if (flags & FLAG_WATCH_OUTSIDE_TOUCH) {
1451 mTempTouchedOutsideWindows.push(window);
1452 }
1453 }
1454 }
1455
1456 // If there is an error window but it is not taking focus (typically because
1457 // it is invisible) then wait for it. Any other focused window may in
1458 // fact be in ANR state.
1459 if (topErrorWindow && newTouchedWindow != topErrorWindow) {
1460#if DEBUG_INPUT_DISPATCHER_POLICY
1461 LOGD("Waiting because system error window is pending.");
1462#endif
1463 anrTimer.dispatchFrozenBySystem();
1464 continue; // wait some more
1465 }
1466
1467 // If we did not find a touched window then fail.
1468 if (! newTouchedWindow) {
1469 if (mFocusedApplication) {
1470#if DEBUG_FOCUS
1471 LOGD("Waiting because there is no focused window but there is a "
1472 "focused application that may yet introduce a new target: '%s'.",
1473 mFocusedApplication->name.string());
1474#endif
1475 continue;
1476 }
1477
1478 LOGI("Dropping event because there is no touched window or focused application.");
1479 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001480 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
Jeff Brown349703e2010-06-22 01:27:15 -07001481 break; // failed, exit wait loop
1482 }
1483
1484 // Check permissions.
1485 if (! checkInjectionPermission(newTouchedWindow, injectorPid, injectorUid)) {
1486 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001487 injectionPermission = INJECTION_PERMISSION_DENIED;
Jeff Brown349703e2010-06-22 01:27:15 -07001488 break; // failed, exit wait loop
1489 }
1490
1491 // If the touched window is paused then keep waiting.
1492 if (newTouchedWindow->paused) {
1493#if DEBUG_INPUT_DISPATCHER_POLICY
1494 LOGD("Waiting because touched window is paused.");
1495#endif
1496 anrTimer.dispatchPausedByApplication(newTouchedWindow);
1497 continue; // wait some more
1498 }
1499
1500 // Success! Update the touch dispatch state for real.
1501 releaseTouchedWindowLd();
1502
1503 mTouchedWindow = newTouchedWindow;
1504
1505 if (newTouchedWindow->hasWallpaper) {
1506 mTouchedWallpaperWindows.appendVector(mWallpaperWindows);
1507 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001508
1509 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1510 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001511 break; // done
1512 } else {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001513 /* Case 2: Everything but ACTION_DOWN */
1514
Jeff Brown349703e2010-06-22 01:27:15 -07001515 // Check permissions.
1516 if (! checkInjectionPermission(mTouchedWindow, injectorPid, injectorUid)) {
1517 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001518 injectionPermission = INJECTION_PERMISSION_DENIED;
1519 break; // failed, exit wait loop
1520 }
1521
1522 // If the pointer is not currently down, then ignore the event.
1523 if (! mTouchDown) {
1524 LOGI("Dropping event because the pointer is not down.");
1525 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1526 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001527 break; // failed, exit wait loop
1528 }
1529
1530 // If there is no currently touched window then fail.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001531 if (! mTouchedWindow) {
Jeff Browna41ca772010-08-11 14:46:32 -07001532#if DEBUG_INPUT_DISPATCHER_POLICY
1533 LOGD("Dropping event because there is no touched window to receive it.");
1534#endif
Jeff Brown349703e2010-06-22 01:27:15 -07001535 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001536 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001537 break; // failed, exit wait loop
1538 }
1539
1540 // If the touched window is paused then keep waiting.
1541 if (mTouchedWindow->paused) {
1542#if DEBUG_INPUT_DISPATCHER_POLICY
1543 LOGD("Waiting because touched window is paused.");
1544#endif
1545 anrTimer.dispatchPausedByApplication(mTouchedWindow);
1546 continue; // wait some more
1547 }
1548
1549 // Success!
Jeff Brownc5ed5912010-07-14 18:48:53 -07001550 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1551 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001552 break; // done
1553 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001554 }
Jeff Brown349703e2010-06-22 01:27:15 -07001555
1556 // Output targets.
Jeff Brown349703e2010-06-22 01:27:15 -07001557 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
Jeff Brown349703e2010-06-22 01:27:15 -07001558 size_t numWallpaperWindows = mTouchedWallpaperWindows.size();
1559 for (size_t i = 0; i < numWallpaperWindows; i++) {
1560 addTarget(mTouchedWallpaperWindows[i], 0, 0, outTargets);
1561 }
1562
1563 size_t numOutsideWindows = mTempTouchedOutsideWindows.size();
1564 for (size_t i = 0; i < numOutsideWindows; i++) {
1565 addTarget(mTempTouchedOutsideWindows[i], InputTarget::FLAG_OUTSIDE, 0, outTargets);
1566 }
1567
1568 addTarget(mTouchedWindow, InputTarget::FLAG_SYNC,
1569 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
1570 outTouchedWindow = mTouchedWindow;
1571 } else {
Jeff Brown349703e2010-06-22 01:27:15 -07001572 outTouchedWindow = NULL;
1573 }
1574 mTempTouchedOutsideWindows.clear();
1575
Jeff Brownc5ed5912010-07-14 18:48:53 -07001576 // Check injection permission once and for all.
1577 if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
1578 if (checkInjectionPermission(action == AMOTION_EVENT_ACTION_DOWN ? NULL : mTouchedWindow,
1579 injectorPid, injectorUid)) {
1580 injectionPermission = INJECTION_PERMISSION_GRANTED;
1581 } else {
1582 injectionPermission = INJECTION_PERMISSION_DENIED;
1583 }
1584 }
1585
1586 // Update final pieces of touch state if the injector had permission.
1587 if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
1588 if (action == AMOTION_EVENT_ACTION_DOWN) {
Jeff Brown349703e2010-06-22 01:27:15 -07001589 if (mTouchDown) {
1590 // This is weird. We got a down but we thought it was already down!
1591 LOGW("Pointer down received while already down.");
1592 } else {
1593 mTouchDown = true;
1594 }
1595
1596 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1597 // Since we failed to identify a target for this touch down, we may still
1598 // be holding on to an earlier target from a previous touch down. Release it.
1599 releaseTouchedWindowLd();
1600 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001601 } else if (action == AMOTION_EVENT_ACTION_UP) {
Jeff Brown349703e2010-06-22 01:27:15 -07001602 mTouchDown = false;
1603 releaseTouchedWindowLd();
1604 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001605 } else {
1606 LOGW("Not updating touch focus because injection was denied.");
Jeff Brown349703e2010-06-22 01:27:15 -07001607 }
1608
1609#if DEBUG_FOCUS
1610 LOGD("waitForTouchedWindow finished: injectionResult=%d",
1611 injectionResult);
Jeff Browne33348b2010-07-15 23:54:05 -07001612 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001613#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001614 return injectionResult;
1615}
1616
Jeff Brown349703e2010-06-22 01:27:15 -07001617void NativeInputManager::releaseTouchedWindowLd() {
1618 mTouchedWindow = NULL;
1619 mTouchedWallpaperWindows.clear();
1620}
1621
1622void NativeInputManager::addTarget(const InputWindow* window, int32_t targetFlags,
1623 nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets) {
1624 nsecs_t timeout = window->dispatchingTimeout - timeSpentWaitingForApplication;
1625 if (timeout < MIN_INPUT_DISPATCHING_TIMEOUT) {
1626 timeout = MIN_INPUT_DISPATCHING_TIMEOUT;
1627 }
1628
1629 outTargets.push();
1630
1631 InputTarget& target = outTargets.editTop();
1632 target.inputChannel = window->inputChannel;
1633 target.flags = targetFlags;
1634 target.timeout = timeout;
1635 target.xOffset = - window->frameLeft;
1636 target.yOffset = - window->frameTop;
1637}
1638
1639bool NativeInputManager::checkInjectionPermission(const InputWindow* window,
1640 int32_t injectorPid, int32_t injectorUid) {
1641 if (injectorUid > 0 && (window == NULL || window->ownerUid != injectorUid)) {
1642 JNIEnv* env = jniEnv();
1643 jboolean result = env->CallBooleanMethod(mCallbacksObj,
1644 gCallbacksClassInfo.checkInjectEventsPermission, injectorPid, injectorUid);
1645 checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission");
1646
1647 if (! result) {
1648 if (window) {
1649 LOGW("Permission denied: injecting event from pid %d uid %d to window "
1650 "with input channel %s owned by uid %d",
1651 injectorPid, injectorUid, window->inputChannel->getName().string(),
1652 window->ownerUid);
1653 } else {
1654 LOGW("Permission denied: injecting event from pid %d uid %d",
1655 injectorPid, injectorUid);
1656 }
1657 return false;
1658 }
1659 }
1660
1661 return true;
1662}
1663
1664int32_t NativeInputManager::waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
1665 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets) {
1666#if DEBUG_INPUT_DISPATCHER_POLICY
1667 LOGD("waitForKeyEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1668 policyFlags, injectorPid, injectorUid);
1669#endif
1670
1671 int32_t windowType;
1672 { // acquire lock
1673 AutoMutex _l(mDispatchLock);
1674
1675 InputWindow* focusedWindow;
1676 int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
1677 injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
1678 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1679 return injectionResult;
1680 }
1681
1682 windowType = focusedWindow->layoutParamsType;
1683 } // release lock
1684
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001685 if (isPolicyKey(keyEvent->getKeyCode(), isScreenOn())) {
1686 const InputTarget& target = outTargets.top();
1687 bool consumed = interceptKeyBeforeDispatching(target, keyEvent, policyFlags);
1688 if (consumed) {
1689 outTargets.clear();
1690 return INPUT_EVENT_INJECTION_SUCCEEDED;
1691 }
Jeff Browna41ca772010-08-11 14:46:32 -07001692
1693 addMonitoringTargetsLd(outTargets);
Jeff Brown349703e2010-06-22 01:27:15 -07001694 }
1695
1696 pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
1697 return INPUT_EVENT_INJECTION_SUCCEEDED;
1698}
1699
1700int32_t NativeInputManager::waitForMotionEventTargets(MotionEvent* motionEvent,
1701 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001702 Vector<InputTarget>& outTargets) {
Jeff Brown349703e2010-06-22 01:27:15 -07001703#if DEBUG_INPUT_DISPATCHER_POLICY
1704 LOGD("waitForMotionEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1705 policyFlags, injectorPid, injectorUid);
1706#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001707
Jeff Brownc5ed5912010-07-14 18:48:53 -07001708 int32_t source = motionEvent->getSource();
1709 if (source & AINPUT_SOURCE_CLASS_POINTER) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001710 return waitForTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
Jeff Brown349703e2010-06-22 01:27:15 -07001711 outTargets);
Jeff Brownc5ed5912010-07-14 18:48:53 -07001712 } else {
1713 return waitForNonTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
1714 outTargets);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001715 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001716}
1717
Jeff Brownc5ed5912010-07-14 18:48:53 -07001718int32_t NativeInputManager::waitForNonTouchEventTargets(MotionEvent* motionEvent,
Jeff Brown349703e2010-06-22 01:27:15 -07001719 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
1720 Vector<InputTarget>& outTargets) {
1721#if DEBUG_INPUT_DISPATCHER_POLICY
Jeff Brownc5ed5912010-07-14 18:48:53 -07001722 LOGD("waitForNonTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
Jeff Brown349703e2010-06-22 01:27:15 -07001723 policyFlags, injectorPid, injectorUid);
1724#endif
1725
1726 int32_t windowType;
1727 { // acquire lock
1728 AutoMutex _l(mDispatchLock);
1729
1730 InputWindow* focusedWindow;
1731 int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
1732 injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
1733 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1734 return injectionResult;
1735 }
1736
1737 windowType = focusedWindow->layoutParamsType;
Jeff Browna41ca772010-08-11 14:46:32 -07001738
1739 addMonitoringTargetsLd(outTargets);
Jeff Brown349703e2010-06-22 01:27:15 -07001740 } // release lock
1741
1742 pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
1743 return INPUT_EVENT_INJECTION_SUCCEEDED;
1744}
1745
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001746int32_t NativeInputManager::waitForTouchEventTargets(MotionEvent* motionEvent,
Jeff Brown349703e2010-06-22 01:27:15 -07001747 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
1748 Vector<InputTarget>& outTargets) {
1749#if DEBUG_INPUT_DISPATCHER_POLICY
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001750 LOGD("waitForTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
Jeff Brown349703e2010-06-22 01:27:15 -07001751 policyFlags, injectorPid, injectorUid);
1752#endif
1753
1754 int32_t windowType;
1755 { // acquire lock
1756 AutoMutex _l(mDispatchLock);
1757
1758 InputWindow* touchedWindow;
1759 int32_t injectionResult = waitForTouchedWindowLd(motionEvent, policyFlags,
1760 injectorPid, injectorUid, outTargets, /*out*/ touchedWindow);
1761 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1762 return injectionResult;
1763 }
1764
1765 windowType = touchedWindow->layoutParamsType;
Jeff Browna41ca772010-08-11 14:46:32 -07001766
1767 addMonitoringTargetsLd(outTargets);
Jeff Brown349703e2010-06-22 01:27:15 -07001768 } // release lock
1769
1770 int32_t eventType;
1771 switch (motionEvent->getAction()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001772 case AMOTION_EVENT_ACTION_DOWN:
Jeff Brown349703e2010-06-22 01:27:15 -07001773 eventType = POWER_MANAGER_TOUCH_EVENT;
1774 break;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001775 case AMOTION_EVENT_ACTION_UP:
Jeff Brown349703e2010-06-22 01:27:15 -07001776 eventType = POWER_MANAGER_TOUCH_UP_EVENT;
1777 break;
1778 default:
1779 if (motionEvent->getEventTime() - motionEvent->getDownTime()
1780 >= EVENT_IGNORE_DURATION) {
1781 eventType = POWER_MANAGER_TOUCH_EVENT;
1782 } else {
1783 eventType = POWER_MANAGER_LONG_TOUCH_EVENT;
1784 }
1785 break;
1786 }
1787 pokeUserActivityIfNeeded(windowType, eventType);
1788 return INPUT_EVENT_INJECTION_SUCCEEDED;
1789}
1790
Jeff Brownd0097872010-06-30 14:41:59 -07001791bool NativeInputManager::interceptKeyBeforeDispatching(const InputTarget& target,
1792 const KeyEvent* keyEvent, uint32_t policyFlags) {
1793 JNIEnv* env = jniEnv();
1794
1795 jobject inputChannelObj = getInputChannelObjLocal(env, target.inputChannel);
1796 if (inputChannelObj) {
1797 jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
1798 gCallbacksClassInfo.interceptKeyBeforeDispatching,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001799 inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(),
1800 keyEvent->getKeyCode(), keyEvent->getMetaState(),
Jeff Brownd0097872010-06-30 14:41:59 -07001801 keyEvent->getRepeatCount(), policyFlags);
1802 bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
1803
1804 env->DeleteLocalRef(inputChannelObj);
1805
1806 return consumed && ! error;
1807 } else {
1808 LOGW("Could not apply key dispatch policy because input channel '%s' is "
1809 "no longer valid.", target.inputChannel->getName().string());
1810 return false;
1811 }
1812}
1813
Jeff Brown349703e2010-06-22 01:27:15 -07001814void NativeInputManager::pokeUserActivityIfNeeded(int32_t windowType, int32_t eventType) {
1815 if (windowType != TYPE_KEYGUARD) {
1816 nsecs_t eventTime = now();
1817 pokeUserActivity(eventTime, eventType);
1818 }
1819}
1820
1821void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001822 android_server_PowerManagerService_userActivity(eventTime, eventType);
Jeff Brown349703e2010-06-22 01:27:15 -07001823}
1824
Jeff Browna41ca772010-08-11 14:46:32 -07001825void NativeInputManager::registerMonitoringChannel(const sp<InputChannel>& inputChannel) {
1826 { // acquire lock
1827 AutoMutex _l(mDispatchLock);
1828 mMonitoringChannels.push(inputChannel);
1829 } // release lock
1830}
1831
1832void NativeInputManager::unregisterMonitoringChannel(const sp<InputChannel>& inputChannel) {
1833 { // acquire lock
1834 AutoMutex _l(mDispatchLock);
1835
1836 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
1837 if (mMonitoringChannels[i] == inputChannel) {
1838 mMonitoringChannels.removeAt(i);
1839 break;
1840 }
1841 }
1842 } // release lock
1843}
1844
1845void NativeInputManager::addMonitoringTargetsLd(Vector<InputTarget>& outTargets) {
1846 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
1847 outTargets.push();
1848
1849 InputTarget& target = outTargets.editTop();
1850 target.inputChannel = mMonitoringChannels[i];
1851 target.flags = 0;
1852 target.timeout = -1;
1853 target.xOffset = 0;
1854 target.yOffset = 0;
1855 }
1856}
1857
Jeff Brown6d0fec22010-07-23 21:28:06 -07001858static void dumpMotionRange(String8& dump,
1859 const char* name, const InputDeviceInfo::MotionRange* range) {
1860 if (range) {
1861 dump.appendFormat(" %s = { min: %0.3f, max: %0.3f, flat: %0.3f, fuzz: %0.3f }\n",
1862 name, range->min, range->max, range->flat, range->fuzz);
1863 }
1864}
1865
1866#define DUMP_MOTION_RANGE(range) \
1867 dumpMotionRange(dump, #range, deviceInfo.getMotionRange(AINPUT_MOTION_RANGE_##range));
1868
1869void NativeInputManager::dumpDeviceInfo(String8& dump) {
1870 Vector<int32_t> deviceIds;
1871 mInputManager->getInputDeviceIds(deviceIds);
1872
1873 InputDeviceInfo deviceInfo;
1874 for (size_t i = 0; i < deviceIds.size(); i++) {
1875 int32_t deviceId = deviceIds[i];
1876
1877 status_t result = mInputManager->getInputDeviceInfo(deviceId, & deviceInfo);
1878 if (result == NAME_NOT_FOUND) {
1879 continue;
1880 } else if (result != OK) {
1881 dump.appendFormat(" ** Unexpected error %d getting information about input devices.\n",
1882 result);
1883 continue;
1884 }
1885
1886 dump.appendFormat(" Device %d: '%s'\n",
1887 deviceInfo.getId(), deviceInfo.getName().string());
1888 dump.appendFormat(" sources = 0x%08x\n",
1889 deviceInfo.getSources());
1890 dump.appendFormat(" keyboardType = %d\n",
1891 deviceInfo.getKeyboardType());
1892
1893 dump.append(" motion ranges:\n");
1894 DUMP_MOTION_RANGE(X);
1895 DUMP_MOTION_RANGE(Y);
1896 DUMP_MOTION_RANGE(PRESSURE);
1897 DUMP_MOTION_RANGE(SIZE);
1898 DUMP_MOTION_RANGE(TOUCH_MAJOR);
1899 DUMP_MOTION_RANGE(TOUCH_MINOR);
1900 DUMP_MOTION_RANGE(TOOL_MAJOR);
1901 DUMP_MOTION_RANGE(TOOL_MINOR);
1902 DUMP_MOTION_RANGE(ORIENTATION);
1903 }
1904}
1905
1906#undef DUMP_MOTION_RANGE
1907
Jeff Browne33348b2010-07-15 23:54:05 -07001908void NativeInputManager::logDispatchStateLd() {
1909 String8 dump;
1910 dumpDispatchStateLd(dump);
1911 LOGD("%s", dump.string());
1912}
1913
1914void NativeInputManager::dumpDispatchStateLd(String8& dump) {
1915 dump.appendFormat(" dispatchEnabled: %d\n", mDispatchEnabled);
1916 dump.appendFormat(" dispatchFrozen: %d\n", mDispatchFrozen);
1917 dump.appendFormat(" windowsReady: %d\n", mWindowsReady);
1918
Jeff Brown349703e2010-06-22 01:27:15 -07001919 if (mFocusedApplication) {
Jeff Browne33348b2010-07-15 23:54:05 -07001920 dump.appendFormat(" focusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001921 mFocusedApplication->name.string(),
1922 mFocusedApplication->dispatchingTimeout / 1000000.0);
1923 } else {
Jeff Browne33348b2010-07-15 23:54:05 -07001924 dump.append(" focusedApplication: <null>\n");
Jeff Brown349703e2010-06-22 01:27:15 -07001925 }
Jeff Browne33348b2010-07-15 23:54:05 -07001926 dump.appendFormat(" focusedWindow: '%s'\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001927 mFocusedWindow != NULL ? mFocusedWindow->inputChannel->getName().string() : "<null>");
Jeff Browne33348b2010-07-15 23:54:05 -07001928 dump.appendFormat(" touchedWindow: '%s', touchDown=%d\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001929 mTouchedWindow != NULL ? mTouchedWindow->inputChannel->getName().string() : "<null>",
1930 mTouchDown);
1931 for (size_t i = 0; i < mTouchedWallpaperWindows.size(); i++) {
Jeff Browne33348b2010-07-15 23:54:05 -07001932 dump.appendFormat(" touchedWallpaperWindows[%d]: '%s'\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001933 i, mTouchedWallpaperWindows[i]->inputChannel->getName().string());
1934 }
1935 for (size_t i = 0; i < mWindows.size(); i++) {
Jeff Browne33348b2010-07-15 23:54:05 -07001936 dump.appendFormat(" windows[%d]: '%s', paused=%d, hasFocus=%d, hasWallpaper=%d, "
1937 "visible=%d, flags=0x%08x, type=0x%08x, "
Jeff Brown349703e2010-06-22 01:27:15 -07001938 "frame=[%d,%d], touchableArea=[%d,%d][%d,%d], "
Jeff Browne33348b2010-07-15 23:54:05 -07001939 "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001940 i, mWindows[i].inputChannel->getName().string(),
1941 mWindows[i].paused, mWindows[i].hasFocus, mWindows[i].hasWallpaper,
1942 mWindows[i].visible, mWindows[i].layoutParamsFlags, mWindows[i].layoutParamsType,
1943 mWindows[i].frameLeft, mWindows[i].frameTop,
1944 mWindows[i].touchableAreaLeft, mWindows[i].touchableAreaTop,
1945 mWindows[i].touchableAreaRight, mWindows[i].touchableAreaBottom,
1946 mWindows[i].ownerPid, mWindows[i].ownerUid,
1947 mWindows[i].dispatchingTimeout / 1000000.0);
1948 }
Jeff Browna41ca772010-08-11 14:46:32 -07001949
1950 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
1951 dump.appendFormat(" monitoringChannel[%d]: '%s'\n",
1952 i, mMonitoringChannels[i]->getName().string());
1953 }
Jeff Brown349703e2010-06-22 01:27:15 -07001954}
1955
1956// ----------------------------------------------------------------------------
1957
1958NativeInputManager::ANRTimer::ANRTimer() :
1959 mBudget(APPLICATION), mStartTime(now()), mFrozen(false), mPausedWindow(NULL) {
1960}
1961
1962void NativeInputManager::ANRTimer::dispatchFrozenBySystem() {
1963 mFrozen = true;
1964}
1965
1966void NativeInputManager::ANRTimer::dispatchPausedByApplication(InputWindow* pausedWindow) {
1967 mPausedWindow = pausedWindow;
1968}
1969
1970bool NativeInputManager::ANRTimer::waitForDispatchStateChangeLd(NativeInputManager* inputManager) {
1971 nsecs_t currentTime = now();
1972
1973 Budget newBudget;
1974 nsecs_t dispatchingTimeout;
1975 sp<InputChannel> pausedChannel = NULL;
1976 jobject tokenObj = NULL;
1977 if (mFrozen) {
1978 newBudget = SYSTEM;
1979 dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
1980 mFrozen = false;
1981 } else if (mPausedWindow) {
1982 newBudget = APPLICATION;
1983 dispatchingTimeout = mPausedWindow->dispatchingTimeout;
1984 pausedChannel = mPausedWindow->inputChannel;
1985 mPausedWindow = NULL;
1986 } else if (inputManager->mFocusedApplication) {
1987 newBudget = APPLICATION;
1988 dispatchingTimeout = inputManager->mFocusedApplication->dispatchingTimeout;
1989 tokenObj = jniEnv()->NewLocalRef(inputManager->mFocusedApplication->tokenObjWeak);
1990 } else {
1991 newBudget = APPLICATION;
1992 dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
1993 }
1994
1995 if (mBudget != newBudget) {
1996 mBudget = newBudget;
1997 mStartTime = currentTime;
1998 }
1999
2000 bool result = false;
2001 nsecs_t timeoutRemaining = mStartTime + dispatchingTimeout - currentTime;
2002 if (timeoutRemaining > 0
2003 && inputManager->mDispatchStateChanged.waitRelative(inputManager->mDispatchLock,
2004 timeoutRemaining) == OK) {
2005 result = true;
2006 } else {
2007 if (pausedChannel != NULL || tokenObj != NULL) {
2008 bool resumed;
2009 nsecs_t newTimeout = 0;
2010
2011 inputManager->mDispatchLock.unlock(); // release lock
2012 if (pausedChannel != NULL) {
2013 resumed = inputManager->notifyInputChannelANR(pausedChannel, /*out*/ newTimeout);
2014 } else {
2015 resumed = inputManager->notifyANR(tokenObj, /*out*/ newTimeout);
2016 }
2017 inputManager->mDispatchLock.lock(); // re-acquire lock
2018
2019 if (resumed) {
2020 mStartTime = now() - dispatchingTimeout + newTimeout;
2021 result = true;
2022 }
2023 }
2024 }
2025
2026 if (tokenObj) {
2027 jniEnv()->DeleteLocalRef(tokenObj);
2028 }
2029
2030 return result;
2031}
2032
2033nsecs_t NativeInputManager::ANRTimer::getTimeSpentWaitingForApplication() const {
2034 return mBudget == APPLICATION ? now() - mStartTime : 0;
2035}
Jeff Brown9c3cda02010-06-15 01:31:58 -07002036
2037// ----------------------------------------------------------------------------
2038
2039static sp<NativeInputManager> gNativeInputManager;
2040
Jeff Brown46b9ac02010-04-22 18:58:52 -07002041static bool checkInputManagerUnitialized(JNIEnv* env) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07002042 if (gNativeInputManager == NULL) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002043 LOGE("Input manager not initialized.");
2044 jniThrowRuntimeException(env, "Input manager not initialized.");
2045 return true;
2046 }
2047 return false;
2048}
2049
2050static void android_server_InputManager_nativeInit(JNIEnv* env, jclass clazz,
2051 jobject callbacks) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07002052 if (gNativeInputManager == NULL) {
2053 gNativeInputManager = new NativeInputManager(callbacks);
2054 } else {
2055 LOGE("Input manager already initialized.");
2056 jniThrowRuntimeException(env, "Input manager already initialized.");
Jeff Brown46b9ac02010-04-22 18:58:52 -07002057 }
2058}
2059
2060static void android_server_InputManager_nativeStart(JNIEnv* env, jclass clazz) {
2061 if (checkInputManagerUnitialized(env)) {
2062 return;
2063 }
2064
Jeff Brown9c3cda02010-06-15 01:31:58 -07002065 status_t result = gNativeInputManager->getInputManager()->start();
Jeff Brown46b9ac02010-04-22 18:58:52 -07002066 if (result) {
2067 jniThrowRuntimeException(env, "Input manager could not be started.");
2068 }
2069}
2070
2071static void android_server_InputManager_nativeSetDisplaySize(JNIEnv* env, jclass clazz,
2072 jint displayId, jint width, jint height) {
2073 if (checkInputManagerUnitialized(env)) {
2074 return;
2075 }
2076
2077 // XXX we could get this from the SurfaceFlinger directly instead of requiring it
2078 // to be passed in like this, not sure which is better but leaving it like this
2079 // keeps the window manager in direct control of when display transitions propagate down
2080 // to the input dispatcher
Jeff Brown9c3cda02010-06-15 01:31:58 -07002081 gNativeInputManager->setDisplaySize(displayId, width, height);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002082}
2083
2084static void android_server_InputManager_nativeSetDisplayOrientation(JNIEnv* env, jclass clazz,
2085 jint displayId, jint orientation) {
2086 if (checkInputManagerUnitialized(env)) {
2087 return;
2088 }
2089
Jeff Brown9c3cda02010-06-15 01:31:58 -07002090 gNativeInputManager->setDisplayOrientation(displayId, orientation);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002091}
2092
2093static jint android_server_InputManager_nativeGetScanCodeState(JNIEnv* env, jclass clazz,
Jeff Brown6d0fec22010-07-23 21:28:06 -07002094 jint deviceId, jint sourceMask, jint scanCode) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002095 if (checkInputManagerUnitialized(env)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002096 return AKEY_STATE_UNKNOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002097 }
2098
Jeff Brown9c3cda02010-06-15 01:31:58 -07002099 return gNativeInputManager->getInputManager()->getScanCodeState(
Jeff Brown6d0fec22010-07-23 21:28:06 -07002100 deviceId, uint32_t(sourceMask), scanCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002101}
2102
2103static jint android_server_InputManager_nativeGetKeyCodeState(JNIEnv* env, jclass clazz,
Jeff Brown6d0fec22010-07-23 21:28:06 -07002104 jint deviceId, jint sourceMask, jint keyCode) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002105 if (checkInputManagerUnitialized(env)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002106 return AKEY_STATE_UNKNOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002107 }
2108
Jeff Brown9c3cda02010-06-15 01:31:58 -07002109 return gNativeInputManager->getInputManager()->getKeyCodeState(
Jeff Brown6d0fec22010-07-23 21:28:06 -07002110 deviceId, uint32_t(sourceMask), keyCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002111}
2112
2113static jint android_server_InputManager_nativeGetSwitchState(JNIEnv* env, jclass clazz,
Jeff Brown6d0fec22010-07-23 21:28:06 -07002114 jint deviceId, jint sourceMask, jint sw) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002115 if (checkInputManagerUnitialized(env)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002116 return AKEY_STATE_UNKNOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002117 }
2118
Jeff Brown6d0fec22010-07-23 21:28:06 -07002119 return gNativeInputManager->getInputManager()->getSwitchState(
2120 deviceId, uint32_t(sourceMask), sw);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002121}
2122
2123static jboolean android_server_InputManager_nativeHasKeys(JNIEnv* env, jclass clazz,
Jeff Brown6d0fec22010-07-23 21:28:06 -07002124 jint deviceId, jint sourceMask, jintArray keyCodes, jbooleanArray outFlags) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002125 if (checkInputManagerUnitialized(env)) {
2126 return JNI_FALSE;
2127 }
2128
2129 int32_t* codes = env->GetIntArrayElements(keyCodes, NULL);
2130 uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL);
2131 jsize numCodes = env->GetArrayLength(keyCodes);
2132 jboolean result;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002133 if (numCodes == env->GetArrayLength(keyCodes)) {
2134 result = gNativeInputManager->getInputManager()->hasKeys(
2135 deviceId, uint32_t(sourceMask), numCodes, codes, flags);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002136 } else {
2137 result = JNI_FALSE;
2138 }
2139
2140 env->ReleaseBooleanArrayElements(outFlags, flags, 0);
2141 env->ReleaseIntArrayElements(keyCodes, codes, 0);
2142 return result;
2143}
2144
2145static void throwInputChannelNotInitialized(JNIEnv* env) {
2146 jniThrowException(env, "java/lang/IllegalStateException",
2147 "inputChannel is not initialized");
2148}
2149
2150static void android_server_InputManager_handleInputChannelDisposed(JNIEnv* env,
2151 jobject inputChannelObj, const sp<InputChannel>& inputChannel, void* data) {
2152 LOGW("Input channel object '%s' was disposed without first being unregistered with "
2153 "the input manager!", inputChannel->getName().string());
2154
Jeff Brown9c3cda02010-06-15 01:31:58 -07002155 if (gNativeInputManager != NULL) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07002156 gNativeInputManager->unregisterInputChannel(env, inputChannel);
Jeff Brown9c3cda02010-06-15 01:31:58 -07002157 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002158}
2159
2160static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
Jeff Browna41ca772010-08-11 14:46:32 -07002161 jobject inputChannelObj, jboolean monitor) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002162 if (checkInputManagerUnitialized(env)) {
2163 return;
2164 }
2165
2166 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
2167 inputChannelObj);
2168 if (inputChannel == NULL) {
2169 throwInputChannelNotInitialized(env);
2170 return;
2171 }
2172
Jeff Brown7fbdc842010-06-17 20:52:56 -07002173
2174 status_t status = gNativeInputManager->registerInputChannel(
Jeff Browna41ca772010-08-11 14:46:32 -07002175 env, inputChannel, inputChannelObj, monitor);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002176 if (status) {
2177 jniThrowRuntimeException(env, "Failed to register input channel. "
2178 "Check logs for details.");
2179 return;
2180 }
2181
Jeff Browna41ca772010-08-11 14:46:32 -07002182 if (! monitor) {
2183 android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
2184 android_server_InputManager_handleInputChannelDisposed, NULL);
2185 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002186}
2187
2188static void android_server_InputManager_nativeUnregisterInputChannel(JNIEnv* env, jclass clazz,
2189 jobject inputChannelObj) {
2190 if (checkInputManagerUnitialized(env)) {
2191 return;
2192 }
2193
2194 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
2195 inputChannelObj);
2196 if (inputChannel == NULL) {
2197 throwInputChannelNotInitialized(env);
2198 return;
2199 }
2200
2201 android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL);
2202
Jeff Brown7fbdc842010-06-17 20:52:56 -07002203 status_t status = gNativeInputManager->unregisterInputChannel(env, inputChannel);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002204 if (status) {
2205 jniThrowRuntimeException(env, "Failed to unregister input channel. "
2206 "Check logs for details.");
2207 }
2208}
2209
Jeff Brown6ec402b2010-07-28 15:48:59 -07002210static jint android_server_InputManager_nativeInjectInputEvent(JNIEnv* env, jclass clazz,
2211 jobject inputEventObj, jint injectorPid, jint injectorUid,
2212 jint syncMode, jint timeoutMillis) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07002213 if (checkInputManagerUnitialized(env)) {
2214 return INPUT_EVENT_INJECTION_FAILED;
2215 }
2216
Jeff Brown6ec402b2010-07-28 15:48:59 -07002217 if (env->IsInstanceOf(inputEventObj, gKeyEventClassInfo.clazz)) {
2218 KeyEvent keyEvent;
2219 android_view_KeyEvent_toNative(env, inputEventObj, & keyEvent);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002220
Jeff Brown6ec402b2010-07-28 15:48:59 -07002221 return gNativeInputManager->getInputManager()->injectInputEvent(& keyEvent,
2222 injectorPid, injectorUid, syncMode, timeoutMillis);
2223 } else if (env->IsInstanceOf(inputEventObj, gMotionEventClassInfo.clazz)) {
2224 MotionEvent motionEvent;
2225 android_view_MotionEvent_toNative(env, inputEventObj, & motionEvent);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002226
Jeff Brown6ec402b2010-07-28 15:48:59 -07002227 return gNativeInputManager->getInputManager()->injectInputEvent(& motionEvent,
2228 injectorPid, injectorUid, syncMode, timeoutMillis);
2229 } else {
2230 jniThrowRuntimeException(env, "Invalid input event type.");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002231 return INPUT_EVENT_INJECTION_FAILED;
2232 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07002233}
2234
Jeff Brown349703e2010-06-22 01:27:15 -07002235static void android_server_InputManager_nativeSetInputWindows(JNIEnv* env, jclass clazz,
2236 jobjectArray windowObjArray) {
2237 if (checkInputManagerUnitialized(env)) {
2238 return;
2239 }
2240
2241 gNativeInputManager->setInputWindows(env, windowObjArray);
2242}
2243
2244static void android_server_InputManager_nativeSetFocusedApplication(JNIEnv* env, jclass clazz,
2245 jobject applicationObj) {
2246 if (checkInputManagerUnitialized(env)) {
2247 return;
2248 }
2249
2250 gNativeInputManager->setFocusedApplication(env, applicationObj);
2251}
2252
2253static void android_server_InputManager_nativeSetInputDispatchMode(JNIEnv* env,
2254 jclass clazz, jboolean enabled, jboolean frozen) {
2255 if (checkInputManagerUnitialized(env)) {
2256 return;
2257 }
2258
2259 gNativeInputManager->setInputDispatchMode(enabled, frozen);
2260}
2261
2262static void android_server_InputManager_nativePreemptInputDispatch(JNIEnv* env,
2263 jclass clazz) {
2264 if (checkInputManagerUnitialized(env)) {
2265 return;
2266 }
2267
2268 gNativeInputManager->preemptInputDispatch();
2269}
2270
Jeff Brown8d608662010-08-30 03:02:23 -07002271static jobject android_server_InputManager_nativeGetInputDevice(JNIEnv* env,
2272 jclass clazz, jint deviceId) {
2273 if (checkInputManagerUnitialized(env)) {
2274 return NULL;
2275 }
2276
2277 InputDeviceInfo deviceInfo;
2278 status_t status = gNativeInputManager->getInputManager()->getInputDeviceInfo(
2279 deviceId, & deviceInfo);
2280 if (status) {
2281 return NULL;
2282 }
2283
2284 jobject deviceObj = env->NewObject(gInputDeviceClassInfo.clazz, gInputDeviceClassInfo.ctor);
2285 if (! deviceObj) {
2286 return NULL;
2287 }
2288
2289 jstring deviceNameObj = env->NewStringUTF(deviceInfo.getName().string());
2290 if (! deviceNameObj) {
2291 return NULL;
2292 }
2293
2294 env->SetIntField(deviceObj, gInputDeviceClassInfo.mId, deviceInfo.getId());
2295 env->SetObjectField(deviceObj, gInputDeviceClassInfo.mName, deviceNameObj);
2296 env->SetIntField(deviceObj, gInputDeviceClassInfo.mSources, deviceInfo.getSources());
2297 env->SetIntField(deviceObj, gInputDeviceClassInfo.mKeyboardType, deviceInfo.getKeyboardType());
2298
2299 const KeyedVector<int, InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
2300 for (size_t i = 0; i < ranges.size(); i++) {
2301 int rangeType = ranges.keyAt(i);
2302 const InputDeviceInfo::MotionRange& range = ranges.valueAt(i);
2303 env->CallVoidMethod(deviceObj, gInputDeviceClassInfo.addMotionRange,
2304 rangeType, range.min, range.max, range.flat, range.fuzz);
2305 if (env->ExceptionCheck()) {
2306 return NULL;
2307 }
2308 }
2309
2310 return deviceObj;
2311}
2312
2313static jintArray android_server_InputManager_nativeGetInputDeviceIds(JNIEnv* env,
2314 jclass clazz) {
2315 if (checkInputManagerUnitialized(env)) {
2316 return NULL;
2317 }
2318
2319 Vector<int> deviceIds;
2320 gNativeInputManager->getInputManager()->getInputDeviceIds(deviceIds);
2321
2322 jintArray deviceIdsObj = env->NewIntArray(deviceIds.size());
2323 if (! deviceIdsObj) {
2324 return NULL;
2325 }
2326
2327 env->SetIntArrayRegion(deviceIdsObj, 0, deviceIds.size(), deviceIds.array());
2328 return deviceIdsObj;
2329}
2330
Jeff Browne33348b2010-07-15 23:54:05 -07002331static jstring android_server_InputManager_nativeDump(JNIEnv* env, jclass clazz) {
2332 if (checkInputManagerUnitialized(env)) {
2333 return NULL;
2334 }
2335
2336 String8 dump(gNativeInputManager->dump());
2337 return env->NewStringUTF(dump.string());
2338}
2339
Jeff Brown9c3cda02010-06-15 01:31:58 -07002340// ----------------------------------------------------------------------------
2341
Jeff Brown46b9ac02010-04-22 18:58:52 -07002342static JNINativeMethod gInputManagerMethods[] = {
2343 /* name, signature, funcPtr */
2344 { "nativeInit", "(Lcom/android/server/InputManager$Callbacks;)V",
2345 (void*) android_server_InputManager_nativeInit },
2346 { "nativeStart", "()V",
2347 (void*) android_server_InputManager_nativeStart },
2348 { "nativeSetDisplaySize", "(III)V",
2349 (void*) android_server_InputManager_nativeSetDisplaySize },
2350 { "nativeSetDisplayOrientation", "(II)V",
2351 (void*) android_server_InputManager_nativeSetDisplayOrientation },
2352 { "nativeGetScanCodeState", "(III)I",
2353 (void*) android_server_InputManager_nativeGetScanCodeState },
2354 { "nativeGetKeyCodeState", "(III)I",
2355 (void*) android_server_InputManager_nativeGetKeyCodeState },
2356 { "nativeGetSwitchState", "(III)I",
2357 (void*) android_server_InputManager_nativeGetSwitchState },
Jeff Brown6d0fec22010-07-23 21:28:06 -07002358 { "nativeHasKeys", "(II[I[Z)Z",
Jeff Brown46b9ac02010-04-22 18:58:52 -07002359 (void*) android_server_InputManager_nativeHasKeys },
Jeff Browna41ca772010-08-11 14:46:32 -07002360 { "nativeRegisterInputChannel", "(Landroid/view/InputChannel;Z)V",
Jeff Brown46b9ac02010-04-22 18:58:52 -07002361 (void*) android_server_InputManager_nativeRegisterInputChannel },
2362 { "nativeUnregisterInputChannel", "(Landroid/view/InputChannel;)V",
Jeff Brown7fbdc842010-06-17 20:52:56 -07002363 (void*) android_server_InputManager_nativeUnregisterInputChannel },
Jeff Brown6ec402b2010-07-28 15:48:59 -07002364 { "nativeInjectInputEvent", "(Landroid/view/InputEvent;IIII)I",
2365 (void*) android_server_InputManager_nativeInjectInputEvent },
Jeff Brown349703e2010-06-22 01:27:15 -07002366 { "nativeSetInputWindows", "([Lcom/android/server/InputWindow;)V",
2367 (void*) android_server_InputManager_nativeSetInputWindows },
2368 { "nativeSetFocusedApplication", "(Lcom/android/server/InputApplication;)V",
2369 (void*) android_server_InputManager_nativeSetFocusedApplication },
2370 { "nativeSetInputDispatchMode", "(ZZ)V",
2371 (void*) android_server_InputManager_nativeSetInputDispatchMode },
2372 { "nativePreemptInputDispatch", "()V",
Jeff Browne33348b2010-07-15 23:54:05 -07002373 (void*) android_server_InputManager_nativePreemptInputDispatch },
Jeff Brown8d608662010-08-30 03:02:23 -07002374 { "nativeGetInputDevice", "(I)Landroid/view/InputDevice;",
2375 (void*) android_server_InputManager_nativeGetInputDevice },
2376 { "nativeGetInputDeviceIds", "()[I",
2377 (void*) android_server_InputManager_nativeGetInputDeviceIds },
Jeff Browne33348b2010-07-15 23:54:05 -07002378 { "nativeDump", "()Ljava/lang/String;",
2379 (void*) android_server_InputManager_nativeDump },
Jeff Brown46b9ac02010-04-22 18:58:52 -07002380};
2381
2382#define FIND_CLASS(var, className) \
2383 var = env->FindClass(className); \
2384 LOG_FATAL_IF(! var, "Unable to find class " className); \
2385 var = jclass(env->NewGlobalRef(var));
2386
2387#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
2388 var = env->GetMethodID(clazz, methodName, methodDescriptor); \
2389 LOG_FATAL_IF(! var, "Unable to find method " methodName);
2390
2391#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
2392 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
2393 LOG_FATAL_IF(! var, "Unable to find field " fieldName);
2394
2395int register_android_server_InputManager(JNIEnv* env) {
2396 int res = jniRegisterNativeMethods(env, "com/android/server/InputManager",
2397 gInputManagerMethods, NELEM(gInputManagerMethods));
2398 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
2399
Jeff Brown9c3cda02010-06-15 01:31:58 -07002400 // Callbacks
Jeff Brown46b9ac02010-04-22 18:58:52 -07002401
2402 FIND_CLASS(gCallbacksClassInfo.clazz, "com/android/server/InputManager$Callbacks");
2403
Jeff Brown46b9ac02010-04-22 18:58:52 -07002404 GET_METHOD_ID(gCallbacksClassInfo.notifyConfigurationChanged, gCallbacksClassInfo.clazz,
2405 "notifyConfigurationChanged", "(JIII)V");
2406
2407 GET_METHOD_ID(gCallbacksClassInfo.notifyLidSwitchChanged, gCallbacksClassInfo.clazz,
2408 "notifyLidSwitchChanged", "(JZ)V");
2409
Jeff Brown7fbdc842010-06-17 20:52:56 -07002410 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelBroken, gCallbacksClassInfo.clazz,
2411 "notifyInputChannelBroken", "(Landroid/view/InputChannel;)V");
2412
2413 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelANR, gCallbacksClassInfo.clazz,
2414 "notifyInputChannelANR", "(Landroid/view/InputChannel;)J");
2415
2416 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelRecoveredFromANR, gCallbacksClassInfo.clazz,
2417 "notifyInputChannelRecoveredFromANR", "(Landroid/view/InputChannel;)V");
2418
Jeff Brown349703e2010-06-22 01:27:15 -07002419 GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
2420 "notifyANR", "(Ljava/lang/Object;)J");
2421
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002422 GET_METHOD_ID(gCallbacksClassInfo.virtualKeyDownFeedback, gCallbacksClassInfo.clazz,
2423 "virtualKeyDownFeedback", "()V");
Jeff Brown46b9ac02010-04-22 18:58:52 -07002424
Jeff Brown349703e2010-06-22 01:27:15 -07002425 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002426 "interceptKeyBeforeQueueing", "(JIZIZ)I");
Jeff Brown349703e2010-06-22 01:27:15 -07002427
2428 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002429 "interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIIIII)Z");
Jeff Brown349703e2010-06-22 01:27:15 -07002430
2431 GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,
2432 "checkInjectEventsPermission", "(II)Z");
Jeff Brown46b9ac02010-04-22 18:58:52 -07002433
Jeff Brown46b9ac02010-04-22 18:58:52 -07002434 GET_METHOD_ID(gCallbacksClassInfo.notifyAppSwitchComing, gCallbacksClassInfo.clazz,
2435 "notifyAppSwitchComing", "()V");
2436
2437 GET_METHOD_ID(gCallbacksClassInfo.filterTouchEvents, gCallbacksClassInfo.clazz,
2438 "filterTouchEvents", "()Z");
2439
2440 GET_METHOD_ID(gCallbacksClassInfo.filterJumpyTouchEvents, gCallbacksClassInfo.clazz,
2441 "filterJumpyTouchEvents", "()Z");
2442
2443 GET_METHOD_ID(gCallbacksClassInfo.getVirtualKeyDefinitions, gCallbacksClassInfo.clazz,
2444 "getVirtualKeyDefinitions",
2445 "(Ljava/lang/String;)[Lcom/android/server/InputManager$VirtualKeyDefinition;");
2446
Jeff Brown8d608662010-08-30 03:02:23 -07002447 GET_METHOD_ID(gCallbacksClassInfo.getInputDeviceCalibration, gCallbacksClassInfo.clazz,
2448 "getInputDeviceCalibration",
2449 "(Ljava/lang/String;)Lcom/android/server/InputManager$InputDeviceCalibration;");
2450
Jeff Brown46b9ac02010-04-22 18:58:52 -07002451 GET_METHOD_ID(gCallbacksClassInfo.getExcludedDeviceNames, gCallbacksClassInfo.clazz,
2452 "getExcludedDeviceNames", "()[Ljava/lang/String;");
2453
Jeff Brownae9fc032010-08-18 15:51:08 -07002454 GET_METHOD_ID(gCallbacksClassInfo.getMaxEventsPerSecond, gCallbacksClassInfo.clazz,
2455 "getMaxEventsPerSecond", "()I");
2456
Jeff Brown46b9ac02010-04-22 18:58:52 -07002457 // VirtualKeyDefinition
2458
2459 FIND_CLASS(gVirtualKeyDefinitionClassInfo.clazz,
2460 "com/android/server/InputManager$VirtualKeyDefinition");
2461
2462 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.scanCode, gVirtualKeyDefinitionClassInfo.clazz,
2463 "scanCode", "I");
2464
2465 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerX, gVirtualKeyDefinitionClassInfo.clazz,
2466 "centerX", "I");
2467
2468 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerY, gVirtualKeyDefinitionClassInfo.clazz,
2469 "centerY", "I");
2470
2471 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.width, gVirtualKeyDefinitionClassInfo.clazz,
2472 "width", "I");
2473
2474 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.height, gVirtualKeyDefinitionClassInfo.clazz,
2475 "height", "I");
2476
Jeff Brown8d608662010-08-30 03:02:23 -07002477 // InputDeviceCalibration
2478
2479 FIND_CLASS(gInputDeviceCalibrationClassInfo.clazz,
2480 "com/android/server/InputManager$InputDeviceCalibration");
2481
2482 GET_FIELD_ID(gInputDeviceCalibrationClassInfo.keys, gInputDeviceCalibrationClassInfo.clazz,
2483 "keys", "[Ljava/lang/String;");
2484
2485 GET_FIELD_ID(gInputDeviceCalibrationClassInfo.values, gInputDeviceCalibrationClassInfo.clazz,
2486 "values", "[Ljava/lang/String;");
2487
Jeff Brown349703e2010-06-22 01:27:15 -07002488 // InputWindow
Jeff Brown7fbdc842010-06-17 20:52:56 -07002489
Jeff Brown349703e2010-06-22 01:27:15 -07002490 FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002491
Jeff Brown349703e2010-06-22 01:27:15 -07002492 GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
2493 "inputChannel", "Landroid/view/InputChannel;");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002494
Jeff Brown349703e2010-06-22 01:27:15 -07002495 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
2496 "layoutParamsFlags", "I");
2497
2498 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
2499 "layoutParamsType", "I");
2500
2501 GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
2502 "dispatchingTimeoutNanos", "J");
2503
2504 GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
2505 "frameLeft", "I");
2506
2507 GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
2508 "frameTop", "I");
2509
2510 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
2511 "touchableAreaLeft", "I");
2512
2513 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
2514 "touchableAreaTop", "I");
2515
2516 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
2517 "touchableAreaRight", "I");
2518
2519 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
2520 "touchableAreaBottom", "I");
2521
2522 GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
2523 "visible", "Z");
2524
2525 GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
2526 "hasFocus", "Z");
2527
2528 GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
2529 "hasWallpaper", "Z");
2530
2531 GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
2532 "paused", "Z");
2533
2534 GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
2535 "ownerPid", "I");
2536
2537 GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
2538 "ownerUid", "I");
2539
2540 // InputApplication
2541
2542 FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication");
2543
2544 GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
2545 "name", "Ljava/lang/String;");
2546
2547 GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
2548 gInputApplicationClassInfo.clazz,
2549 "dispatchingTimeoutNanos", "J");
2550
2551 GET_FIELD_ID(gInputApplicationClassInfo.token, gInputApplicationClassInfo.clazz,
2552 "token", "Ljava/lang/Object;");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002553
Jeff Brown6ec402b2010-07-28 15:48:59 -07002554 // KeyEvent
2555
2556 FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
2557
Jeff Brown8d608662010-08-30 03:02:23 -07002558 // MotionEvent
Jeff Brown6ec402b2010-07-28 15:48:59 -07002559
2560 FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent");
2561
Jeff Brown8d608662010-08-30 03:02:23 -07002562 // InputDevice
2563
2564 FIND_CLASS(gInputDeviceClassInfo.clazz, "android/view/InputDevice");
2565
2566 GET_METHOD_ID(gInputDeviceClassInfo.ctor, gInputDeviceClassInfo.clazz,
2567 "<init>", "()V");
2568
2569 GET_METHOD_ID(gInputDeviceClassInfo.addMotionRange, gInputDeviceClassInfo.clazz,
2570 "addMotionRange", "(IFFFF)V");
2571
2572 GET_FIELD_ID(gInputDeviceClassInfo.mId, gInputDeviceClassInfo.clazz,
2573 "mId", "I");
2574
2575 GET_FIELD_ID(gInputDeviceClassInfo.mName, gInputDeviceClassInfo.clazz,
2576 "mName", "Ljava/lang/String;");
2577
2578 GET_FIELD_ID(gInputDeviceClassInfo.mSources, gInputDeviceClassInfo.clazz,
2579 "mSources", "I");
2580
2581 GET_FIELD_ID(gInputDeviceClassInfo.mKeyboardType, gInputDeviceClassInfo.clazz,
2582 "mKeyboardType", "I");
2583
2584 GET_FIELD_ID(gInputDeviceClassInfo.mMotionRanges, gInputDeviceClassInfo.clazz,
2585 "mMotionRanges", "[Landroid/view/InputDevice$MotionRange;");
2586
Jeff Brown46b9ac02010-04-22 18:58:52 -07002587 return 0;
2588}
2589
Jeff Brown46b9ac02010-04-22 18:58:52 -07002590} /* namespace android */