blob: 3addc0d2e208b9592ca7ce8f2481bef0af645e7b [file] [log] [blame]
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "InputManager-JNI"
18
Jeff Brown9c3cda02010-06-15 01:31:58 -070019//#define LOG_NDEBUG 0
20
21// Log debug messages about InputReaderPolicy
Jeff Brown349703e2010-06-22 01:27:15 -070022#define DEBUG_INPUT_READER_POLICY 0
Jeff Brown9c3cda02010-06-15 01:31:58 -070023
24// Log debug messages about InputDispatcherPolicy
Jeff Brown349703e2010-06-22 01:27:15 -070025#define DEBUG_INPUT_DISPATCHER_POLICY 0
Jeff Brown9c3cda02010-06-15 01:31:58 -070026
Jeff Brown349703e2010-06-22 01:27:15 -070027// Log debug messages about input focus tracking
28#define DEBUG_FOCUS 0
Jeff Brown9c3cda02010-06-15 01:31:58 -070029
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070030#include "JNIHelp.h"
31#include "jni.h"
Jeff Brown349703e2010-06-22 01:27:15 -070032#include <limits.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070033#include <android_runtime/AndroidRuntime.h>
Jeff Brown9c3cda02010-06-15 01:31:58 -070034#include <ui/InputReader.h>
35#include <ui/InputDispatcher.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070036#include <ui/InputManager.h>
37#include <ui/InputTransport.h>
38#include <utils/Log.h>
39#include <utils/threads.h>
40#include "../../core/jni/android_view_KeyEvent.h"
41#include "../../core/jni/android_view_MotionEvent.h"
42#include "../../core/jni/android_view_InputChannel.h"
Jeff Brown00fa7bd2010-07-02 15:37:36 -070043#include "com_android_server_PowerManagerService.h"
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070044
45namespace android {
46
Jeff Brown349703e2010-06-22 01:27:15 -070047// Window flags from WindowManager.LayoutParams
48enum {
49 FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
50 FLAG_DIM_BEHIND = 0x00000002,
51 FLAG_BLUR_BEHIND = 0x00000004,
52 FLAG_NOT_FOCUSABLE = 0x00000008,
53 FLAG_NOT_TOUCHABLE = 0x00000010,
54 FLAG_NOT_TOUCH_MODAL = 0x00000020,
55 FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
56 FLAG_KEEP_SCREEN_ON = 0x00000080,
57 FLAG_LAYOUT_IN_SCREEN = 0x00000100,
58 FLAG_LAYOUT_NO_LIMITS = 0x00000200,
59 FLAG_FULLSCREEN = 0x00000400,
60 FLAG_FORCE_NOT_FULLSCREEN = 0x00000800,
61 FLAG_DITHER = 0x00001000,
62 FLAG_SECURE = 0x00002000,
63 FLAG_SCALED = 0x00004000,
64 FLAG_IGNORE_CHEEK_PRESSES = 0x00008000,
65 FLAG_LAYOUT_INSET_DECOR = 0x00010000,
66 FLAG_ALT_FOCUSABLE_IM = 0x00020000,
67 FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
68 FLAG_SHOW_WHEN_LOCKED = 0x00080000,
69 FLAG_SHOW_WALLPAPER = 0x00100000,
70 FLAG_TURN_SCREEN_ON = 0x00200000,
71 FLAG_DISMISS_KEYGUARD = 0x00400000,
72 FLAG_IMMERSIVE = 0x00800000,
73 FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000,
74 FLAG_COMPATIBLE_WINDOW = 0x20000000,
75 FLAG_SYSTEM_ERROR = 0x40000000,
76};
77
78// Window types from WindowManager.LayoutParams
79enum {
80 FIRST_APPLICATION_WINDOW = 1,
81 TYPE_BASE_APPLICATION = 1,
82 TYPE_APPLICATION = 2,
83 TYPE_APPLICATION_STARTING = 3,
84 LAST_APPLICATION_WINDOW = 99,
85 FIRST_SUB_WINDOW = 1000,
86 TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW,
87 TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1,
88 TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2,
89 TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3,
90 TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4,
91 LAST_SUB_WINDOW = 1999,
92 FIRST_SYSTEM_WINDOW = 2000,
93 TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW,
94 TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1,
95 TYPE_PHONE = FIRST_SYSTEM_WINDOW+2,
96 TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3,
97 TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4,
98 TYPE_TOAST = FIRST_SYSTEM_WINDOW+5,
99 TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6,
100 TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7,
101 TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8,
102 TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9,
103 TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10,
104 TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11,
105 TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
106 TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13,
107 TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14,
108 LAST_SYSTEM_WINDOW = 2999,
109};
110
Jeff Brown349703e2010-06-22 01:27:15 -0700111// Delay between reporting long touch events to the power manager.
112const nsecs_t EVENT_IGNORE_DURATION = 300 * 1000000LL; // 300 ms
113
114// Default input dispatching timeout if there is no focused application or paused window
115// from which to determine an appropriate dispatching timeout.
116const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
117
118// Minimum amount of time to provide to the input dispatcher for delivery of an event
119// regardless of how long the application window was paused.
120const nsecs_t MIN_INPUT_DISPATCHING_TIMEOUT = 1000 * 1000000LL; // 1 sec
121
Jeff Brown9c3cda02010-06-15 01:31:58 -0700122// ----------------------------------------------------------------------------
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700123
124static struct {
125 jclass clazz;
126
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700127 jmethodID notifyConfigurationChanged;
128 jmethodID notifyLidSwitchChanged;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700129 jmethodID notifyInputChannelBroken;
130 jmethodID notifyInputChannelANR;
131 jmethodID notifyInputChannelRecoveredFromANR;
Jeff Brown349703e2010-06-22 01:27:15 -0700132 jmethodID notifyANR;
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700133 jmethodID virtualKeyDownFeedback;
Jeff Brown349703e2010-06-22 01:27:15 -0700134 jmethodID interceptKeyBeforeQueueing;
135 jmethodID interceptKeyBeforeDispatching;
136 jmethodID checkInjectEventsPermission;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700137 jmethodID notifyAppSwitchComing;
138 jmethodID filterTouchEvents;
139 jmethodID filterJumpyTouchEvents;
140 jmethodID getVirtualKeyDefinitions;
141 jmethodID getExcludedDeviceNames;
Jeff Brownae9fc032010-08-18 15:51:08 -0700142 jmethodID getMaxEventsPerSecond;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700143} gCallbacksClassInfo;
144
145static struct {
146 jclass clazz;
147
148 jfieldID scanCode;
149 jfieldID centerX;
150 jfieldID centerY;
151 jfieldID width;
152 jfieldID height;
153} gVirtualKeyDefinitionClassInfo;
154
Jeff Brown7fbdc842010-06-17 20:52:56 -0700155static struct {
156 jclass clazz;
157
Jeff Brown349703e2010-06-22 01:27:15 -0700158 jfieldID inputChannel;
159 jfieldID layoutParamsFlags;
160 jfieldID layoutParamsType;
161 jfieldID dispatchingTimeoutNanos;
162 jfieldID frameLeft;
163 jfieldID frameTop;
164 jfieldID touchableAreaLeft;
165 jfieldID touchableAreaTop;
166 jfieldID touchableAreaRight;
167 jfieldID touchableAreaBottom;
168 jfieldID visible;
169 jfieldID hasFocus;
170 jfieldID hasWallpaper;
171 jfieldID paused;
172 jfieldID ownerPid;
173 jfieldID ownerUid;
174} gInputWindowClassInfo;
175
176static struct {
177 jclass clazz;
178
179 jfieldID name;
180 jfieldID dispatchingTimeoutNanos;
181 jfieldID token;
182} gInputApplicationClassInfo;
183
Jeff Brown6ec402b2010-07-28 15:48:59 -0700184static struct {
185 jclass clazz;
186} gKeyEventClassInfo;
187
188static struct {
189 jclass clazz;
190} gMotionEventClassInfo;
191
Jeff Brown349703e2010-06-22 01:27:15 -0700192// ----------------------------------------------------------------------------
193
194static inline nsecs_t now() {
195 return systemTime(SYSTEM_TIME_MONOTONIC);
196}
Jeff Brown7fbdc842010-06-17 20:52:56 -0700197
Jeff Brown9c3cda02010-06-15 01:31:58 -0700198// ----------------------------------------------------------------------------
199
200class NativeInputManager : public virtual RefBase,
201 public virtual InputReaderPolicyInterface,
202 public virtual InputDispatcherPolicyInterface {
203protected:
204 virtual ~NativeInputManager();
205
206public:
207 NativeInputManager(jobject callbacksObj);
208
209 inline sp<InputManager> getInputManager() const { return mInputManager; }
210
Jeff Browne33348b2010-07-15 23:54:05 -0700211 String8 dump();
212
Jeff Brown9c3cda02010-06-15 01:31:58 -0700213 void setDisplaySize(int32_t displayId, int32_t width, int32_t height);
214 void setDisplayOrientation(int32_t displayId, int32_t orientation);
215
Jeff Brown7fbdc842010-06-17 20:52:56 -0700216 status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
Jeff Browna41ca772010-08-11 14:46:32 -0700217 jweak inputChannelObjWeak, bool monitor);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700218 status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
219
Jeff Brown349703e2010-06-22 01:27:15 -0700220 void setInputWindows(JNIEnv* env, jobjectArray windowObjArray);
221 void setFocusedApplication(JNIEnv* env, jobject applicationObj);
222 void setInputDispatchMode(bool enabled, bool frozen);
223 void preemptInputDispatch();
224
Jeff Brown9c3cda02010-06-15 01:31:58 -0700225 /* --- InputReaderPolicyInterface implementation --- */
226
227 virtual bool getDisplayInfo(int32_t displayId,
228 int32_t* width, int32_t* height, int32_t* orientation);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700229 virtual void virtualKeyDownFeedback();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700230 virtual int32_t interceptKey(nsecs_t when, int32_t deviceId,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700231 bool down, int32_t keyCode, int32_t scanCode, uint32_t& policyFlags);
232 virtual int32_t interceptSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
233 uint32_t& policyFlags);
234 virtual int32_t interceptGeneric(nsecs_t when, uint32_t& policyFlags);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700235 virtual bool filterTouchEvents();
236 virtual bool filterJumpyTouchEvents();
237 virtual void getVirtualKeyDefinitions(const String8& deviceName,
238 Vector<InputReaderPolicyInterface::VirtualKeyDefinition>& outVirtualKeyDefinitions);
239 virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames);
240
241 /* --- InputDispatcherPolicyInterface implementation --- */
242
243 virtual void notifyConfigurationChanged(nsecs_t when);
244 virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700245 virtual bool notifyInputChannelANR(const sp<InputChannel>& inputChannel,
246 nsecs_t& outNewTimeout);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700247 virtual void notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel);
248 virtual nsecs_t getKeyRepeatTimeout();
Jeff Brown349703e2010-06-22 01:27:15 -0700249 virtual int32_t waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700250 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brown349703e2010-06-22 01:27:15 -0700251 virtual int32_t waitForMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700252 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brownae9fc032010-08-18 15:51:08 -0700253 virtual int32_t getMaxEventsPerSecond();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700254
255private:
Jeff Brown349703e2010-06-22 01:27:15 -0700256 struct InputWindow {
257 sp<InputChannel> inputChannel;
258 int32_t layoutParamsFlags;
259 int32_t layoutParamsType;
260 nsecs_t dispatchingTimeout;
261 int32_t frameLeft;
262 int32_t frameTop;
263 int32_t touchableAreaLeft;
264 int32_t touchableAreaTop;
265 int32_t touchableAreaRight;
266 int32_t touchableAreaBottom;
267 bool visible;
268 bool hasFocus;
269 bool hasWallpaper;
270 bool paused;
271 int32_t ownerPid;
272 int32_t ownerUid;
273
274 inline bool touchableAreaContainsPoint(int32_t x, int32_t y) {
275 return x >= touchableAreaLeft && x <= touchableAreaRight
276 && y >= touchableAreaTop && y <= touchableAreaBottom;
277 }
278 };
279
280 struct InputApplication {
281 String8 name;
282 nsecs_t dispatchingTimeout;
283 jweak tokenObjWeak;
284 };
285
286 class ANRTimer {
287 enum Budget {
288 SYSTEM = 0,
289 APPLICATION = 1
290 };
291
292 Budget mBudget;
293 nsecs_t mStartTime;
294 bool mFrozen;
295 InputWindow* mPausedWindow;
296
297 public:
298 ANRTimer();
299
300 void dispatchFrozenBySystem();
301 void dispatchPausedByApplication(InputWindow* pausedWindow);
302 bool waitForDispatchStateChangeLd(NativeInputManager* inputManager);
303
304 nsecs_t getTimeSpentWaitingForApplication() const;
305 };
306
Jeff Brown9c3cda02010-06-15 01:31:58 -0700307 sp<InputManager> mInputManager;
308
309 jobject mCallbacksObj;
310
311 // Cached filtering policies.
312 int32_t mFilterTouchEvents;
313 int32_t mFilterJumpyTouchEvents;
314
Jeff Brownae9fc032010-08-18 15:51:08 -0700315 // Cached throttling policy.
316 int32_t mMaxEventsPerSecond;
317
Jeff Brown9c3cda02010-06-15 01:31:58 -0700318 // Cached display state. (lock mDisplayLock)
319 Mutex mDisplayLock;
320 int32_t mDisplayWidth, mDisplayHeight;
321 int32_t mDisplayOrientation;
322
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700323 // Power manager interactions.
Jeff Brown9c3cda02010-06-15 01:31:58 -0700324 bool isScreenOn();
325 bool isScreenBright();
326
Jeff Brown2cbecea2010-08-17 15:59:26 -0700327 // Weak references to all currently registered input channels by connection pointer.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700328 Mutex mInputChannelRegistryLock;
Jeff Brown2cbecea2010-08-17 15:59:26 -0700329 KeyedVector<InputChannel*, jweak> mInputChannelObjWeakTable;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700330
331 jobject getInputChannelObjLocal(JNIEnv* env, const sp<InputChannel>& inputChannel);
332
Jeff Brown349703e2010-06-22 01:27:15 -0700333 // Input target and focus tracking. (lock mDispatchLock)
334 Mutex mDispatchLock;
335 Condition mDispatchStateChanged;
336
337 bool mDispatchEnabled;
338 bool mDispatchFrozen;
339 bool mWindowsReady;
340 Vector<InputWindow> mWindows;
341 Vector<InputWindow*> mWallpaperWindows;
Jeff Browna41ca772010-08-11 14:46:32 -0700342 Vector<sp<InputChannel> > mMonitoringChannels;
Jeff Brown349703e2010-06-22 01:27:15 -0700343
344 // Focus tracking for keys, trackball, etc.
345 InputWindow* mFocusedWindow;
346
347 // Focus tracking for touch.
348 bool mTouchDown;
349 InputWindow* mTouchedWindow; // primary target for current down
350 Vector<InputWindow*> mTouchedWallpaperWindows; // wallpaper targets
351
352 Vector<InputWindow*> mTempTouchedOutsideWindows; // temporary outside touch targets
353 Vector<sp<InputChannel> > mTempTouchedWallpaperChannels; // temporary wallpaper targets
354
355 // Focused application.
356 InputApplication* mFocusedApplication;
357 InputApplication mFocusedApplicationStorage; // preallocated storage for mFocusedApplication
358
Jeff Brown6d0fec22010-07-23 21:28:06 -0700359 void dumpDeviceInfo(String8& dump);
Jeff Browne33348b2010-07-15 23:54:05 -0700360 void dumpDispatchStateLd(String8& dump);
361 void logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -0700362
363 bool notifyANR(jobject tokenObj, nsecs_t& outNewTimeout);
364 void releaseFocusedApplicationLd(JNIEnv* env);
365
366 int32_t waitForFocusedWindowLd(uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
367 Vector<InputTarget>& outTargets, InputWindow*& outFocusedWindow);
368 int32_t waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
369 int32_t injectorPid, int32_t injectorUid,
370 Vector<InputTarget>& outTargets, InputWindow*& outTouchedWindow);
371
372 void releaseTouchedWindowLd();
373
Jeff Brownc5ed5912010-07-14 18:48:53 -0700374 int32_t waitForNonTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown349703e2010-06-22 01:27:15 -0700375 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700376 int32_t waitForTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown349703e2010-06-22 01:27:15 -0700377 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
378
Jeff Brownd0097872010-06-30 14:41:59 -0700379 bool interceptKeyBeforeDispatching(const InputTarget& target,
380 const KeyEvent* keyEvent, uint32_t policyFlags);
381
Jeff Brown349703e2010-06-22 01:27:15 -0700382 void pokeUserActivityIfNeeded(int32_t windowType, int32_t eventType);
383 void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
384 bool checkInjectionPermission(const InputWindow* window,
385 int32_t injectorPid, int32_t injectorUid);
386
387 static bool populateWindow(JNIEnv* env, jobject windowObj, InputWindow& outWindow);
388 static void addTarget(const InputWindow* window, int32_t targetFlags,
389 nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets);
390
Jeff Browna41ca772010-08-11 14:46:32 -0700391 void registerMonitoringChannel(const sp<InputChannel>& inputChannel);
392 void unregisterMonitoringChannel(const sp<InputChannel>& inputChannel);
393 void addMonitoringTargetsLd(Vector<InputTarget>& outTargets);
394
Jeff Brown9c3cda02010-06-15 01:31:58 -0700395 static inline JNIEnv* jniEnv() {
396 return AndroidRuntime::getJNIEnv();
397 }
398
399 static bool isAppSwitchKey(int32_t keyCode);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700400 static bool isPolicyKey(int32_t keyCode, bool isScreenOn);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700401 static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700402};
403
404// ----------------------------------------------------------------------------
405
406NativeInputManager::NativeInputManager(jobject callbacksObj) :
407 mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1),
Jeff Brownae9fc032010-08-18 15:51:08 -0700408 mMaxEventsPerSecond(-1),
Jeff Brown0b72e822010-06-29 16:52:21 -0700409 mDisplayWidth(-1), mDisplayHeight(-1), mDisplayOrientation(ROTATION_0),
Jeff Brown349703e2010-06-22 01:27:15 -0700410 mDispatchEnabled(true), mDispatchFrozen(false), mWindowsReady(true),
411 mFocusedWindow(NULL), mTouchDown(false), mTouchedWindow(NULL),
412 mFocusedApplication(NULL) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700413 JNIEnv* env = jniEnv();
414
415 mCallbacksObj = env->NewGlobalRef(callbacksObj);
416
417 sp<EventHub> eventHub = new EventHub();
418 mInputManager = new InputManager(eventHub, this, this);
419}
420
421NativeInputManager::~NativeInputManager() {
422 JNIEnv* env = jniEnv();
423
424 env->DeleteGlobalRef(mCallbacksObj);
Jeff Brown349703e2010-06-22 01:27:15 -0700425
426 releaseFocusedApplicationLd(env);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700427}
428
Jeff Browne33348b2010-07-15 23:54:05 -0700429String8 NativeInputManager::dump() {
430 String8 dump;
Jeff Brown00ba8842010-07-16 15:01:56 -0700431 { // acquire lock
432 AutoMutex _l(mDisplayLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700433 dump.append("Native Input Dispatcher State:\n");
Jeff Brown00ba8842010-07-16 15:01:56 -0700434 dumpDispatchStateLd(dump);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700435 dump.append("\n");
Jeff Brown00ba8842010-07-16 15:01:56 -0700436 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -0700437
438 dump.append("Input Devices:\n");
439 dumpDeviceInfo(dump);
440
Jeff Browne33348b2010-07-15 23:54:05 -0700441 return dump;
442}
443
Jeff Brown9c3cda02010-06-15 01:31:58 -0700444bool NativeInputManager::isAppSwitchKey(int32_t keyCode) {
Jeff Brownfd035822010-06-30 16:10:35 -0700445 return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700446}
447
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700448bool NativeInputManager::isPolicyKey(int32_t keyCode, bool isScreenOn) {
449 // Special keys that the WindowManagerPolicy might care about.
450 switch (keyCode) {
Jeff Brownfd035822010-06-30 16:10:35 -0700451 case AKEYCODE_VOLUME_UP:
452 case AKEYCODE_VOLUME_DOWN:
453 case AKEYCODE_ENDCALL:
454 case AKEYCODE_POWER:
455 case AKEYCODE_CALL:
456 case AKEYCODE_HOME:
457 case AKEYCODE_MENU:
458 case AKEYCODE_SEARCH:
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700459 // media keys
Jeff Brownfd035822010-06-30 16:10:35 -0700460 case AKEYCODE_HEADSETHOOK:
461 case AKEYCODE_MEDIA_PLAY_PAUSE:
462 case AKEYCODE_MEDIA_STOP:
463 case AKEYCODE_MEDIA_NEXT:
464 case AKEYCODE_MEDIA_PREVIOUS:
465 case AKEYCODE_MEDIA_REWIND:
466 case AKEYCODE_MEDIA_FAST_FORWARD:
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700467 return true;
468 default:
469 // We need to pass all keys to the policy in the following cases:
470 // - screen is off
471 // - keyguard is visible
472 // - policy is performing key chording
473 //return ! isScreenOn || keyguardVisible || chording;
474 return true; // XXX stubbed out for now
475 }
476}
477
Jeff Brown7fbdc842010-06-17 20:52:56 -0700478bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700479 if (env->ExceptionCheck()) {
480 LOGE("An exception was thrown by callback '%s'.", methodName);
481 LOGE_EX(env);
482 env->ExceptionClear();
483 return true;
484 }
485 return false;
486}
487
488void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height) {
489 if (displayId == 0) {
490 AutoMutex _l(mDisplayLock);
491
492 mDisplayWidth = width;
493 mDisplayHeight = height;
494 }
495}
496
497void NativeInputManager::setDisplayOrientation(int32_t displayId, int32_t orientation) {
498 if (displayId == 0) {
499 AutoMutex _l(mDisplayLock);
500
501 mDisplayOrientation = orientation;
502 }
503}
504
Jeff Brown7fbdc842010-06-17 20:52:56 -0700505status_t NativeInputManager::registerInputChannel(JNIEnv* env,
Jeff Browna41ca772010-08-11 14:46:32 -0700506 const sp<InputChannel>& inputChannel, jobject inputChannelObj, bool monitor) {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700507 jweak inputChannelObjWeak = env->NewWeakGlobalRef(inputChannelObj);
508 if (! inputChannelObjWeak) {
509 LOGE("Could not create weak reference for input channel.");
510 LOGE_EX(env);
511 return NO_MEMORY;
512 }
513
514 status_t status;
515 {
516 AutoMutex _l(mInputChannelRegistryLock);
517
Jeff Brown2cbecea2010-08-17 15:59:26 -0700518 ssize_t index = mInputChannelObjWeakTable.indexOfKey(inputChannel.get());
Jeff Brown7fbdc842010-06-17 20:52:56 -0700519 if (index >= 0) {
520 LOGE("Input channel object '%s' has already been registered",
521 inputChannel->getName().string());
522 status = INVALID_OPERATION;
523 goto DeleteWeakRef;
524 }
525
Jeff Brown2cbecea2010-08-17 15:59:26 -0700526 mInputChannelObjWeakTable.add(inputChannel.get(), inputChannelObjWeak);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700527 }
528
529 status = mInputManager->registerInputChannel(inputChannel);
530 if (! status) {
Jeff Browna41ca772010-08-11 14:46:32 -0700531 // Success.
532 if (monitor) {
533 registerMonitoringChannel(inputChannel);
534 }
Jeff Brown7fbdc842010-06-17 20:52:56 -0700535 return OK;
536 }
537
Jeff Browna41ca772010-08-11 14:46:32 -0700538 // Failed!
Jeff Brown7fbdc842010-06-17 20:52:56 -0700539 {
540 AutoMutex _l(mInputChannelRegistryLock);
Jeff Brown2cbecea2010-08-17 15:59:26 -0700541 mInputChannelObjWeakTable.removeItem(inputChannel.get());
Jeff Brown7fbdc842010-06-17 20:52:56 -0700542 }
543
544DeleteWeakRef:
545 env->DeleteWeakGlobalRef(inputChannelObjWeak);
546 return status;
547}
548
549status_t NativeInputManager::unregisterInputChannel(JNIEnv* env,
550 const sp<InputChannel>& inputChannel) {
551 jweak inputChannelObjWeak;
552 {
553 AutoMutex _l(mInputChannelRegistryLock);
554
Jeff Brown2cbecea2010-08-17 15:59:26 -0700555 ssize_t index = mInputChannelObjWeakTable.indexOfKey(inputChannel.get());
Jeff Brown7fbdc842010-06-17 20:52:56 -0700556 if (index < 0) {
557 LOGE("Input channel object '%s' is not currently registered",
558 inputChannel->getName().string());
559 return INVALID_OPERATION;
560 }
561
Jeff Brown2cbecea2010-08-17 15:59:26 -0700562 inputChannelObjWeak = mInputChannelObjWeakTable.valueAt(index);
563 mInputChannelObjWeakTable.removeItemsAt(index);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700564 }
565
566 env->DeleteWeakGlobalRef(inputChannelObjWeak);
567
Jeff Browna41ca772010-08-11 14:46:32 -0700568 unregisterMonitoringChannel(inputChannel);
569
Jeff Brown7fbdc842010-06-17 20:52:56 -0700570 return mInputManager->unregisterInputChannel(inputChannel);
571}
572
573jobject NativeInputManager::getInputChannelObjLocal(JNIEnv* env,
574 const sp<InputChannel>& inputChannel) {
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 return NULL;
581 }
582
Jeff Brown2cbecea2010-08-17 15:59:26 -0700583 jweak inputChannelObjWeak = mInputChannelObjWeakTable.valueAt(index);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700584 return env->NewLocalRef(inputChannelObjWeak);
585 }
586}
587
Jeff Brown9c3cda02010-06-15 01:31:58 -0700588bool NativeInputManager::getDisplayInfo(int32_t displayId,
589 int32_t* width, int32_t* height, int32_t* orientation) {
590 bool result = false;
591 if (displayId == 0) {
592 AutoMutex _l(mDisplayLock);
593
594 if (mDisplayWidth > 0) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700595 if (width) {
596 *width = mDisplayWidth;
597 }
598 if (height) {
599 *height = mDisplayHeight;
600 }
601 if (orientation) {
602 *orientation = mDisplayOrientation;
603 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700604 result = true;
605 }
606 }
607 return result;
608}
609
610bool NativeInputManager::isScreenOn() {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700611 return android_server_PowerManagerService_isScreenOn();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700612}
613
614bool NativeInputManager::isScreenBright() {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700615 return android_server_PowerManagerService_isScreenBright();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700616}
617
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700618void NativeInputManager::virtualKeyDownFeedback() {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700619#if DEBUG_INPUT_READER_POLICY
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700620 LOGD("virtualKeyDownFeedback");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700621#endif
622
623 JNIEnv* env = jniEnv();
624
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700625 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.virtualKeyDownFeedback);
626 checkAndClearExceptionFromCallback(env, "virtualKeyDownFeedback");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700627}
628
629int32_t NativeInputManager::interceptKey(nsecs_t when,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700630 int32_t deviceId, bool down, int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700631#if DEBUG_INPUT_READER_POLICY
632 LOGD("interceptKey - when=%lld, deviceId=%d, down=%d, keyCode=%d, scanCode=%d, "
Jeff Brown349703e2010-06-22 01:27:15 -0700633 "policyFlags=0x%x",
Jeff Brown9c3cda02010-06-15 01:31:58 -0700634 when, deviceId, down, keyCode, scanCode, policyFlags);
635#endif
636
637 const int32_t WM_ACTION_PASS_TO_USER = 1;
638 const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2;
639 const int32_t WM_ACTION_GO_TO_SLEEP = 4;
640
Jeff Brown9c3cda02010-06-15 01:31:58 -0700641 bool isScreenOn = this->isScreenOn();
642 bool isScreenBright = this->isScreenBright();
643
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700644 jint wmActions = 0;
645 if (isPolicyKey(keyCode, isScreenOn)) {
646 JNIEnv* env = jniEnv();
647
648 wmActions = env->CallIntMethod(mCallbacksObj,
649 gCallbacksClassInfo.interceptKeyBeforeQueueing,
650 when, keyCode, down, policyFlags, isScreenOn);
651 if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
652 wmActions = 0;
653 }
654 } else {
655 wmActions = WM_ACTION_PASS_TO_USER;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700656 }
657
658 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
659 if (! isScreenOn) {
660 // Key presses and releases wake the device.
Jeff Brown6d0fec22010-07-23 21:28:06 -0700661 policyFlags |= POLICY_FLAG_WOKE_HERE;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700662 }
663
664 if (! isScreenBright) {
665 // Key presses and releases brighten the screen if dimmed.
Jeff Brown6d0fec22010-07-23 21:28:06 -0700666 policyFlags |= POLICY_FLAG_BRIGHT_HERE;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700667 }
668
669 if (wmActions & WM_ACTION_GO_TO_SLEEP) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700670 android_server_PowerManagerService_goToSleep(when);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700671 }
672
673 if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
Jeff Brown349703e2010-06-22 01:27:15 -0700674 pokeUserActivity(when, POWER_MANAGER_BUTTON_EVENT);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700675 }
676
677 if (wmActions & WM_ACTION_PASS_TO_USER) {
678 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700679
Jeff Brown9c3cda02010-06-15 01:31:58 -0700680 if (down && isAppSwitchKey(keyCode)) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700681 JNIEnv* env = jniEnv();
682
Jeff Brown9c3cda02010-06-15 01:31:58 -0700683 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyAppSwitchComing);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700684 checkAndClearExceptionFromCallback(env, "notifyAppSwitchComing");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700685
686 actions |= InputReaderPolicyInterface::ACTION_APP_SWITCH_COMING;
687 }
688 }
Jeff Brown349703e2010-06-22 01:27:15 -0700689
Jeff Brown9c3cda02010-06-15 01:31:58 -0700690 return actions;
691}
692
Jeff Brown6d0fec22010-07-23 21:28:06 -0700693int32_t NativeInputManager::interceptGeneric(nsecs_t when, uint32_t& policyFlags) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700694#if DEBUG_INPUT_READER_POLICY
Jeff Brown6d0fec22010-07-23 21:28:06 -0700695 LOGD("interceptGeneric - when=%lld, policyFlags=0x%x", when, policyFlags);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700696#endif
697
Jeff Brown5c225b12010-06-16 01:53:36 -0700698 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
699 if (isScreenOn()) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700700 // Only dispatch events when the device is awake.
Jeff Brown349703e2010-06-22 01:27:15 -0700701 // Do not wake the device.
Jeff Brown5c225b12010-06-16 01:53:36 -0700702 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700703
Jeff Brown349703e2010-06-22 01:27:15 -0700704 if (! isScreenBright()) {
705 // Brighten the screen if dimmed.
Jeff Brown6d0fec22010-07-23 21:28:06 -0700706 policyFlags |= POLICY_FLAG_BRIGHT_HERE;
Jeff Brown349703e2010-06-22 01:27:15 -0700707 }
Jeff Brown5c225b12010-06-16 01:53:36 -0700708 }
709
710 return actions;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700711}
712
713int32_t NativeInputManager::interceptSwitch(nsecs_t when, int32_t switchCode,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700714 int32_t switchValue, uint32_t& policyFlags) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700715#if DEBUG_INPUT_READER_POLICY
Jeff Brown6d0fec22010-07-23 21:28:06 -0700716 LOGD("interceptSwitch - when=%lld, switchCode=%d, switchValue=%d, policyFlags=0x%x",
717 when, switchCode, switchValue, policyFlags);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700718#endif
719
720 JNIEnv* env = jniEnv();
721
722 switch (switchCode) {
723 case SW_LID:
724 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyLidSwitchChanged,
725 when, switchValue == 0);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700726 checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700727 break;
728 }
729
730 return InputReaderPolicyInterface::ACTION_NONE;
731}
732
733bool NativeInputManager::filterTouchEvents() {
734 if (mFilterTouchEvents < 0) {
735 JNIEnv* env = jniEnv();
736
737 jboolean result = env->CallBooleanMethod(mCallbacksObj,
738 gCallbacksClassInfo.filterTouchEvents);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700739 if (checkAndClearExceptionFromCallback(env, "filterTouchEvents")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700740 result = false;
741 }
742
743 mFilterTouchEvents = result ? 1 : 0;
744 }
745 return mFilterTouchEvents;
746}
747
748bool NativeInputManager::filterJumpyTouchEvents() {
749 if (mFilterJumpyTouchEvents < 0) {
750 JNIEnv* env = jniEnv();
751
752 jboolean result = env->CallBooleanMethod(mCallbacksObj,
753 gCallbacksClassInfo.filterJumpyTouchEvents);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700754 if (checkAndClearExceptionFromCallback(env, "filterJumpyTouchEvents")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700755 result = false;
756 }
757
758 mFilterJumpyTouchEvents = result ? 1 : 0;
759 }
760 return mFilterJumpyTouchEvents;
761}
762
763void NativeInputManager::getVirtualKeyDefinitions(const String8& deviceName,
764 Vector<InputReaderPolicyInterface::VirtualKeyDefinition>& outVirtualKeyDefinitions) {
765 JNIEnv* env = jniEnv();
766
767 jstring deviceNameStr = env->NewStringUTF(deviceName.string());
Jeff Brown7fbdc842010-06-17 20:52:56 -0700768 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700769 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
770 gCallbacksClassInfo.getVirtualKeyDefinitions, deviceNameStr));
Jeff Brown7fbdc842010-06-17 20:52:56 -0700771 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions") && result) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700772 jsize length = env->GetArrayLength(result);
773 for (jsize i = 0; i < length; i++) {
774 jobject item = env->GetObjectArrayElement(result, i);
775
776 outVirtualKeyDefinitions.add();
777 outVirtualKeyDefinitions.editTop().scanCode =
778 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.scanCode));
779 outVirtualKeyDefinitions.editTop().centerX =
780 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerX));
781 outVirtualKeyDefinitions.editTop().centerY =
782 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerY));
783 outVirtualKeyDefinitions.editTop().width =
784 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.width));
785 outVirtualKeyDefinitions.editTop().height =
786 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.height));
787
788 env->DeleteLocalRef(item);
789 }
790 env->DeleteLocalRef(result);
791 }
792 env->DeleteLocalRef(deviceNameStr);
793 }
794}
795
796void NativeInputManager::getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
797 JNIEnv* env = jniEnv();
798
799 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
800 gCallbacksClassInfo.getExcludedDeviceNames));
Jeff Brown7fbdc842010-06-17 20:52:56 -0700801 if (! checkAndClearExceptionFromCallback(env, "getExcludedDeviceNames") && result) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700802 jsize length = env->GetArrayLength(result);
803 for (jsize i = 0; i < length; i++) {
804 jstring item = jstring(env->GetObjectArrayElement(result, i));
805
806 const char* deviceNameChars = env->GetStringUTFChars(item, NULL);
807 outExcludedDeviceNames.add(String8(deviceNameChars));
808 env->ReleaseStringUTFChars(item, deviceNameChars);
809
810 env->DeleteLocalRef(item);
811 }
812 env->DeleteLocalRef(result);
813 }
814}
815
816void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
817#if DEBUG_INPUT_DISPATCHER_POLICY
818 LOGD("notifyConfigurationChanged - when=%lld", when);
819#endif
820
821 JNIEnv* env = jniEnv();
822
823 InputConfiguration config;
824 mInputManager->getInputConfiguration(& config);
825
826 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyConfigurationChanged,
827 when, config.touchScreen, config.keyboard, config.navigation);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700828 checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700829}
830
831void NativeInputManager::notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
832#if DEBUG_INPUT_DISPATCHER_POLICY
833 LOGD("notifyInputChannelBroken - inputChannel='%s'", inputChannel->getName().string());
834#endif
835
Jeff Brown7fbdc842010-06-17 20:52:56 -0700836 JNIEnv* env = jniEnv();
837
838 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
839 if (inputChannelObjLocal) {
840 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelBroken,
841 inputChannelObjLocal);
842 checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken");
843
844 env->DeleteLocalRef(inputChannelObjLocal);
845 }
Jeff Browna41ca772010-08-11 14:46:32 -0700846
847 unregisterMonitoringChannel(inputChannel);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700848}
849
Jeff Brown7fbdc842010-06-17 20:52:56 -0700850bool NativeInputManager::notifyInputChannelANR(const sp<InputChannel>& inputChannel,
851 nsecs_t& outNewTimeout) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700852#if DEBUG_INPUT_DISPATCHER_POLICY
853 LOGD("notifyInputChannelANR - inputChannel='%s'",
854 inputChannel->getName().string());
855#endif
856
Jeff Brown7fbdc842010-06-17 20:52:56 -0700857 JNIEnv* env = jniEnv();
858
859 jlong newTimeout;
860 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
861 if (inputChannelObjLocal) {
862 newTimeout = env->CallLongMethod(mCallbacksObj,
863 gCallbacksClassInfo.notifyInputChannelANR, inputChannelObjLocal);
864 if (checkAndClearExceptionFromCallback(env, "notifyInputChannelANR")) {
865 newTimeout = -2;
866 }
867
868 env->DeleteLocalRef(inputChannelObjLocal);
869 } else {
870 newTimeout = -2;
871 }
872
873 if (newTimeout == -2) {
874 return false; // abort
875 }
876
877 outNewTimeout = newTimeout;
878 return true; // resume
Jeff Brown9c3cda02010-06-15 01:31:58 -0700879}
880
881void NativeInputManager::notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel) {
882#if DEBUG_INPUT_DISPATCHER_POLICY
883 LOGD("notifyInputChannelRecoveredFromANR - inputChannel='%s'",
884 inputChannel->getName().string());
885#endif
886
Jeff Brown7fbdc842010-06-17 20:52:56 -0700887 JNIEnv* env = jniEnv();
888
889 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
890 if (inputChannelObjLocal) {
891 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelRecoveredFromANR,
892 inputChannelObjLocal);
893 checkAndClearExceptionFromCallback(env, "notifyInputChannelRecoveredFromANR");
894
895 env->DeleteLocalRef(inputChannelObjLocal);
896 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700897}
898
Jeff Brown349703e2010-06-22 01:27:15 -0700899bool NativeInputManager::notifyANR(jobject tokenObj, nsecs_t& outNewTimeout) {
900#if DEBUG_INPUT_DISPATCHER_POLICY
901 LOGD("notifyANR");
902#endif
903
904 JNIEnv* env = jniEnv();
905
906 jlong newTimeout = env->CallLongMethod(mCallbacksObj,
907 gCallbacksClassInfo.notifyANR, tokenObj);
908 if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
909 newTimeout = -2;
910 }
911
912 if (newTimeout == -2) {
913 return false; // abort
914 }
915
916 outNewTimeout = newTimeout;
917 return true; // resume
918}
919
Jeff Brown9c3cda02010-06-15 01:31:58 -0700920nsecs_t NativeInputManager::getKeyRepeatTimeout() {
921 if (! isScreenOn()) {
922 // Disable key repeat when the screen is off.
923 return -1;
924 } else {
925 // TODO use ViewConfiguration.getLongPressTimeout()
926 return milliseconds_to_nanoseconds(500);
927 }
928}
929
Jeff Brownae9fc032010-08-18 15:51:08 -0700930int32_t NativeInputManager::getMaxEventsPerSecond() {
931 if (mMaxEventsPerSecond < 0) {
932 JNIEnv* env = jniEnv();
933
934 jint result = env->CallIntMethod(mCallbacksObj,
935 gCallbacksClassInfo.getMaxEventsPerSecond);
936 if (checkAndClearExceptionFromCallback(env, "getMaxEventsPerSecond")) {
Jeff Brown3d8c9bd2010-08-18 17:48:53 -0700937 result = 60;
Jeff Brownae9fc032010-08-18 15:51:08 -0700938 }
939
940 mMaxEventsPerSecond = result;
941 }
942 return mMaxEventsPerSecond;
943}
944
Jeff Brown349703e2010-06-22 01:27:15 -0700945void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArray) {
946#if DEBUG_FOCUS
947 LOGD("setInputWindows");
948#endif
949 { // acquire lock
950 AutoMutex _l(mDispatchLock);
951
952 sp<InputChannel> touchedWindowChannel;
953 if (mTouchedWindow) {
954 touchedWindowChannel = mTouchedWindow->inputChannel;
955 mTouchedWindow = NULL;
956 }
957 size_t numTouchedWallpapers = mTouchedWallpaperWindows.size();
958 if (numTouchedWallpapers != 0) {
959 for (size_t i = 0; i < numTouchedWallpapers; i++) {
960 mTempTouchedWallpaperChannels.push(mTouchedWallpaperWindows[i]->inputChannel);
961 }
962 mTouchedWallpaperWindows.clear();
963 }
964
Jeff Browne33348b2010-07-15 23:54:05 -0700965 bool hadFocusedWindow = mFocusedWindow != NULL;
966
Jeff Brown349703e2010-06-22 01:27:15 -0700967 mWindows.clear();
968 mFocusedWindow = NULL;
969 mWallpaperWindows.clear();
970
971 if (windowObjArray) {
972 mWindowsReady = true;
973
974 jsize length = env->GetArrayLength(windowObjArray);
975 for (jsize i = 0; i < length; i++) {
976 jobject inputTargetObj = env->GetObjectArrayElement(windowObjArray, i);
977 if (! inputTargetObj) {
978 break; // found null element indicating end of used portion of the array
979 }
980
981 mWindows.push();
982 InputWindow& window = mWindows.editTop();
983 bool valid = populateWindow(env, inputTargetObj, window);
984 if (! valid) {
985 mWindows.pop();
986 }
987
988 env->DeleteLocalRef(inputTargetObj);
989 }
990
991 size_t numWindows = mWindows.size();
992 for (size_t i = 0; i < numWindows; i++) {
993 InputWindow* window = & mWindows.editItemAt(i);
994 if (window->hasFocus) {
995 mFocusedWindow = window;
996 }
997
998 if (window->layoutParamsType == TYPE_WALLPAPER) {
999 mWallpaperWindows.push(window);
1000
1001 for (size_t j = 0; j < numTouchedWallpapers; j++) {
1002 if (window->inputChannel == mTempTouchedWallpaperChannels[i]) {
1003 mTouchedWallpaperWindows.push(window);
1004 }
1005 }
1006 }
1007
1008 if (window->inputChannel == touchedWindowChannel) {
1009 mTouchedWindow = window;
1010 }
1011 }
1012 } else {
1013 mWindowsReady = false;
1014 }
1015
1016 mTempTouchedWallpaperChannels.clear();
1017
Jeff Brown00ba8842010-07-16 15:01:56 -07001018 if ((hadFocusedWindow && ! mFocusedWindow)
1019 || (mFocusedWindow && ! mFocusedWindow->visible)) {
Jeff Browne33348b2010-07-15 23:54:05 -07001020 preemptInputDispatch();
1021 }
1022
Jeff Brown349703e2010-06-22 01:27:15 -07001023 mDispatchStateChanged.broadcast();
1024
1025#if DEBUG_FOCUS
Jeff Browne33348b2010-07-15 23:54:05 -07001026 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001027#endif
1028 } // release lock
1029}
1030
1031bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj,
1032 InputWindow& outWindow) {
1033 bool valid = false;
1034
1035 jobject inputChannelObj = env->GetObjectField(windowObj,
1036 gInputWindowClassInfo.inputChannel);
1037 if (inputChannelObj) {
1038 sp<InputChannel> inputChannel =
1039 android_view_InputChannel_getInputChannel(env, inputChannelObj);
1040 if (inputChannel != NULL) {
1041 jint layoutParamsFlags = env->GetIntField(windowObj,
1042 gInputWindowClassInfo.layoutParamsFlags);
1043 jint layoutParamsType = env->GetIntField(windowObj,
1044 gInputWindowClassInfo.layoutParamsType);
1045 jlong dispatchingTimeoutNanos = env->GetLongField(windowObj,
1046 gInputWindowClassInfo.dispatchingTimeoutNanos);
1047 jint frameLeft = env->GetIntField(windowObj,
1048 gInputWindowClassInfo.frameLeft);
1049 jint frameTop = env->GetIntField(windowObj,
1050 gInputWindowClassInfo.frameTop);
1051 jint touchableAreaLeft = env->GetIntField(windowObj,
1052 gInputWindowClassInfo.touchableAreaLeft);
1053 jint touchableAreaTop = env->GetIntField(windowObj,
1054 gInputWindowClassInfo.touchableAreaTop);
1055 jint touchableAreaRight = env->GetIntField(windowObj,
1056 gInputWindowClassInfo.touchableAreaRight);
1057 jint touchableAreaBottom = env->GetIntField(windowObj,
1058 gInputWindowClassInfo.touchableAreaBottom);
1059 jboolean visible = env->GetBooleanField(windowObj,
1060 gInputWindowClassInfo.visible);
1061 jboolean hasFocus = env->GetBooleanField(windowObj,
1062 gInputWindowClassInfo.hasFocus);
1063 jboolean hasWallpaper = env->GetBooleanField(windowObj,
1064 gInputWindowClassInfo.hasWallpaper);
1065 jboolean paused = env->GetBooleanField(windowObj,
1066 gInputWindowClassInfo.paused);
1067 jint ownerPid = env->GetIntField(windowObj,
1068 gInputWindowClassInfo.ownerPid);
1069 jint ownerUid = env->GetIntField(windowObj,
1070 gInputWindowClassInfo.ownerUid);
1071
1072 outWindow.inputChannel = inputChannel;
1073 outWindow.layoutParamsFlags = layoutParamsFlags;
1074 outWindow.layoutParamsType = layoutParamsType;
1075 outWindow.dispatchingTimeout = dispatchingTimeoutNanos;
1076 outWindow.frameLeft = frameLeft;
1077 outWindow.frameTop = frameTop;
1078 outWindow.touchableAreaLeft = touchableAreaLeft;
1079 outWindow.touchableAreaTop = touchableAreaTop;
1080 outWindow.touchableAreaRight = touchableAreaRight;
1081 outWindow.touchableAreaBottom = touchableAreaBottom;
1082 outWindow.visible = visible;
1083 outWindow.hasFocus = hasFocus;
1084 outWindow.hasWallpaper = hasWallpaper;
1085 outWindow.paused = paused;
1086 outWindow.ownerPid = ownerPid;
1087 outWindow.ownerUid = ownerUid;
1088 valid = true;
1089 } else {
1090 LOGW("Dropping input target because its input channel is not initialized.");
1091 }
1092
1093 env->DeleteLocalRef(inputChannelObj);
1094 } else {
1095 LOGW("Dropping input target because the input channel object was null.");
1096 }
1097 return valid;
1098}
1099
1100void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) {
1101#if DEBUG_FOCUS
1102 LOGD("setFocusedApplication");
1103#endif
1104 { // acquire lock
1105 AutoMutex _l(mDispatchLock);
1106
1107 releaseFocusedApplicationLd(env);
1108
1109 if (applicationObj) {
1110 jstring nameObj = jstring(env->GetObjectField(applicationObj,
1111 gInputApplicationClassInfo.name));
1112 jlong dispatchingTimeoutNanos = env->GetLongField(applicationObj,
1113 gInputApplicationClassInfo.dispatchingTimeoutNanos);
1114 jobject tokenObj = env->GetObjectField(applicationObj,
1115 gInputApplicationClassInfo.token);
1116 jweak tokenObjWeak = env->NewWeakGlobalRef(tokenObj);
1117 if (! tokenObjWeak) {
1118 LOGE("Could not create weak reference for application token.");
1119 LOGE_EX(env);
1120 env->ExceptionClear();
1121 }
1122 env->DeleteLocalRef(tokenObj);
1123
1124 mFocusedApplication = & mFocusedApplicationStorage;
1125
1126 if (nameObj) {
1127 const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
1128 mFocusedApplication->name.setTo(nameStr);
1129 env->ReleaseStringUTFChars(nameObj, nameStr);
1130 env->DeleteLocalRef(nameObj);
1131 } else {
1132 LOGE("InputApplication.name should not be null.");
1133 mFocusedApplication->name.setTo("unknown");
1134 }
1135
1136 mFocusedApplication->dispatchingTimeout = dispatchingTimeoutNanos;
1137 mFocusedApplication->tokenObjWeak = tokenObjWeak;
1138 }
1139
1140 mDispatchStateChanged.broadcast();
1141
1142#if DEBUG_FOCUS
Jeff Browne33348b2010-07-15 23:54:05 -07001143 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001144#endif
1145 } // release lock
1146}
1147
1148void NativeInputManager::releaseFocusedApplicationLd(JNIEnv* env) {
1149 if (mFocusedApplication) {
1150 env->DeleteWeakGlobalRef(mFocusedApplication->tokenObjWeak);
1151 mFocusedApplication = NULL;
1152 }
1153}
1154
1155void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
1156#if DEBUG_FOCUS
1157 LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001158#endif
1159
Jeff Brown349703e2010-06-22 01:27:15 -07001160 { // acquire lock
1161 AutoMutex _l(mDispatchLock);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001162
Jeff Brown349703e2010-06-22 01:27:15 -07001163 if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
1164 mDispatchEnabled = enabled;
1165 mDispatchFrozen = frozen;
1166
1167 mDispatchStateChanged.broadcast();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001168 }
Jeff Brown349703e2010-06-22 01:27:15 -07001169
1170#if DEBUG_FOCUS
Jeff Browne33348b2010-07-15 23:54:05 -07001171 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001172#endif
1173 } // release lock
1174}
1175
1176void NativeInputManager::preemptInputDispatch() {
1177#if DEBUG_FOCUS
1178 LOGD("preemptInputDispatch");
1179#endif
1180
1181 mInputManager->preemptInputDispatch();
1182}
1183
1184int32_t NativeInputManager::waitForFocusedWindowLd(uint32_t policyFlags,
1185 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
1186 InputWindow*& outFocusedWindow) {
1187
1188 int32_t injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1189 bool firstIteration = true;
1190 ANRTimer anrTimer;
1191 for (;;) {
1192 if (firstIteration) {
1193 firstIteration = false;
1194 } else {
1195 if (! anrTimer.waitForDispatchStateChangeLd(this)) {
1196 LOGW("Dropping event because the dispatcher timed out waiting to identify "
1197 "the window that should receive it.");
1198 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1199 break;
1200 }
1201 }
1202
1203 // If dispatch is not enabled then fail.
1204 if (! mDispatchEnabled) {
1205 LOGI("Dropping event because input dispatch is disabled.");
1206 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1207 break;
1208 }
1209
1210 // If dispatch is frozen or we don't have valid window data yet then wait.
1211 if (mDispatchFrozen || ! mWindowsReady) {
1212#if DEBUG_FOCUS
1213 LOGD("Waiting because dispatch is frozen or windows are not ready.");
1214#endif
1215 anrTimer.dispatchFrozenBySystem();
1216 continue;
1217 }
1218
1219 // If there is no currently focused window and no focused application
1220 // then drop the event.
1221 if (! mFocusedWindow) {
1222 if (mFocusedApplication) {
1223#if DEBUG_FOCUS
1224 LOGD("Waiting because there is no focused window but there is a "
1225 "focused application that may yet introduce a new target: '%s'.",
1226 mFocusedApplication->name.string());
1227#endif
1228 continue;
1229 }
1230
1231 LOGI("Dropping event because there is no focused window or focused application.");
1232 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1233 break;
1234 }
1235
1236 // Check permissions.
1237 if (! checkInjectionPermission(mFocusedWindow, injectorPid, injectorUid)) {
1238 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1239 break;
1240 }
1241
1242 // If the currently focused window is paused then keep waiting.
1243 if (mFocusedWindow->paused) {
1244#if DEBUG_FOCUS
1245 LOGD("Waiting because focused window is paused.");
1246#endif
1247 anrTimer.dispatchPausedByApplication(mFocusedWindow);
1248 continue;
1249 }
1250
1251 // Success!
1252 break; // done waiting, exit loop
Jeff Brown9c3cda02010-06-15 01:31:58 -07001253 }
Jeff Brown349703e2010-06-22 01:27:15 -07001254
1255 // Output targets.
1256 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
1257 addTarget(mFocusedWindow, InputTarget::FLAG_SYNC,
1258 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
1259
1260 outFocusedWindow = mFocusedWindow;
1261 } else {
1262 outFocusedWindow = NULL;
1263 }
1264
1265#if DEBUG_FOCUS
1266 LOGD("waitForFocusedWindow finished: injectionResult=%d",
1267 injectionResult);
Jeff Browne33348b2010-07-15 23:54:05 -07001268 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001269#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001270 return injectionResult;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001271}
1272
Jeff Brownc5ed5912010-07-14 18:48:53 -07001273enum InjectionPermission {
1274 INJECTION_PERMISSION_UNKNOWN,
1275 INJECTION_PERMISSION_GRANTED,
1276 INJECTION_PERMISSION_DENIED
1277};
1278
Jeff Brown349703e2010-06-22 01:27:15 -07001279int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
1280 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
1281 InputWindow*& outTouchedWindow) {
1282 nsecs_t startTime = now();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001283
Jeff Brown349703e2010-06-22 01:27:15 -07001284 // For security reasons, we defer updating the touch state until we are sure that
1285 // event injection will be allowed.
1286 //
1287 // FIXME In the original code, screenWasOff could never be set to true.
1288 // The reason is that the POLICY_FLAG_WOKE_HERE
1289 // and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
1290 // EV_KEY, EV_REL and EV_ABS events. As it happens, the touch event was
1291 // actually enqueued using the policyFlags that appeared in the final EV_SYN
1292 // events upon which no preprocessing took place. So policyFlags was always 0.
1293 // In the new native input dispatcher we're a bit more careful about event
1294 // preprocessing so the touches we receive can actually have non-zero policyFlags.
1295 // Unfortunately we obtain undesirable behavior.
1296 //
1297 // Here's what happens:
1298 //
1299 // When the device dims in anticipation of going to sleep, touches
1300 // in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
1301 // the device to brighten and reset the user activity timer.
1302 // Touches on other windows (such as the launcher window)
1303 // are dropped. Then after a moment, the device goes to sleep. Oops.
1304 //
1305 // Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
1306 // instead of POLICY_FLAG_WOKE_HERE...
1307 //
1308 bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001309
1310 int32_t action = motionEvent->getAction();
1311
Jeff Brown349703e2010-06-22 01:27:15 -07001312 bool firstIteration = true;
1313 ANRTimer anrTimer;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001314 int32_t injectionResult;
1315 InjectionPermission injectionPermission;
Jeff Brown349703e2010-06-22 01:27:15 -07001316 for (;;) {
1317 if (firstIteration) {
1318 firstIteration = false;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001319 } else {
Jeff Brown349703e2010-06-22 01:27:15 -07001320 if (! anrTimer.waitForDispatchStateChangeLd(this)) {
1321 LOGW("Dropping event because the dispatcher timed out waiting to identify "
1322 "the window that should receive it.");
1323 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001324 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
1325 break; // timed out, exit wait loop
Jeff Brown349703e2010-06-22 01:27:15 -07001326 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001327 }
Jeff Brown349703e2010-06-22 01:27:15 -07001328
1329 // If dispatch is not enabled then fail.
1330 if (! mDispatchEnabled) {
1331 LOGI("Dropping event because input dispatch is disabled.");
1332 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001333 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
Jeff Brown349703e2010-06-22 01:27:15 -07001334 break; // failed, exit wait loop
1335 }
1336
1337 // If dispatch is frozen or we don't have valid window data yet then wait.
1338 if (mDispatchFrozen || ! mWindowsReady) {
1339#if DEBUG_INPUT_DISPATCHER_POLICY
1340 LOGD("Waiting because dispatch is frozen or windows are not ready.");
1341#endif
1342 anrTimer.dispatchFrozenBySystem();
1343 continue;
1344 }
1345
1346 // Update the touch state as needed based on the properties of the touch event.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001347 if (action == AMOTION_EVENT_ACTION_DOWN) {
1348 /* Case 1: ACTION_DOWN */
1349
Jeff Brown349703e2010-06-22 01:27:15 -07001350 InputWindow* newTouchedWindow = NULL;
1351 mTempTouchedOutsideWindows.clear();
1352
1353 int32_t x = int32_t(motionEvent->getX(0));
1354 int32_t y = int32_t(motionEvent->getY(0));
1355 InputWindow* topErrorWindow = NULL;
1356
1357 // Traverse windows from front to back to find touched window and outside targets.
1358 size_t numWindows = mWindows.size();
1359 for (size_t i = 0; i < numWindows; i++) {
1360 InputWindow* window = & mWindows.editItemAt(i);
1361 int32_t flags = window->layoutParamsFlags;
1362
1363 if (flags & FLAG_SYSTEM_ERROR) {
1364 if (! topErrorWindow) {
1365 topErrorWindow = window;
1366 }
1367 }
1368
1369 if (window->visible) {
1370 if (! (flags & FLAG_NOT_TOUCHABLE)) {
1371 bool isTouchModal = (flags &
1372 (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL)) == 0;
1373 if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
1374 if (! screenWasOff || flags & FLAG_TOUCHABLE_WHEN_WAKING) {
1375 newTouchedWindow = window;
1376 }
1377 break; // found touched window, exit window loop
1378 }
1379 }
1380
1381 if (flags & FLAG_WATCH_OUTSIDE_TOUCH) {
1382 mTempTouchedOutsideWindows.push(window);
1383 }
1384 }
1385 }
1386
1387 // If there is an error window but it is not taking focus (typically because
1388 // it is invisible) then wait for it. Any other focused window may in
1389 // fact be in ANR state.
1390 if (topErrorWindow && newTouchedWindow != topErrorWindow) {
1391#if DEBUG_INPUT_DISPATCHER_POLICY
1392 LOGD("Waiting because system error window is pending.");
1393#endif
1394 anrTimer.dispatchFrozenBySystem();
1395 continue; // wait some more
1396 }
1397
1398 // If we did not find a touched window then fail.
1399 if (! newTouchedWindow) {
1400 if (mFocusedApplication) {
1401#if DEBUG_FOCUS
1402 LOGD("Waiting because there is no focused window but there is a "
1403 "focused application that may yet introduce a new target: '%s'.",
1404 mFocusedApplication->name.string());
1405#endif
1406 continue;
1407 }
1408
1409 LOGI("Dropping event because there is no touched window or focused application.");
1410 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001411 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
Jeff Brown349703e2010-06-22 01:27:15 -07001412 break; // failed, exit wait loop
1413 }
1414
1415 // Check permissions.
1416 if (! checkInjectionPermission(newTouchedWindow, injectorPid, injectorUid)) {
1417 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001418 injectionPermission = INJECTION_PERMISSION_DENIED;
Jeff Brown349703e2010-06-22 01:27:15 -07001419 break; // failed, exit wait loop
1420 }
1421
1422 // If the touched window is paused then keep waiting.
1423 if (newTouchedWindow->paused) {
1424#if DEBUG_INPUT_DISPATCHER_POLICY
1425 LOGD("Waiting because touched window is paused.");
1426#endif
1427 anrTimer.dispatchPausedByApplication(newTouchedWindow);
1428 continue; // wait some more
1429 }
1430
1431 // Success! Update the touch dispatch state for real.
1432 releaseTouchedWindowLd();
1433
1434 mTouchedWindow = newTouchedWindow;
1435
1436 if (newTouchedWindow->hasWallpaper) {
1437 mTouchedWallpaperWindows.appendVector(mWallpaperWindows);
1438 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001439
1440 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1441 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001442 break; // done
1443 } else {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001444 /* Case 2: Everything but ACTION_DOWN */
1445
Jeff Brown349703e2010-06-22 01:27:15 -07001446 // Check permissions.
1447 if (! checkInjectionPermission(mTouchedWindow, injectorPid, injectorUid)) {
1448 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001449 injectionPermission = INJECTION_PERMISSION_DENIED;
1450 break; // failed, exit wait loop
1451 }
1452
1453 // If the pointer is not currently down, then ignore the event.
1454 if (! mTouchDown) {
1455 LOGI("Dropping event because the pointer is not down.");
1456 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1457 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001458 break; // failed, exit wait loop
1459 }
1460
1461 // If there is no currently touched window then fail.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001462 if (! mTouchedWindow) {
Jeff Browna41ca772010-08-11 14:46:32 -07001463#if DEBUG_INPUT_DISPATCHER_POLICY
1464 LOGD("Dropping event because there is no touched window to receive it.");
1465#endif
Jeff Brown349703e2010-06-22 01:27:15 -07001466 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001467 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001468 break; // failed, exit wait loop
1469 }
1470
1471 // If the touched window is paused then keep waiting.
1472 if (mTouchedWindow->paused) {
1473#if DEBUG_INPUT_DISPATCHER_POLICY
1474 LOGD("Waiting because touched window is paused.");
1475#endif
1476 anrTimer.dispatchPausedByApplication(mTouchedWindow);
1477 continue; // wait some more
1478 }
1479
1480 // Success!
Jeff Brownc5ed5912010-07-14 18:48:53 -07001481 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1482 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001483 break; // done
1484 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001485 }
Jeff Brown349703e2010-06-22 01:27:15 -07001486
1487 // Output targets.
Jeff Brown349703e2010-06-22 01:27:15 -07001488 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
Jeff Brown349703e2010-06-22 01:27:15 -07001489 size_t numWallpaperWindows = mTouchedWallpaperWindows.size();
1490 for (size_t i = 0; i < numWallpaperWindows; i++) {
1491 addTarget(mTouchedWallpaperWindows[i], 0, 0, outTargets);
1492 }
1493
1494 size_t numOutsideWindows = mTempTouchedOutsideWindows.size();
1495 for (size_t i = 0; i < numOutsideWindows; i++) {
1496 addTarget(mTempTouchedOutsideWindows[i], InputTarget::FLAG_OUTSIDE, 0, outTargets);
1497 }
1498
1499 addTarget(mTouchedWindow, InputTarget::FLAG_SYNC,
1500 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
1501 outTouchedWindow = mTouchedWindow;
1502 } else {
Jeff Brown349703e2010-06-22 01:27:15 -07001503 outTouchedWindow = NULL;
1504 }
1505 mTempTouchedOutsideWindows.clear();
1506
Jeff Brownc5ed5912010-07-14 18:48:53 -07001507 // Check injection permission once and for all.
1508 if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
1509 if (checkInjectionPermission(action == AMOTION_EVENT_ACTION_DOWN ? NULL : mTouchedWindow,
1510 injectorPid, injectorUid)) {
1511 injectionPermission = INJECTION_PERMISSION_GRANTED;
1512 } else {
1513 injectionPermission = INJECTION_PERMISSION_DENIED;
1514 }
1515 }
1516
1517 // Update final pieces of touch state if the injector had permission.
1518 if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
1519 if (action == AMOTION_EVENT_ACTION_DOWN) {
Jeff Brown349703e2010-06-22 01:27:15 -07001520 if (mTouchDown) {
1521 // This is weird. We got a down but we thought it was already down!
1522 LOGW("Pointer down received while already down.");
1523 } else {
1524 mTouchDown = true;
1525 }
1526
1527 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1528 // Since we failed to identify a target for this touch down, we may still
1529 // be holding on to an earlier target from a previous touch down. Release it.
1530 releaseTouchedWindowLd();
1531 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001532 } else if (action == AMOTION_EVENT_ACTION_UP) {
Jeff Brown349703e2010-06-22 01:27:15 -07001533 mTouchDown = false;
1534 releaseTouchedWindowLd();
1535 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001536 } else {
1537 LOGW("Not updating touch focus because injection was denied.");
Jeff Brown349703e2010-06-22 01:27:15 -07001538 }
1539
1540#if DEBUG_FOCUS
1541 LOGD("waitForTouchedWindow finished: injectionResult=%d",
1542 injectionResult);
Jeff Browne33348b2010-07-15 23:54:05 -07001543 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001544#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001545 return injectionResult;
1546}
1547
Jeff Brown349703e2010-06-22 01:27:15 -07001548void NativeInputManager::releaseTouchedWindowLd() {
1549 mTouchedWindow = NULL;
1550 mTouchedWallpaperWindows.clear();
1551}
1552
1553void NativeInputManager::addTarget(const InputWindow* window, int32_t targetFlags,
1554 nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets) {
1555 nsecs_t timeout = window->dispatchingTimeout - timeSpentWaitingForApplication;
1556 if (timeout < MIN_INPUT_DISPATCHING_TIMEOUT) {
1557 timeout = MIN_INPUT_DISPATCHING_TIMEOUT;
1558 }
1559
1560 outTargets.push();
1561
1562 InputTarget& target = outTargets.editTop();
1563 target.inputChannel = window->inputChannel;
1564 target.flags = targetFlags;
1565 target.timeout = timeout;
1566 target.xOffset = - window->frameLeft;
1567 target.yOffset = - window->frameTop;
1568}
1569
1570bool NativeInputManager::checkInjectionPermission(const InputWindow* window,
1571 int32_t injectorPid, int32_t injectorUid) {
1572 if (injectorUid > 0 && (window == NULL || window->ownerUid != injectorUid)) {
1573 JNIEnv* env = jniEnv();
1574 jboolean result = env->CallBooleanMethod(mCallbacksObj,
1575 gCallbacksClassInfo.checkInjectEventsPermission, injectorPid, injectorUid);
1576 checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission");
1577
1578 if (! result) {
1579 if (window) {
1580 LOGW("Permission denied: injecting event from pid %d uid %d to window "
1581 "with input channel %s owned by uid %d",
1582 injectorPid, injectorUid, window->inputChannel->getName().string(),
1583 window->ownerUid);
1584 } else {
1585 LOGW("Permission denied: injecting event from pid %d uid %d",
1586 injectorPid, injectorUid);
1587 }
1588 return false;
1589 }
1590 }
1591
1592 return true;
1593}
1594
1595int32_t NativeInputManager::waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
1596 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets) {
1597#if DEBUG_INPUT_DISPATCHER_POLICY
1598 LOGD("waitForKeyEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1599 policyFlags, injectorPid, injectorUid);
1600#endif
1601
1602 int32_t windowType;
1603 { // acquire lock
1604 AutoMutex _l(mDispatchLock);
1605
1606 InputWindow* focusedWindow;
1607 int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
1608 injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
1609 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1610 return injectionResult;
1611 }
1612
1613 windowType = focusedWindow->layoutParamsType;
1614 } // release lock
1615
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001616 if (isPolicyKey(keyEvent->getKeyCode(), isScreenOn())) {
1617 const InputTarget& target = outTargets.top();
1618 bool consumed = interceptKeyBeforeDispatching(target, keyEvent, policyFlags);
1619 if (consumed) {
1620 outTargets.clear();
1621 return INPUT_EVENT_INJECTION_SUCCEEDED;
1622 }
Jeff Browna41ca772010-08-11 14:46:32 -07001623
1624 addMonitoringTargetsLd(outTargets);
Jeff Brown349703e2010-06-22 01:27:15 -07001625 }
1626
1627 pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
1628 return INPUT_EVENT_INJECTION_SUCCEEDED;
1629}
1630
1631int32_t NativeInputManager::waitForMotionEventTargets(MotionEvent* motionEvent,
1632 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001633 Vector<InputTarget>& outTargets) {
Jeff Brown349703e2010-06-22 01:27:15 -07001634#if DEBUG_INPUT_DISPATCHER_POLICY
1635 LOGD("waitForMotionEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1636 policyFlags, injectorPid, injectorUid);
1637#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001638
Jeff Brownc5ed5912010-07-14 18:48:53 -07001639 int32_t source = motionEvent->getSource();
1640 if (source & AINPUT_SOURCE_CLASS_POINTER) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001641 return waitForTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
Jeff Brown349703e2010-06-22 01:27:15 -07001642 outTargets);
Jeff Brownc5ed5912010-07-14 18:48:53 -07001643 } else {
1644 return waitForNonTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
1645 outTargets);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001646 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001647}
1648
Jeff Brownc5ed5912010-07-14 18:48:53 -07001649int32_t NativeInputManager::waitForNonTouchEventTargets(MotionEvent* motionEvent,
Jeff Brown349703e2010-06-22 01:27:15 -07001650 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
1651 Vector<InputTarget>& outTargets) {
1652#if DEBUG_INPUT_DISPATCHER_POLICY
Jeff Brownc5ed5912010-07-14 18:48:53 -07001653 LOGD("waitForNonTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
Jeff Brown349703e2010-06-22 01:27:15 -07001654 policyFlags, injectorPid, injectorUid);
1655#endif
1656
1657 int32_t windowType;
1658 { // acquire lock
1659 AutoMutex _l(mDispatchLock);
1660
1661 InputWindow* focusedWindow;
1662 int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
1663 injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
1664 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1665 return injectionResult;
1666 }
1667
1668 windowType = focusedWindow->layoutParamsType;
Jeff Browna41ca772010-08-11 14:46:32 -07001669
1670 addMonitoringTargetsLd(outTargets);
Jeff Brown349703e2010-06-22 01:27:15 -07001671 } // release lock
1672
1673 pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
1674 return INPUT_EVENT_INJECTION_SUCCEEDED;
1675}
1676
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001677int32_t NativeInputManager::waitForTouchEventTargets(MotionEvent* motionEvent,
Jeff Brown349703e2010-06-22 01:27:15 -07001678 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
1679 Vector<InputTarget>& outTargets) {
1680#if DEBUG_INPUT_DISPATCHER_POLICY
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001681 LOGD("waitForTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
Jeff Brown349703e2010-06-22 01:27:15 -07001682 policyFlags, injectorPid, injectorUid);
1683#endif
1684
1685 int32_t windowType;
1686 { // acquire lock
1687 AutoMutex _l(mDispatchLock);
1688
1689 InputWindow* touchedWindow;
1690 int32_t injectionResult = waitForTouchedWindowLd(motionEvent, policyFlags,
1691 injectorPid, injectorUid, outTargets, /*out*/ touchedWindow);
1692 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1693 return injectionResult;
1694 }
1695
1696 windowType = touchedWindow->layoutParamsType;
Jeff Browna41ca772010-08-11 14:46:32 -07001697
1698 addMonitoringTargetsLd(outTargets);
Jeff Brown349703e2010-06-22 01:27:15 -07001699 } // release lock
1700
1701 int32_t eventType;
1702 switch (motionEvent->getAction()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001703 case AMOTION_EVENT_ACTION_DOWN:
Jeff Brown349703e2010-06-22 01:27:15 -07001704 eventType = POWER_MANAGER_TOUCH_EVENT;
1705 break;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001706 case AMOTION_EVENT_ACTION_UP:
Jeff Brown349703e2010-06-22 01:27:15 -07001707 eventType = POWER_MANAGER_TOUCH_UP_EVENT;
1708 break;
1709 default:
1710 if (motionEvent->getEventTime() - motionEvent->getDownTime()
1711 >= EVENT_IGNORE_DURATION) {
1712 eventType = POWER_MANAGER_TOUCH_EVENT;
1713 } else {
1714 eventType = POWER_MANAGER_LONG_TOUCH_EVENT;
1715 }
1716 break;
1717 }
1718 pokeUserActivityIfNeeded(windowType, eventType);
1719 return INPUT_EVENT_INJECTION_SUCCEEDED;
1720}
1721
Jeff Brownd0097872010-06-30 14:41:59 -07001722bool NativeInputManager::interceptKeyBeforeDispatching(const InputTarget& target,
1723 const KeyEvent* keyEvent, uint32_t policyFlags) {
1724 JNIEnv* env = jniEnv();
1725
1726 jobject inputChannelObj = getInputChannelObjLocal(env, target.inputChannel);
1727 if (inputChannelObj) {
1728 jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
1729 gCallbacksClassInfo.interceptKeyBeforeDispatching,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001730 inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(),
1731 keyEvent->getKeyCode(), keyEvent->getMetaState(),
Jeff Brownd0097872010-06-30 14:41:59 -07001732 keyEvent->getRepeatCount(), policyFlags);
1733 bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
1734
1735 env->DeleteLocalRef(inputChannelObj);
1736
1737 return consumed && ! error;
1738 } else {
1739 LOGW("Could not apply key dispatch policy because input channel '%s' is "
1740 "no longer valid.", target.inputChannel->getName().string());
1741 return false;
1742 }
1743}
1744
Jeff Brown349703e2010-06-22 01:27:15 -07001745void NativeInputManager::pokeUserActivityIfNeeded(int32_t windowType, int32_t eventType) {
1746 if (windowType != TYPE_KEYGUARD) {
1747 nsecs_t eventTime = now();
1748 pokeUserActivity(eventTime, eventType);
1749 }
1750}
1751
1752void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001753 android_server_PowerManagerService_userActivity(eventTime, eventType);
Jeff Brown349703e2010-06-22 01:27:15 -07001754}
1755
Jeff Browna41ca772010-08-11 14:46:32 -07001756void NativeInputManager::registerMonitoringChannel(const sp<InputChannel>& inputChannel) {
1757 { // acquire lock
1758 AutoMutex _l(mDispatchLock);
1759 mMonitoringChannels.push(inputChannel);
1760 } // release lock
1761}
1762
1763void NativeInputManager::unregisterMonitoringChannel(const sp<InputChannel>& inputChannel) {
1764 { // acquire lock
1765 AutoMutex _l(mDispatchLock);
1766
1767 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
1768 if (mMonitoringChannels[i] == inputChannel) {
1769 mMonitoringChannels.removeAt(i);
1770 break;
1771 }
1772 }
1773 } // release lock
1774}
1775
1776void NativeInputManager::addMonitoringTargetsLd(Vector<InputTarget>& outTargets) {
1777 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
1778 outTargets.push();
1779
1780 InputTarget& target = outTargets.editTop();
1781 target.inputChannel = mMonitoringChannels[i];
1782 target.flags = 0;
1783 target.timeout = -1;
1784 target.xOffset = 0;
1785 target.yOffset = 0;
1786 }
1787}
1788
Jeff Brown6d0fec22010-07-23 21:28:06 -07001789static void dumpMotionRange(String8& dump,
1790 const char* name, const InputDeviceInfo::MotionRange* range) {
1791 if (range) {
1792 dump.appendFormat(" %s = { min: %0.3f, max: %0.3f, flat: %0.3f, fuzz: %0.3f }\n",
1793 name, range->min, range->max, range->flat, range->fuzz);
1794 }
1795}
1796
1797#define DUMP_MOTION_RANGE(range) \
1798 dumpMotionRange(dump, #range, deviceInfo.getMotionRange(AINPUT_MOTION_RANGE_##range));
1799
1800void NativeInputManager::dumpDeviceInfo(String8& dump) {
1801 Vector<int32_t> deviceIds;
1802 mInputManager->getInputDeviceIds(deviceIds);
1803
1804 InputDeviceInfo deviceInfo;
1805 for (size_t i = 0; i < deviceIds.size(); i++) {
1806 int32_t deviceId = deviceIds[i];
1807
1808 status_t result = mInputManager->getInputDeviceInfo(deviceId, & deviceInfo);
1809 if (result == NAME_NOT_FOUND) {
1810 continue;
1811 } else if (result != OK) {
1812 dump.appendFormat(" ** Unexpected error %d getting information about input devices.\n",
1813 result);
1814 continue;
1815 }
1816
1817 dump.appendFormat(" Device %d: '%s'\n",
1818 deviceInfo.getId(), deviceInfo.getName().string());
1819 dump.appendFormat(" sources = 0x%08x\n",
1820 deviceInfo.getSources());
1821 dump.appendFormat(" keyboardType = %d\n",
1822 deviceInfo.getKeyboardType());
1823
1824 dump.append(" motion ranges:\n");
1825 DUMP_MOTION_RANGE(X);
1826 DUMP_MOTION_RANGE(Y);
1827 DUMP_MOTION_RANGE(PRESSURE);
1828 DUMP_MOTION_RANGE(SIZE);
1829 DUMP_MOTION_RANGE(TOUCH_MAJOR);
1830 DUMP_MOTION_RANGE(TOUCH_MINOR);
1831 DUMP_MOTION_RANGE(TOOL_MAJOR);
1832 DUMP_MOTION_RANGE(TOOL_MINOR);
1833 DUMP_MOTION_RANGE(ORIENTATION);
1834 }
1835}
1836
1837#undef DUMP_MOTION_RANGE
1838
Jeff Browne33348b2010-07-15 23:54:05 -07001839void NativeInputManager::logDispatchStateLd() {
1840 String8 dump;
1841 dumpDispatchStateLd(dump);
1842 LOGD("%s", dump.string());
1843}
1844
1845void NativeInputManager::dumpDispatchStateLd(String8& dump) {
1846 dump.appendFormat(" dispatchEnabled: %d\n", mDispatchEnabled);
1847 dump.appendFormat(" dispatchFrozen: %d\n", mDispatchFrozen);
1848 dump.appendFormat(" windowsReady: %d\n", mWindowsReady);
1849
Jeff Brown349703e2010-06-22 01:27:15 -07001850 if (mFocusedApplication) {
Jeff Browne33348b2010-07-15 23:54:05 -07001851 dump.appendFormat(" focusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001852 mFocusedApplication->name.string(),
1853 mFocusedApplication->dispatchingTimeout / 1000000.0);
1854 } else {
Jeff Browne33348b2010-07-15 23:54:05 -07001855 dump.append(" focusedApplication: <null>\n");
Jeff Brown349703e2010-06-22 01:27:15 -07001856 }
Jeff Browne33348b2010-07-15 23:54:05 -07001857 dump.appendFormat(" focusedWindow: '%s'\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001858 mFocusedWindow != NULL ? mFocusedWindow->inputChannel->getName().string() : "<null>");
Jeff Browne33348b2010-07-15 23:54:05 -07001859 dump.appendFormat(" touchedWindow: '%s', touchDown=%d\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001860 mTouchedWindow != NULL ? mTouchedWindow->inputChannel->getName().string() : "<null>",
1861 mTouchDown);
1862 for (size_t i = 0; i < mTouchedWallpaperWindows.size(); i++) {
Jeff Browne33348b2010-07-15 23:54:05 -07001863 dump.appendFormat(" touchedWallpaperWindows[%d]: '%s'\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001864 i, mTouchedWallpaperWindows[i]->inputChannel->getName().string());
1865 }
1866 for (size_t i = 0; i < mWindows.size(); i++) {
Jeff Browne33348b2010-07-15 23:54:05 -07001867 dump.appendFormat(" windows[%d]: '%s', paused=%d, hasFocus=%d, hasWallpaper=%d, "
1868 "visible=%d, flags=0x%08x, type=0x%08x, "
Jeff Brown349703e2010-06-22 01:27:15 -07001869 "frame=[%d,%d], touchableArea=[%d,%d][%d,%d], "
Jeff Browne33348b2010-07-15 23:54:05 -07001870 "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001871 i, mWindows[i].inputChannel->getName().string(),
1872 mWindows[i].paused, mWindows[i].hasFocus, mWindows[i].hasWallpaper,
1873 mWindows[i].visible, mWindows[i].layoutParamsFlags, mWindows[i].layoutParamsType,
1874 mWindows[i].frameLeft, mWindows[i].frameTop,
1875 mWindows[i].touchableAreaLeft, mWindows[i].touchableAreaTop,
1876 mWindows[i].touchableAreaRight, mWindows[i].touchableAreaBottom,
1877 mWindows[i].ownerPid, mWindows[i].ownerUid,
1878 mWindows[i].dispatchingTimeout / 1000000.0);
1879 }
Jeff Browna41ca772010-08-11 14:46:32 -07001880
1881 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
1882 dump.appendFormat(" monitoringChannel[%d]: '%s'\n",
1883 i, mMonitoringChannels[i]->getName().string());
1884 }
Jeff Brown349703e2010-06-22 01:27:15 -07001885}
1886
1887// ----------------------------------------------------------------------------
1888
1889NativeInputManager::ANRTimer::ANRTimer() :
1890 mBudget(APPLICATION), mStartTime(now()), mFrozen(false), mPausedWindow(NULL) {
1891}
1892
1893void NativeInputManager::ANRTimer::dispatchFrozenBySystem() {
1894 mFrozen = true;
1895}
1896
1897void NativeInputManager::ANRTimer::dispatchPausedByApplication(InputWindow* pausedWindow) {
1898 mPausedWindow = pausedWindow;
1899}
1900
1901bool NativeInputManager::ANRTimer::waitForDispatchStateChangeLd(NativeInputManager* inputManager) {
1902 nsecs_t currentTime = now();
1903
1904 Budget newBudget;
1905 nsecs_t dispatchingTimeout;
1906 sp<InputChannel> pausedChannel = NULL;
1907 jobject tokenObj = NULL;
1908 if (mFrozen) {
1909 newBudget = SYSTEM;
1910 dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
1911 mFrozen = false;
1912 } else if (mPausedWindow) {
1913 newBudget = APPLICATION;
1914 dispatchingTimeout = mPausedWindow->dispatchingTimeout;
1915 pausedChannel = mPausedWindow->inputChannel;
1916 mPausedWindow = NULL;
1917 } else if (inputManager->mFocusedApplication) {
1918 newBudget = APPLICATION;
1919 dispatchingTimeout = inputManager->mFocusedApplication->dispatchingTimeout;
1920 tokenObj = jniEnv()->NewLocalRef(inputManager->mFocusedApplication->tokenObjWeak);
1921 } else {
1922 newBudget = APPLICATION;
1923 dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
1924 }
1925
1926 if (mBudget != newBudget) {
1927 mBudget = newBudget;
1928 mStartTime = currentTime;
1929 }
1930
1931 bool result = false;
1932 nsecs_t timeoutRemaining = mStartTime + dispatchingTimeout - currentTime;
1933 if (timeoutRemaining > 0
1934 && inputManager->mDispatchStateChanged.waitRelative(inputManager->mDispatchLock,
1935 timeoutRemaining) == OK) {
1936 result = true;
1937 } else {
1938 if (pausedChannel != NULL || tokenObj != NULL) {
1939 bool resumed;
1940 nsecs_t newTimeout = 0;
1941
1942 inputManager->mDispatchLock.unlock(); // release lock
1943 if (pausedChannel != NULL) {
1944 resumed = inputManager->notifyInputChannelANR(pausedChannel, /*out*/ newTimeout);
1945 } else {
1946 resumed = inputManager->notifyANR(tokenObj, /*out*/ newTimeout);
1947 }
1948 inputManager->mDispatchLock.lock(); // re-acquire lock
1949
1950 if (resumed) {
1951 mStartTime = now() - dispatchingTimeout + newTimeout;
1952 result = true;
1953 }
1954 }
1955 }
1956
1957 if (tokenObj) {
1958 jniEnv()->DeleteLocalRef(tokenObj);
1959 }
1960
1961 return result;
1962}
1963
1964nsecs_t NativeInputManager::ANRTimer::getTimeSpentWaitingForApplication() const {
1965 return mBudget == APPLICATION ? now() - mStartTime : 0;
1966}
Jeff Brown9c3cda02010-06-15 01:31:58 -07001967
1968// ----------------------------------------------------------------------------
1969
1970static sp<NativeInputManager> gNativeInputManager;
1971
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001972static bool checkInputManagerUnitialized(JNIEnv* env) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001973 if (gNativeInputManager == NULL) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001974 LOGE("Input manager not initialized.");
1975 jniThrowRuntimeException(env, "Input manager not initialized.");
1976 return true;
1977 }
1978 return false;
1979}
1980
1981static void android_server_InputManager_nativeInit(JNIEnv* env, jclass clazz,
1982 jobject callbacks) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001983 if (gNativeInputManager == NULL) {
1984 gNativeInputManager = new NativeInputManager(callbacks);
1985 } else {
1986 LOGE("Input manager already initialized.");
1987 jniThrowRuntimeException(env, "Input manager already initialized.");
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001988 }
1989}
1990
1991static void android_server_InputManager_nativeStart(JNIEnv* env, jclass clazz) {
1992 if (checkInputManagerUnitialized(env)) {
1993 return;
1994 }
1995
Jeff Brown9c3cda02010-06-15 01:31:58 -07001996 status_t result = gNativeInputManager->getInputManager()->start();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001997 if (result) {
1998 jniThrowRuntimeException(env, "Input manager could not be started.");
1999 }
2000}
2001
2002static void android_server_InputManager_nativeSetDisplaySize(JNIEnv* env, jclass clazz,
2003 jint displayId, jint width, jint height) {
2004 if (checkInputManagerUnitialized(env)) {
2005 return;
2006 }
2007
2008 // XXX we could get this from the SurfaceFlinger directly instead of requiring it
2009 // to be passed in like this, not sure which is better but leaving it like this
2010 // keeps the window manager in direct control of when display transitions propagate down
2011 // to the input dispatcher
Jeff Brown9c3cda02010-06-15 01:31:58 -07002012 gNativeInputManager->setDisplaySize(displayId, width, height);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002013}
2014
2015static void android_server_InputManager_nativeSetDisplayOrientation(JNIEnv* env, jclass clazz,
2016 jint displayId, jint orientation) {
2017 if (checkInputManagerUnitialized(env)) {
2018 return;
2019 }
2020
Jeff Brown9c3cda02010-06-15 01:31:58 -07002021 gNativeInputManager->setDisplayOrientation(displayId, orientation);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002022}
2023
2024static jint android_server_InputManager_nativeGetScanCodeState(JNIEnv* env, jclass clazz,
Jeff Brown6d0fec22010-07-23 21:28:06 -07002025 jint deviceId, jint sourceMask, jint scanCode) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002026 if (checkInputManagerUnitialized(env)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002027 return AKEY_STATE_UNKNOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002028 }
2029
Jeff Brown9c3cda02010-06-15 01:31:58 -07002030 return gNativeInputManager->getInputManager()->getScanCodeState(
Jeff Brown6d0fec22010-07-23 21:28:06 -07002031 deviceId, uint32_t(sourceMask), scanCode);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002032}
2033
2034static jint android_server_InputManager_nativeGetKeyCodeState(JNIEnv* env, jclass clazz,
Jeff Brown6d0fec22010-07-23 21:28:06 -07002035 jint deviceId, jint sourceMask, jint keyCode) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002036 if (checkInputManagerUnitialized(env)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002037 return AKEY_STATE_UNKNOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002038 }
2039
Jeff Brown9c3cda02010-06-15 01:31:58 -07002040 return gNativeInputManager->getInputManager()->getKeyCodeState(
Jeff Brown6d0fec22010-07-23 21:28:06 -07002041 deviceId, uint32_t(sourceMask), keyCode);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002042}
2043
2044static jint android_server_InputManager_nativeGetSwitchState(JNIEnv* env, jclass clazz,
Jeff Brown6d0fec22010-07-23 21:28:06 -07002045 jint deviceId, jint sourceMask, jint sw) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002046 if (checkInputManagerUnitialized(env)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002047 return AKEY_STATE_UNKNOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002048 }
2049
Jeff Brown6d0fec22010-07-23 21:28:06 -07002050 return gNativeInputManager->getInputManager()->getSwitchState(
2051 deviceId, uint32_t(sourceMask), sw);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002052}
2053
2054static jboolean android_server_InputManager_nativeHasKeys(JNIEnv* env, jclass clazz,
Jeff Brown6d0fec22010-07-23 21:28:06 -07002055 jint deviceId, jint sourceMask, jintArray keyCodes, jbooleanArray outFlags) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002056 if (checkInputManagerUnitialized(env)) {
2057 return JNI_FALSE;
2058 }
2059
2060 int32_t* codes = env->GetIntArrayElements(keyCodes, NULL);
2061 uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL);
2062 jsize numCodes = env->GetArrayLength(keyCodes);
2063 jboolean result;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002064 if (numCodes == env->GetArrayLength(keyCodes)) {
2065 result = gNativeInputManager->getInputManager()->hasKeys(
2066 deviceId, uint32_t(sourceMask), numCodes, codes, flags);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002067 } else {
2068 result = JNI_FALSE;
2069 }
2070
2071 env->ReleaseBooleanArrayElements(outFlags, flags, 0);
2072 env->ReleaseIntArrayElements(keyCodes, codes, 0);
2073 return result;
2074}
2075
2076static void throwInputChannelNotInitialized(JNIEnv* env) {
2077 jniThrowException(env, "java/lang/IllegalStateException",
2078 "inputChannel is not initialized");
2079}
2080
2081static void android_server_InputManager_handleInputChannelDisposed(JNIEnv* env,
2082 jobject inputChannelObj, const sp<InputChannel>& inputChannel, void* data) {
2083 LOGW("Input channel object '%s' was disposed without first being unregistered with "
2084 "the input manager!", inputChannel->getName().string());
2085
Jeff Brown9c3cda02010-06-15 01:31:58 -07002086 if (gNativeInputManager != NULL) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07002087 gNativeInputManager->unregisterInputChannel(env, inputChannel);
Jeff Brown9c3cda02010-06-15 01:31:58 -07002088 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002089}
2090
2091static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
Jeff Browna41ca772010-08-11 14:46:32 -07002092 jobject inputChannelObj, jboolean monitor) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002093 if (checkInputManagerUnitialized(env)) {
2094 return;
2095 }
2096
2097 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
2098 inputChannelObj);
2099 if (inputChannel == NULL) {
2100 throwInputChannelNotInitialized(env);
2101 return;
2102 }
2103
Jeff Brown7fbdc842010-06-17 20:52:56 -07002104
2105 status_t status = gNativeInputManager->registerInputChannel(
Jeff Browna41ca772010-08-11 14:46:32 -07002106 env, inputChannel, inputChannelObj, monitor);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002107 if (status) {
2108 jniThrowRuntimeException(env, "Failed to register input channel. "
2109 "Check logs for details.");
2110 return;
2111 }
2112
Jeff Browna41ca772010-08-11 14:46:32 -07002113 if (! monitor) {
2114 android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
2115 android_server_InputManager_handleInputChannelDisposed, NULL);
2116 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002117}
2118
2119static void android_server_InputManager_nativeUnregisterInputChannel(JNIEnv* env, jclass clazz,
2120 jobject inputChannelObj) {
2121 if (checkInputManagerUnitialized(env)) {
2122 return;
2123 }
2124
2125 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
2126 inputChannelObj);
2127 if (inputChannel == NULL) {
2128 throwInputChannelNotInitialized(env);
2129 return;
2130 }
2131
2132 android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL);
2133
Jeff Brown7fbdc842010-06-17 20:52:56 -07002134 status_t status = gNativeInputManager->unregisterInputChannel(env, inputChannel);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002135 if (status) {
2136 jniThrowRuntimeException(env, "Failed to unregister input channel. "
2137 "Check logs for details.");
2138 }
2139}
2140
Jeff Brown6ec402b2010-07-28 15:48:59 -07002141static jint android_server_InputManager_nativeInjectInputEvent(JNIEnv* env, jclass clazz,
2142 jobject inputEventObj, jint injectorPid, jint injectorUid,
2143 jint syncMode, jint timeoutMillis) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07002144 if (checkInputManagerUnitialized(env)) {
2145 return INPUT_EVENT_INJECTION_FAILED;
2146 }
2147
Jeff Brown6ec402b2010-07-28 15:48:59 -07002148 if (env->IsInstanceOf(inputEventObj, gKeyEventClassInfo.clazz)) {
2149 KeyEvent keyEvent;
2150 android_view_KeyEvent_toNative(env, inputEventObj, & keyEvent);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002151
Jeff Brown6ec402b2010-07-28 15:48:59 -07002152 return gNativeInputManager->getInputManager()->injectInputEvent(& keyEvent,
2153 injectorPid, injectorUid, syncMode, timeoutMillis);
2154 } else if (env->IsInstanceOf(inputEventObj, gMotionEventClassInfo.clazz)) {
2155 MotionEvent motionEvent;
2156 android_view_MotionEvent_toNative(env, inputEventObj, & motionEvent);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002157
Jeff Brown6ec402b2010-07-28 15:48:59 -07002158 return gNativeInputManager->getInputManager()->injectInputEvent(& motionEvent,
2159 injectorPid, injectorUid, syncMode, timeoutMillis);
2160 } else {
2161 jniThrowRuntimeException(env, "Invalid input event type.");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002162 return INPUT_EVENT_INJECTION_FAILED;
2163 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07002164}
2165
Jeff Brown349703e2010-06-22 01:27:15 -07002166static void android_server_InputManager_nativeSetInputWindows(JNIEnv* env, jclass clazz,
2167 jobjectArray windowObjArray) {
2168 if (checkInputManagerUnitialized(env)) {
2169 return;
2170 }
2171
2172 gNativeInputManager->setInputWindows(env, windowObjArray);
2173}
2174
2175static void android_server_InputManager_nativeSetFocusedApplication(JNIEnv* env, jclass clazz,
2176 jobject applicationObj) {
2177 if (checkInputManagerUnitialized(env)) {
2178 return;
2179 }
2180
2181 gNativeInputManager->setFocusedApplication(env, applicationObj);
2182}
2183
2184static void android_server_InputManager_nativeSetInputDispatchMode(JNIEnv* env,
2185 jclass clazz, jboolean enabled, jboolean frozen) {
2186 if (checkInputManagerUnitialized(env)) {
2187 return;
2188 }
2189
2190 gNativeInputManager->setInputDispatchMode(enabled, frozen);
2191}
2192
2193static void android_server_InputManager_nativePreemptInputDispatch(JNIEnv* env,
2194 jclass clazz) {
2195 if (checkInputManagerUnitialized(env)) {
2196 return;
2197 }
2198
2199 gNativeInputManager->preemptInputDispatch();
2200}
2201
Jeff Browne33348b2010-07-15 23:54:05 -07002202static jstring android_server_InputManager_nativeDump(JNIEnv* env, jclass clazz) {
2203 if (checkInputManagerUnitialized(env)) {
2204 return NULL;
2205 }
2206
2207 String8 dump(gNativeInputManager->dump());
2208 return env->NewStringUTF(dump.string());
2209}
2210
Jeff Brown9c3cda02010-06-15 01:31:58 -07002211// ----------------------------------------------------------------------------
2212
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002213static JNINativeMethod gInputManagerMethods[] = {
2214 /* name, signature, funcPtr */
2215 { "nativeInit", "(Lcom/android/server/InputManager$Callbacks;)V",
2216 (void*) android_server_InputManager_nativeInit },
2217 { "nativeStart", "()V",
2218 (void*) android_server_InputManager_nativeStart },
2219 { "nativeSetDisplaySize", "(III)V",
2220 (void*) android_server_InputManager_nativeSetDisplaySize },
2221 { "nativeSetDisplayOrientation", "(II)V",
2222 (void*) android_server_InputManager_nativeSetDisplayOrientation },
2223 { "nativeGetScanCodeState", "(III)I",
2224 (void*) android_server_InputManager_nativeGetScanCodeState },
2225 { "nativeGetKeyCodeState", "(III)I",
2226 (void*) android_server_InputManager_nativeGetKeyCodeState },
2227 { "nativeGetSwitchState", "(III)I",
2228 (void*) android_server_InputManager_nativeGetSwitchState },
Jeff Brown6d0fec22010-07-23 21:28:06 -07002229 { "nativeHasKeys", "(II[I[Z)Z",
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002230 (void*) android_server_InputManager_nativeHasKeys },
Jeff Browna41ca772010-08-11 14:46:32 -07002231 { "nativeRegisterInputChannel", "(Landroid/view/InputChannel;Z)V",
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002232 (void*) android_server_InputManager_nativeRegisterInputChannel },
2233 { "nativeUnregisterInputChannel", "(Landroid/view/InputChannel;)V",
Jeff Brown7fbdc842010-06-17 20:52:56 -07002234 (void*) android_server_InputManager_nativeUnregisterInputChannel },
Jeff Brown6ec402b2010-07-28 15:48:59 -07002235 { "nativeInjectInputEvent", "(Landroid/view/InputEvent;IIII)I",
2236 (void*) android_server_InputManager_nativeInjectInputEvent },
Jeff Brown349703e2010-06-22 01:27:15 -07002237 { "nativeSetInputWindows", "([Lcom/android/server/InputWindow;)V",
2238 (void*) android_server_InputManager_nativeSetInputWindows },
2239 { "nativeSetFocusedApplication", "(Lcom/android/server/InputApplication;)V",
2240 (void*) android_server_InputManager_nativeSetFocusedApplication },
2241 { "nativeSetInputDispatchMode", "(ZZ)V",
2242 (void*) android_server_InputManager_nativeSetInputDispatchMode },
2243 { "nativePreemptInputDispatch", "()V",
Jeff Browne33348b2010-07-15 23:54:05 -07002244 (void*) android_server_InputManager_nativePreemptInputDispatch },
2245 { "nativeDump", "()Ljava/lang/String;",
2246 (void*) android_server_InputManager_nativeDump },
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002247};
2248
2249#define FIND_CLASS(var, className) \
2250 var = env->FindClass(className); \
2251 LOG_FATAL_IF(! var, "Unable to find class " className); \
2252 var = jclass(env->NewGlobalRef(var));
2253
2254#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
2255 var = env->GetMethodID(clazz, methodName, methodDescriptor); \
2256 LOG_FATAL_IF(! var, "Unable to find method " methodName);
2257
2258#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
2259 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
2260 LOG_FATAL_IF(! var, "Unable to find field " fieldName);
2261
2262int register_android_server_InputManager(JNIEnv* env) {
2263 int res = jniRegisterNativeMethods(env, "com/android/server/InputManager",
2264 gInputManagerMethods, NELEM(gInputManagerMethods));
2265 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
2266
Jeff Brown9c3cda02010-06-15 01:31:58 -07002267 // Callbacks
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002268
2269 FIND_CLASS(gCallbacksClassInfo.clazz, "com/android/server/InputManager$Callbacks");
2270
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002271 GET_METHOD_ID(gCallbacksClassInfo.notifyConfigurationChanged, gCallbacksClassInfo.clazz,
2272 "notifyConfigurationChanged", "(JIII)V");
2273
2274 GET_METHOD_ID(gCallbacksClassInfo.notifyLidSwitchChanged, gCallbacksClassInfo.clazz,
2275 "notifyLidSwitchChanged", "(JZ)V");
2276
Jeff Brown7fbdc842010-06-17 20:52:56 -07002277 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelBroken, gCallbacksClassInfo.clazz,
2278 "notifyInputChannelBroken", "(Landroid/view/InputChannel;)V");
2279
2280 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelANR, gCallbacksClassInfo.clazz,
2281 "notifyInputChannelANR", "(Landroid/view/InputChannel;)J");
2282
2283 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelRecoveredFromANR, gCallbacksClassInfo.clazz,
2284 "notifyInputChannelRecoveredFromANR", "(Landroid/view/InputChannel;)V");
2285
Jeff Brown349703e2010-06-22 01:27:15 -07002286 GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
2287 "notifyANR", "(Ljava/lang/Object;)J");
2288
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002289 GET_METHOD_ID(gCallbacksClassInfo.virtualKeyDownFeedback, gCallbacksClassInfo.clazz,
2290 "virtualKeyDownFeedback", "()V");
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002291
Jeff Brown349703e2010-06-22 01:27:15 -07002292 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002293 "interceptKeyBeforeQueueing", "(JIZIZ)I");
Jeff Brown349703e2010-06-22 01:27:15 -07002294
2295 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002296 "interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIIIII)Z");
Jeff Brown349703e2010-06-22 01:27:15 -07002297
2298 GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,
2299 "checkInjectEventsPermission", "(II)Z");
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002300
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002301 GET_METHOD_ID(gCallbacksClassInfo.notifyAppSwitchComing, gCallbacksClassInfo.clazz,
2302 "notifyAppSwitchComing", "()V");
2303
2304 GET_METHOD_ID(gCallbacksClassInfo.filterTouchEvents, gCallbacksClassInfo.clazz,
2305 "filterTouchEvents", "()Z");
2306
2307 GET_METHOD_ID(gCallbacksClassInfo.filterJumpyTouchEvents, gCallbacksClassInfo.clazz,
2308 "filterJumpyTouchEvents", "()Z");
2309
2310 GET_METHOD_ID(gCallbacksClassInfo.getVirtualKeyDefinitions, gCallbacksClassInfo.clazz,
2311 "getVirtualKeyDefinitions",
2312 "(Ljava/lang/String;)[Lcom/android/server/InputManager$VirtualKeyDefinition;");
2313
2314 GET_METHOD_ID(gCallbacksClassInfo.getExcludedDeviceNames, gCallbacksClassInfo.clazz,
2315 "getExcludedDeviceNames", "()[Ljava/lang/String;");
2316
Jeff Brownae9fc032010-08-18 15:51:08 -07002317 GET_METHOD_ID(gCallbacksClassInfo.getMaxEventsPerSecond, gCallbacksClassInfo.clazz,
2318 "getMaxEventsPerSecond", "()I");
2319
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002320 // VirtualKeyDefinition
2321
2322 FIND_CLASS(gVirtualKeyDefinitionClassInfo.clazz,
2323 "com/android/server/InputManager$VirtualKeyDefinition");
2324
2325 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.scanCode, gVirtualKeyDefinitionClassInfo.clazz,
2326 "scanCode", "I");
2327
2328 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerX, gVirtualKeyDefinitionClassInfo.clazz,
2329 "centerX", "I");
2330
2331 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerY, gVirtualKeyDefinitionClassInfo.clazz,
2332 "centerY", "I");
2333
2334 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.width, gVirtualKeyDefinitionClassInfo.clazz,
2335 "width", "I");
2336
2337 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.height, gVirtualKeyDefinitionClassInfo.clazz,
2338 "height", "I");
2339
Jeff Brown349703e2010-06-22 01:27:15 -07002340 // InputWindow
Jeff Brown7fbdc842010-06-17 20:52:56 -07002341
Jeff Brown349703e2010-06-22 01:27:15 -07002342 FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002343
Jeff Brown349703e2010-06-22 01:27:15 -07002344 GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
2345 "inputChannel", "Landroid/view/InputChannel;");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002346
Jeff Brown349703e2010-06-22 01:27:15 -07002347 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
2348 "layoutParamsFlags", "I");
2349
2350 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
2351 "layoutParamsType", "I");
2352
2353 GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
2354 "dispatchingTimeoutNanos", "J");
2355
2356 GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
2357 "frameLeft", "I");
2358
2359 GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
2360 "frameTop", "I");
2361
2362 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
2363 "touchableAreaLeft", "I");
2364
2365 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
2366 "touchableAreaTop", "I");
2367
2368 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
2369 "touchableAreaRight", "I");
2370
2371 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
2372 "touchableAreaBottom", "I");
2373
2374 GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
2375 "visible", "Z");
2376
2377 GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
2378 "hasFocus", "Z");
2379
2380 GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
2381 "hasWallpaper", "Z");
2382
2383 GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
2384 "paused", "Z");
2385
2386 GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
2387 "ownerPid", "I");
2388
2389 GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
2390 "ownerUid", "I");
2391
2392 // InputApplication
2393
2394 FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication");
2395
2396 GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
2397 "name", "Ljava/lang/String;");
2398
2399 GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
2400 gInputApplicationClassInfo.clazz,
2401 "dispatchingTimeoutNanos", "J");
2402
2403 GET_FIELD_ID(gInputApplicationClassInfo.token, gInputApplicationClassInfo.clazz,
2404 "token", "Ljava/lang/Object;");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002405
Jeff Brown6ec402b2010-07-28 15:48:59 -07002406 // KeyEvent
2407
2408 FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
2409
2410 // MotionEVent
2411
2412 FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent");
2413
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002414 return 0;
2415}
2416
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002417} /* namespace android */