blob: f19f1ec6931d69b5a5a3145375cdd57d0cd038c2 [file] [log] [blame]
Jeff Brown46b9ac02010-04-22 18:58:52 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "InputManager-JNI"
18
Jeff Brown9c3cda02010-06-15 01:31:58 -070019//#define LOG_NDEBUG 0
20
21// Log debug messages about InputReaderPolicy
Jeff Brown349703e2010-06-22 01:27:15 -070022#define DEBUG_INPUT_READER_POLICY 0
Jeff Brown9c3cda02010-06-15 01:31:58 -070023
24// Log debug messages about InputDispatcherPolicy
Jeff Brown349703e2010-06-22 01:27:15 -070025#define DEBUG_INPUT_DISPATCHER_POLICY 0
Jeff Brown9c3cda02010-06-15 01:31:58 -070026
Jeff Brown349703e2010-06-22 01:27:15 -070027// Log debug messages about input focus tracking
28#define DEBUG_FOCUS 0
Jeff Brown9c3cda02010-06-15 01:31:58 -070029
Jeff Brown46b9ac02010-04-22 18:58:52 -070030#include "JNIHelp.h"
31#include "jni.h"
Jeff Brown349703e2010-06-22 01:27:15 -070032#include <limits.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070033#include <android_runtime/AndroidRuntime.h>
Jeff Brown9c3cda02010-06-15 01:31:58 -070034#include <ui/InputReader.h>
35#include <ui/InputDispatcher.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070036#include <ui/InputManager.h>
37#include <ui/InputTransport.h>
38#include <utils/Log.h>
39#include <utils/threads.h>
40#include "../../core/jni/android_view_KeyEvent.h"
41#include "../../core/jni/android_view_MotionEvent.h"
42#include "../../core/jni/android_view_InputChannel.h"
Jeff Brown00fa7bd2010-07-02 15:37:36 -070043#include "com_android_server_PowerManagerService.h"
Jeff Brown46b9ac02010-04-22 18:58:52 -070044
45namespace android {
46
Jeff Brown349703e2010-06-22 01:27:15 -070047// Window flags from WindowManager.LayoutParams
48enum {
49 FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
50 FLAG_DIM_BEHIND = 0x00000002,
51 FLAG_BLUR_BEHIND = 0x00000004,
52 FLAG_NOT_FOCUSABLE = 0x00000008,
53 FLAG_NOT_TOUCHABLE = 0x00000010,
54 FLAG_NOT_TOUCH_MODAL = 0x00000020,
55 FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
56 FLAG_KEEP_SCREEN_ON = 0x00000080,
57 FLAG_LAYOUT_IN_SCREEN = 0x00000100,
58 FLAG_LAYOUT_NO_LIMITS = 0x00000200,
59 FLAG_FULLSCREEN = 0x00000400,
60 FLAG_FORCE_NOT_FULLSCREEN = 0x00000800,
61 FLAG_DITHER = 0x00001000,
62 FLAG_SECURE = 0x00002000,
63 FLAG_SCALED = 0x00004000,
64 FLAG_IGNORE_CHEEK_PRESSES = 0x00008000,
65 FLAG_LAYOUT_INSET_DECOR = 0x00010000,
66 FLAG_ALT_FOCUSABLE_IM = 0x00020000,
67 FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
68 FLAG_SHOW_WHEN_LOCKED = 0x00080000,
69 FLAG_SHOW_WALLPAPER = 0x00100000,
70 FLAG_TURN_SCREEN_ON = 0x00200000,
71 FLAG_DISMISS_KEYGUARD = 0x00400000,
72 FLAG_IMMERSIVE = 0x00800000,
73 FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000,
74 FLAG_COMPATIBLE_WINDOW = 0x20000000,
75 FLAG_SYSTEM_ERROR = 0x40000000,
76};
77
78// Window types from WindowManager.LayoutParams
79enum {
80 FIRST_APPLICATION_WINDOW = 1,
81 TYPE_BASE_APPLICATION = 1,
82 TYPE_APPLICATION = 2,
83 TYPE_APPLICATION_STARTING = 3,
84 LAST_APPLICATION_WINDOW = 99,
85 FIRST_SUB_WINDOW = 1000,
86 TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW,
87 TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1,
88 TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2,
89 TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3,
90 TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4,
91 LAST_SUB_WINDOW = 1999,
92 FIRST_SYSTEM_WINDOW = 2000,
93 TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW,
94 TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1,
95 TYPE_PHONE = FIRST_SYSTEM_WINDOW+2,
96 TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3,
97 TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4,
98 TYPE_TOAST = FIRST_SYSTEM_WINDOW+5,
99 TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6,
100 TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7,
101 TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8,
102 TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9,
103 TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10,
104 TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11,
105 TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
106 TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13,
107 TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14,
108 LAST_SYSTEM_WINDOW = 2999,
109};
110
Jeff Brown349703e2010-06-22 01:27:15 -0700111// Delay between reporting long touch events to the power manager.
112const nsecs_t EVENT_IGNORE_DURATION = 300 * 1000000LL; // 300 ms
113
114// Default input dispatching timeout if there is no focused application or paused window
115// from which to determine an appropriate dispatching timeout.
116const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
117
118// Minimum amount of time to provide to the input dispatcher for delivery of an event
119// regardless of how long the application window was paused.
120const nsecs_t MIN_INPUT_DISPATCHING_TIMEOUT = 1000 * 1000000LL; // 1 sec
121
Jeff Brown9c3cda02010-06-15 01:31:58 -0700122// ----------------------------------------------------------------------------
Jeff Brown46b9ac02010-04-22 18:58:52 -0700123
124static struct {
125 jclass clazz;
126
Jeff Brown46b9ac02010-04-22 18:58:52 -0700127 jmethodID notifyConfigurationChanged;
128 jmethodID notifyLidSwitchChanged;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700129 jmethodID notifyInputChannelBroken;
130 jmethodID notifyInputChannelANR;
131 jmethodID notifyInputChannelRecoveredFromANR;
Jeff Brown349703e2010-06-22 01:27:15 -0700132 jmethodID notifyANR;
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700133 jmethodID virtualKeyDownFeedback;
Jeff Brown349703e2010-06-22 01:27:15 -0700134 jmethodID interceptKeyBeforeQueueing;
135 jmethodID interceptKeyBeforeDispatching;
136 jmethodID checkInjectEventsPermission;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700137 jmethodID notifyAppSwitchComing;
138 jmethodID filterTouchEvents;
139 jmethodID filterJumpyTouchEvents;
140 jmethodID getVirtualKeyDefinitions;
141 jmethodID getExcludedDeviceNames;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700142} gCallbacksClassInfo;
143
144static struct {
145 jclass clazz;
146
147 jfieldID scanCode;
148 jfieldID centerX;
149 jfieldID centerY;
150 jfieldID width;
151 jfieldID height;
152} gVirtualKeyDefinitionClassInfo;
153
Jeff Brown7fbdc842010-06-17 20:52:56 -0700154static struct {
155 jclass clazz;
156
Jeff Brown349703e2010-06-22 01:27:15 -0700157 jfieldID inputChannel;
158 jfieldID layoutParamsFlags;
159 jfieldID layoutParamsType;
160 jfieldID dispatchingTimeoutNanos;
161 jfieldID frameLeft;
162 jfieldID frameTop;
163 jfieldID touchableAreaLeft;
164 jfieldID touchableAreaTop;
165 jfieldID touchableAreaRight;
166 jfieldID touchableAreaBottom;
167 jfieldID visible;
168 jfieldID hasFocus;
169 jfieldID hasWallpaper;
170 jfieldID paused;
171 jfieldID ownerPid;
172 jfieldID ownerUid;
173} gInputWindowClassInfo;
174
175static struct {
176 jclass clazz;
177
178 jfieldID name;
179 jfieldID dispatchingTimeoutNanos;
180 jfieldID token;
181} gInputApplicationClassInfo;
182
183// ----------------------------------------------------------------------------
184
185static inline nsecs_t now() {
186 return systemTime(SYSTEM_TIME_MONOTONIC);
187}
Jeff Brown7fbdc842010-06-17 20:52:56 -0700188
Jeff Brown9c3cda02010-06-15 01:31:58 -0700189// ----------------------------------------------------------------------------
190
191class NativeInputManager : public virtual RefBase,
192 public virtual InputReaderPolicyInterface,
193 public virtual InputDispatcherPolicyInterface {
194protected:
195 virtual ~NativeInputManager();
196
197public:
198 NativeInputManager(jobject callbacksObj);
199
200 inline sp<InputManager> getInputManager() const { return mInputManager; }
201
Jeff Browne33348b2010-07-15 23:54:05 -0700202 String8 dump();
203
Jeff Brown9c3cda02010-06-15 01:31:58 -0700204 void setDisplaySize(int32_t displayId, int32_t width, int32_t height);
205 void setDisplayOrientation(int32_t displayId, int32_t orientation);
206
Jeff Brown7fbdc842010-06-17 20:52:56 -0700207 status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
208 jweak inputChannelObjWeak);
209 status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
210
Jeff Brown349703e2010-06-22 01:27:15 -0700211 void setInputWindows(JNIEnv* env, jobjectArray windowObjArray);
212 void setFocusedApplication(JNIEnv* env, jobject applicationObj);
213 void setInputDispatchMode(bool enabled, bool frozen);
214 void preemptInputDispatch();
215
Jeff Brown9c3cda02010-06-15 01:31:58 -0700216 /* --- InputReaderPolicyInterface implementation --- */
217
218 virtual bool getDisplayInfo(int32_t displayId,
219 int32_t* width, int32_t* height, int32_t* orientation);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700220 virtual void virtualKeyDownFeedback();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700221 virtual int32_t interceptKey(nsecs_t when, int32_t deviceId,
222 bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags);
223 virtual int32_t interceptTrackball(nsecs_t when, bool buttonChanged, bool buttonDown,
224 bool rolled);
225 virtual int32_t interceptTouch(nsecs_t when);
226 virtual int32_t interceptSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue);
227 virtual bool filterTouchEvents();
228 virtual bool filterJumpyTouchEvents();
229 virtual void getVirtualKeyDefinitions(const String8& deviceName,
230 Vector<InputReaderPolicyInterface::VirtualKeyDefinition>& outVirtualKeyDefinitions);
231 virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames);
232
233 /* --- InputDispatcherPolicyInterface implementation --- */
234
235 virtual void notifyConfigurationChanged(nsecs_t when);
236 virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700237 virtual bool notifyInputChannelANR(const sp<InputChannel>& inputChannel,
238 nsecs_t& outNewTimeout);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700239 virtual void notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel);
240 virtual nsecs_t getKeyRepeatTimeout();
Jeff Brown349703e2010-06-22 01:27:15 -0700241 virtual int32_t waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700242 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brown349703e2010-06-22 01:27:15 -0700243 virtual int32_t waitForMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700244 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700245
246private:
Jeff Brown349703e2010-06-22 01:27:15 -0700247 struct InputWindow {
248 sp<InputChannel> inputChannel;
249 int32_t layoutParamsFlags;
250 int32_t layoutParamsType;
251 nsecs_t dispatchingTimeout;
252 int32_t frameLeft;
253 int32_t frameTop;
254 int32_t touchableAreaLeft;
255 int32_t touchableAreaTop;
256 int32_t touchableAreaRight;
257 int32_t touchableAreaBottom;
258 bool visible;
259 bool hasFocus;
260 bool hasWallpaper;
261 bool paused;
262 int32_t ownerPid;
263 int32_t ownerUid;
264
265 inline bool touchableAreaContainsPoint(int32_t x, int32_t y) {
266 return x >= touchableAreaLeft && x <= touchableAreaRight
267 && y >= touchableAreaTop && y <= touchableAreaBottom;
268 }
269 };
270
271 struct InputApplication {
272 String8 name;
273 nsecs_t dispatchingTimeout;
274 jweak tokenObjWeak;
275 };
276
277 class ANRTimer {
278 enum Budget {
279 SYSTEM = 0,
280 APPLICATION = 1
281 };
282
283 Budget mBudget;
284 nsecs_t mStartTime;
285 bool mFrozen;
286 InputWindow* mPausedWindow;
287
288 public:
289 ANRTimer();
290
291 void dispatchFrozenBySystem();
292 void dispatchPausedByApplication(InputWindow* pausedWindow);
293 bool waitForDispatchStateChangeLd(NativeInputManager* inputManager);
294
295 nsecs_t getTimeSpentWaitingForApplication() const;
296 };
297
Jeff Brown9c3cda02010-06-15 01:31:58 -0700298 sp<InputManager> mInputManager;
299
300 jobject mCallbacksObj;
301
302 // Cached filtering policies.
303 int32_t mFilterTouchEvents;
304 int32_t mFilterJumpyTouchEvents;
305
306 // Cached display state. (lock mDisplayLock)
307 Mutex mDisplayLock;
308 int32_t mDisplayWidth, mDisplayHeight;
309 int32_t mDisplayOrientation;
310
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700311 // Power manager interactions.
Jeff Brown9c3cda02010-06-15 01:31:58 -0700312 bool isScreenOn();
313 bool isScreenBright();
314
Jeff Brown7fbdc842010-06-17 20:52:56 -0700315 // Weak references to all currently registered input channels by receive fd.
316 Mutex mInputChannelRegistryLock;
317 KeyedVector<int, jweak> mInputChannelObjWeakByReceiveFd;
318
319 jobject getInputChannelObjLocal(JNIEnv* env, const sp<InputChannel>& inputChannel);
320
Jeff Brown349703e2010-06-22 01:27:15 -0700321 // Input target and focus tracking. (lock mDispatchLock)
322 Mutex mDispatchLock;
323 Condition mDispatchStateChanged;
324
325 bool mDispatchEnabled;
326 bool mDispatchFrozen;
327 bool mWindowsReady;
328 Vector<InputWindow> mWindows;
329 Vector<InputWindow*> mWallpaperWindows;
330
331 // Focus tracking for keys, trackball, etc.
332 InputWindow* mFocusedWindow;
333
334 // Focus tracking for touch.
335 bool mTouchDown;
336 InputWindow* mTouchedWindow; // primary target for current down
337 Vector<InputWindow*> mTouchedWallpaperWindows; // wallpaper targets
338
339 Vector<InputWindow*> mTempTouchedOutsideWindows; // temporary outside touch targets
340 Vector<sp<InputChannel> > mTempTouchedWallpaperChannels; // temporary wallpaper targets
341
342 // Focused application.
343 InputApplication* mFocusedApplication;
344 InputApplication mFocusedApplicationStorage; // preallocated storage for mFocusedApplication
345
Jeff Browne33348b2010-07-15 23:54:05 -0700346 void dumpDispatchStateLd(String8& dump);
347 void logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -0700348
349 bool notifyANR(jobject tokenObj, nsecs_t& outNewTimeout);
350 void releaseFocusedApplicationLd(JNIEnv* env);
351
352 int32_t waitForFocusedWindowLd(uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
353 Vector<InputTarget>& outTargets, InputWindow*& outFocusedWindow);
354 int32_t waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
355 int32_t injectorPid, int32_t injectorUid,
356 Vector<InputTarget>& outTargets, InputWindow*& outTouchedWindow);
357
358 void releaseTouchedWindowLd();
359
Jeff Brownc5ed5912010-07-14 18:48:53 -0700360 int32_t waitForNonTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown349703e2010-06-22 01:27:15 -0700361 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700362 int32_t waitForTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown349703e2010-06-22 01:27:15 -0700363 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
364
Jeff Brownd0097872010-06-30 14:41:59 -0700365 bool interceptKeyBeforeDispatching(const InputTarget& target,
366 const KeyEvent* keyEvent, uint32_t policyFlags);
367
Jeff Brown349703e2010-06-22 01:27:15 -0700368 void pokeUserActivityIfNeeded(int32_t windowType, int32_t eventType);
369 void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
370 bool checkInjectionPermission(const InputWindow* window,
371 int32_t injectorPid, int32_t injectorUid);
372
373 static bool populateWindow(JNIEnv* env, jobject windowObj, InputWindow& outWindow);
374 static void addTarget(const InputWindow* window, int32_t targetFlags,
375 nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets);
376
Jeff Brown9c3cda02010-06-15 01:31:58 -0700377 static inline JNIEnv* jniEnv() {
378 return AndroidRuntime::getJNIEnv();
379 }
380
381 static bool isAppSwitchKey(int32_t keyCode);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700382 static bool isPolicyKey(int32_t keyCode, bool isScreenOn);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700383 static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700384};
385
386// ----------------------------------------------------------------------------
387
388NativeInputManager::NativeInputManager(jobject callbacksObj) :
389 mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1),
Jeff Brown0b72e822010-06-29 16:52:21 -0700390 mDisplayWidth(-1), mDisplayHeight(-1), mDisplayOrientation(ROTATION_0),
Jeff Brown349703e2010-06-22 01:27:15 -0700391 mDispatchEnabled(true), mDispatchFrozen(false), mWindowsReady(true),
392 mFocusedWindow(NULL), mTouchDown(false), mTouchedWindow(NULL),
393 mFocusedApplication(NULL) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700394 JNIEnv* env = jniEnv();
395
396 mCallbacksObj = env->NewGlobalRef(callbacksObj);
397
398 sp<EventHub> eventHub = new EventHub();
399 mInputManager = new InputManager(eventHub, this, this);
400}
401
402NativeInputManager::~NativeInputManager() {
403 JNIEnv* env = jniEnv();
404
405 env->DeleteGlobalRef(mCallbacksObj);
Jeff Brown349703e2010-06-22 01:27:15 -0700406
407 releaseFocusedApplicationLd(env);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700408}
409
Jeff Browne33348b2010-07-15 23:54:05 -0700410String8 NativeInputManager::dump() {
411 String8 dump;
412 dump.append("Native Input Dispatcher State:\n");
413 dumpDispatchStateLd(dump);
414 return dump;
415}
416
Jeff Brown9c3cda02010-06-15 01:31:58 -0700417bool NativeInputManager::isAppSwitchKey(int32_t keyCode) {
Jeff Brownfd035822010-06-30 16:10:35 -0700418 return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700419}
420
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700421bool NativeInputManager::isPolicyKey(int32_t keyCode, bool isScreenOn) {
422 // Special keys that the WindowManagerPolicy might care about.
423 switch (keyCode) {
Jeff Brownfd035822010-06-30 16:10:35 -0700424 case AKEYCODE_VOLUME_UP:
425 case AKEYCODE_VOLUME_DOWN:
426 case AKEYCODE_ENDCALL:
427 case AKEYCODE_POWER:
428 case AKEYCODE_CALL:
429 case AKEYCODE_HOME:
430 case AKEYCODE_MENU:
431 case AKEYCODE_SEARCH:
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700432 // media keys
Jeff Brownfd035822010-06-30 16:10:35 -0700433 case AKEYCODE_HEADSETHOOK:
434 case AKEYCODE_MEDIA_PLAY_PAUSE:
435 case AKEYCODE_MEDIA_STOP:
436 case AKEYCODE_MEDIA_NEXT:
437 case AKEYCODE_MEDIA_PREVIOUS:
438 case AKEYCODE_MEDIA_REWIND:
439 case AKEYCODE_MEDIA_FAST_FORWARD:
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700440 return true;
441 default:
442 // We need to pass all keys to the policy in the following cases:
443 // - screen is off
444 // - keyguard is visible
445 // - policy is performing key chording
446 //return ! isScreenOn || keyguardVisible || chording;
447 return true; // XXX stubbed out for now
448 }
449}
450
Jeff Brown7fbdc842010-06-17 20:52:56 -0700451bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700452 if (env->ExceptionCheck()) {
453 LOGE("An exception was thrown by callback '%s'.", methodName);
454 LOGE_EX(env);
455 env->ExceptionClear();
456 return true;
457 }
458 return false;
459}
460
461void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height) {
462 if (displayId == 0) {
463 AutoMutex _l(mDisplayLock);
464
465 mDisplayWidth = width;
466 mDisplayHeight = height;
467 }
468}
469
470void NativeInputManager::setDisplayOrientation(int32_t displayId, int32_t orientation) {
471 if (displayId == 0) {
472 AutoMutex _l(mDisplayLock);
473
474 mDisplayOrientation = orientation;
475 }
476}
477
Jeff Brown7fbdc842010-06-17 20:52:56 -0700478status_t NativeInputManager::registerInputChannel(JNIEnv* env,
479 const sp<InputChannel>& inputChannel, jobject inputChannelObj) {
480 jweak inputChannelObjWeak = env->NewWeakGlobalRef(inputChannelObj);
481 if (! inputChannelObjWeak) {
482 LOGE("Could not create weak reference for input channel.");
483 LOGE_EX(env);
484 return NO_MEMORY;
485 }
486
487 status_t status;
488 {
489 AutoMutex _l(mInputChannelRegistryLock);
490
491 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
492 inputChannel->getReceivePipeFd());
493 if (index >= 0) {
494 LOGE("Input channel object '%s' has already been registered",
495 inputChannel->getName().string());
496 status = INVALID_OPERATION;
497 goto DeleteWeakRef;
498 }
499
500 mInputChannelObjWeakByReceiveFd.add(inputChannel->getReceivePipeFd(),
501 inputChannelObjWeak);
502 }
503
504 status = mInputManager->registerInputChannel(inputChannel);
505 if (! status) {
506 return OK;
507 }
508
509 {
510 AutoMutex _l(mInputChannelRegistryLock);
511 mInputChannelObjWeakByReceiveFd.removeItem(inputChannel->getReceivePipeFd());
512 }
513
514DeleteWeakRef:
515 env->DeleteWeakGlobalRef(inputChannelObjWeak);
516 return status;
517}
518
519status_t NativeInputManager::unregisterInputChannel(JNIEnv* env,
520 const sp<InputChannel>& inputChannel) {
521 jweak inputChannelObjWeak;
522 {
523 AutoMutex _l(mInputChannelRegistryLock);
524
525 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
526 inputChannel->getReceivePipeFd());
527 if (index < 0) {
528 LOGE("Input channel object '%s' is not currently registered",
529 inputChannel->getName().string());
530 return INVALID_OPERATION;
531 }
532
533 inputChannelObjWeak = mInputChannelObjWeakByReceiveFd.valueAt(index);
534 mInputChannelObjWeakByReceiveFd.removeItemsAt(index);
535 }
536
537 env->DeleteWeakGlobalRef(inputChannelObjWeak);
538
539 return mInputManager->unregisterInputChannel(inputChannel);
540}
541
542jobject NativeInputManager::getInputChannelObjLocal(JNIEnv* env,
543 const sp<InputChannel>& inputChannel) {
544 {
545 AutoMutex _l(mInputChannelRegistryLock);
546
547 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
548 inputChannel->getReceivePipeFd());
549 if (index < 0) {
550 return NULL;
551 }
552
553 jweak inputChannelObjWeak = mInputChannelObjWeakByReceiveFd.valueAt(index);
554 return env->NewLocalRef(inputChannelObjWeak);
555 }
556}
557
Jeff Brown9c3cda02010-06-15 01:31:58 -0700558bool NativeInputManager::getDisplayInfo(int32_t displayId,
559 int32_t* width, int32_t* height, int32_t* orientation) {
560 bool result = false;
561 if (displayId == 0) {
562 AutoMutex _l(mDisplayLock);
563
564 if (mDisplayWidth > 0) {
565 *width = mDisplayWidth;
566 *height = mDisplayHeight;
567 *orientation = mDisplayOrientation;
568 result = true;
569 }
570 }
571 return result;
572}
573
574bool NativeInputManager::isScreenOn() {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700575 return android_server_PowerManagerService_isScreenOn();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700576}
577
578bool NativeInputManager::isScreenBright() {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700579 return android_server_PowerManagerService_isScreenBright();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700580}
581
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700582void NativeInputManager::virtualKeyDownFeedback() {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700583#if DEBUG_INPUT_READER_POLICY
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700584 LOGD("virtualKeyDownFeedback");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700585#endif
586
587 JNIEnv* env = jniEnv();
588
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700589 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.virtualKeyDownFeedback);
590 checkAndClearExceptionFromCallback(env, "virtualKeyDownFeedback");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700591}
592
593int32_t NativeInputManager::interceptKey(nsecs_t when,
594 int32_t deviceId, bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) {
595#if DEBUG_INPUT_READER_POLICY
596 LOGD("interceptKey - when=%lld, deviceId=%d, down=%d, keyCode=%d, scanCode=%d, "
Jeff Brown349703e2010-06-22 01:27:15 -0700597 "policyFlags=0x%x",
Jeff Brown9c3cda02010-06-15 01:31:58 -0700598 when, deviceId, down, keyCode, scanCode, policyFlags);
599#endif
600
601 const int32_t WM_ACTION_PASS_TO_USER = 1;
602 const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2;
603 const int32_t WM_ACTION_GO_TO_SLEEP = 4;
604
Jeff Brown9c3cda02010-06-15 01:31:58 -0700605 bool isScreenOn = this->isScreenOn();
606 bool isScreenBright = this->isScreenBright();
607
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700608 jint wmActions = 0;
609 if (isPolicyKey(keyCode, isScreenOn)) {
610 JNIEnv* env = jniEnv();
611
612 wmActions = env->CallIntMethod(mCallbacksObj,
613 gCallbacksClassInfo.interceptKeyBeforeQueueing,
614 when, keyCode, down, policyFlags, isScreenOn);
615 if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
616 wmActions = 0;
617 }
618 } else {
619 wmActions = WM_ACTION_PASS_TO_USER;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700620 }
621
622 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
623 if (! isScreenOn) {
624 // Key presses and releases wake the device.
625 actions |= InputReaderPolicyInterface::ACTION_WOKE_HERE;
626 }
627
628 if (! isScreenBright) {
629 // Key presses and releases brighten the screen if dimmed.
630 actions |= InputReaderPolicyInterface::ACTION_BRIGHT_HERE;
631 }
632
633 if (wmActions & WM_ACTION_GO_TO_SLEEP) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700634 android_server_PowerManagerService_goToSleep(when);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700635 }
636
637 if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
Jeff Brown349703e2010-06-22 01:27:15 -0700638 pokeUserActivity(when, POWER_MANAGER_BUTTON_EVENT);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700639 }
640
641 if (wmActions & WM_ACTION_PASS_TO_USER) {
642 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700643
Jeff Brown9c3cda02010-06-15 01:31:58 -0700644 if (down && isAppSwitchKey(keyCode)) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700645 JNIEnv* env = jniEnv();
646
Jeff Brown9c3cda02010-06-15 01:31:58 -0700647 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyAppSwitchComing);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700648 checkAndClearExceptionFromCallback(env, "notifyAppSwitchComing");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700649
650 actions |= InputReaderPolicyInterface::ACTION_APP_SWITCH_COMING;
651 }
652 }
Jeff Brown349703e2010-06-22 01:27:15 -0700653
Jeff Brown9c3cda02010-06-15 01:31:58 -0700654 return actions;
655}
656
657int32_t NativeInputManager::interceptTouch(nsecs_t when) {
658#if DEBUG_INPUT_READER_POLICY
659 LOGD("interceptTouch - when=%lld", when);
660#endif
661
Jeff Brown5c225b12010-06-16 01:53:36 -0700662 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
663 if (isScreenOn()) {
664 // Only dispatch touch events when the device is awake.
Jeff Brown349703e2010-06-22 01:27:15 -0700665 // Do not wake the device.
Jeff Brown5c225b12010-06-16 01:53:36 -0700666 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700667
Jeff Brown349703e2010-06-22 01:27:15 -0700668 if (! isScreenBright()) {
669 // Brighten the screen if dimmed.
670 actions |= InputReaderPolicyInterface::ACTION_BRIGHT_HERE;
671 }
Jeff Brown5c225b12010-06-16 01:53:36 -0700672 }
673
674 return actions;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700675}
676
677int32_t NativeInputManager::interceptTrackball(nsecs_t when,
678 bool buttonChanged, bool buttonDown, bool rolled) {
679#if DEBUG_INPUT_READER_POLICY
680 LOGD("interceptTrackball - when=%lld, buttonChanged=%d, buttonDown=%d, rolled=%d",
681 when, buttonChanged, buttonDown, rolled);
682#endif
683
Jeff Brown5c225b12010-06-16 01:53:36 -0700684 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
685 if (isScreenOn()) {
686 // Only dispatch trackball events when the device is awake.
Jeff Brown349703e2010-06-22 01:27:15 -0700687 // Do not wake the device.
Jeff Brown5c225b12010-06-16 01:53:36 -0700688 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700689
Jeff Brown349703e2010-06-22 01:27:15 -0700690 if (! isScreenBright()) {
691 // Brighten the screen if dimmed.
692 actions |= InputReaderPolicyInterface::ACTION_BRIGHT_HERE;
693 }
Jeff Brown5c225b12010-06-16 01:53:36 -0700694 }
695
696 return actions;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700697}
698
699int32_t NativeInputManager::interceptSwitch(nsecs_t when, int32_t switchCode,
700 int32_t switchValue) {
701#if DEBUG_INPUT_READER_POLICY
702 LOGD("interceptSwitch - when=%lld, switchCode=%d, switchValue=%d",
703 when, switchCode, switchValue);
704#endif
705
706 JNIEnv* env = jniEnv();
707
708 switch (switchCode) {
709 case SW_LID:
710 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyLidSwitchChanged,
711 when, switchValue == 0);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700712 checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700713 break;
714 }
715
716 return InputReaderPolicyInterface::ACTION_NONE;
717}
718
719bool NativeInputManager::filterTouchEvents() {
720 if (mFilterTouchEvents < 0) {
721 JNIEnv* env = jniEnv();
722
723 jboolean result = env->CallBooleanMethod(mCallbacksObj,
724 gCallbacksClassInfo.filterTouchEvents);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700725 if (checkAndClearExceptionFromCallback(env, "filterTouchEvents")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700726 result = false;
727 }
728
729 mFilterTouchEvents = result ? 1 : 0;
730 }
731 return mFilterTouchEvents;
732}
733
734bool NativeInputManager::filterJumpyTouchEvents() {
735 if (mFilterJumpyTouchEvents < 0) {
736 JNIEnv* env = jniEnv();
737
738 jboolean result = env->CallBooleanMethod(mCallbacksObj,
739 gCallbacksClassInfo.filterJumpyTouchEvents);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700740 if (checkAndClearExceptionFromCallback(env, "filterJumpyTouchEvents")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700741 result = false;
742 }
743
744 mFilterJumpyTouchEvents = result ? 1 : 0;
745 }
746 return mFilterJumpyTouchEvents;
747}
748
749void NativeInputManager::getVirtualKeyDefinitions(const String8& deviceName,
750 Vector<InputReaderPolicyInterface::VirtualKeyDefinition>& outVirtualKeyDefinitions) {
751 JNIEnv* env = jniEnv();
752
753 jstring deviceNameStr = env->NewStringUTF(deviceName.string());
Jeff Brown7fbdc842010-06-17 20:52:56 -0700754 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700755 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
756 gCallbacksClassInfo.getVirtualKeyDefinitions, deviceNameStr));
Jeff Brown7fbdc842010-06-17 20:52:56 -0700757 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions") && result) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700758 jsize length = env->GetArrayLength(result);
759 for (jsize i = 0; i < length; i++) {
760 jobject item = env->GetObjectArrayElement(result, i);
761
762 outVirtualKeyDefinitions.add();
763 outVirtualKeyDefinitions.editTop().scanCode =
764 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.scanCode));
765 outVirtualKeyDefinitions.editTop().centerX =
766 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerX));
767 outVirtualKeyDefinitions.editTop().centerY =
768 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerY));
769 outVirtualKeyDefinitions.editTop().width =
770 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.width));
771 outVirtualKeyDefinitions.editTop().height =
772 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.height));
773
774 env->DeleteLocalRef(item);
775 }
776 env->DeleteLocalRef(result);
777 }
778 env->DeleteLocalRef(deviceNameStr);
779 }
780}
781
782void NativeInputManager::getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
783 JNIEnv* env = jniEnv();
784
785 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
786 gCallbacksClassInfo.getExcludedDeviceNames));
Jeff Brown7fbdc842010-06-17 20:52:56 -0700787 if (! checkAndClearExceptionFromCallback(env, "getExcludedDeviceNames") && result) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700788 jsize length = env->GetArrayLength(result);
789 for (jsize i = 0; i < length; i++) {
790 jstring item = jstring(env->GetObjectArrayElement(result, i));
791
792 const char* deviceNameChars = env->GetStringUTFChars(item, NULL);
793 outExcludedDeviceNames.add(String8(deviceNameChars));
794 env->ReleaseStringUTFChars(item, deviceNameChars);
795
796 env->DeleteLocalRef(item);
797 }
798 env->DeleteLocalRef(result);
799 }
800}
801
802void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
803#if DEBUG_INPUT_DISPATCHER_POLICY
804 LOGD("notifyConfigurationChanged - when=%lld", when);
805#endif
806
807 JNIEnv* env = jniEnv();
808
809 InputConfiguration config;
810 mInputManager->getInputConfiguration(& config);
811
812 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyConfigurationChanged,
813 when, config.touchScreen, config.keyboard, config.navigation);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700814 checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700815}
816
817void NativeInputManager::notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
818#if DEBUG_INPUT_DISPATCHER_POLICY
819 LOGD("notifyInputChannelBroken - inputChannel='%s'", inputChannel->getName().string());
820#endif
821
Jeff Brown7fbdc842010-06-17 20:52:56 -0700822 JNIEnv* env = jniEnv();
823
824 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
825 if (inputChannelObjLocal) {
826 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelBroken,
827 inputChannelObjLocal);
828 checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken");
829
830 env->DeleteLocalRef(inputChannelObjLocal);
831 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700832}
833
Jeff Brown7fbdc842010-06-17 20:52:56 -0700834bool NativeInputManager::notifyInputChannelANR(const sp<InputChannel>& inputChannel,
835 nsecs_t& outNewTimeout) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700836#if DEBUG_INPUT_DISPATCHER_POLICY
837 LOGD("notifyInputChannelANR - inputChannel='%s'",
838 inputChannel->getName().string());
839#endif
840
Jeff Brown7fbdc842010-06-17 20:52:56 -0700841 JNIEnv* env = jniEnv();
842
843 jlong newTimeout;
844 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
845 if (inputChannelObjLocal) {
846 newTimeout = env->CallLongMethod(mCallbacksObj,
847 gCallbacksClassInfo.notifyInputChannelANR, inputChannelObjLocal);
848 if (checkAndClearExceptionFromCallback(env, "notifyInputChannelANR")) {
849 newTimeout = -2;
850 }
851
852 env->DeleteLocalRef(inputChannelObjLocal);
853 } else {
854 newTimeout = -2;
855 }
856
857 if (newTimeout == -2) {
858 return false; // abort
859 }
860
861 outNewTimeout = newTimeout;
862 return true; // resume
Jeff Brown9c3cda02010-06-15 01:31:58 -0700863}
864
865void NativeInputManager::notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel) {
866#if DEBUG_INPUT_DISPATCHER_POLICY
867 LOGD("notifyInputChannelRecoveredFromANR - inputChannel='%s'",
868 inputChannel->getName().string());
869#endif
870
Jeff Brown7fbdc842010-06-17 20:52:56 -0700871 JNIEnv* env = jniEnv();
872
873 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
874 if (inputChannelObjLocal) {
875 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelRecoveredFromANR,
876 inputChannelObjLocal);
877 checkAndClearExceptionFromCallback(env, "notifyInputChannelRecoveredFromANR");
878
879 env->DeleteLocalRef(inputChannelObjLocal);
880 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700881}
882
Jeff Brown349703e2010-06-22 01:27:15 -0700883bool NativeInputManager::notifyANR(jobject tokenObj, nsecs_t& outNewTimeout) {
884#if DEBUG_INPUT_DISPATCHER_POLICY
885 LOGD("notifyANR");
886#endif
887
888 JNIEnv* env = jniEnv();
889
890 jlong newTimeout = env->CallLongMethod(mCallbacksObj,
891 gCallbacksClassInfo.notifyANR, tokenObj);
892 if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
893 newTimeout = -2;
894 }
895
896 if (newTimeout == -2) {
897 return false; // abort
898 }
899
900 outNewTimeout = newTimeout;
901 return true; // resume
902}
903
Jeff Brown9c3cda02010-06-15 01:31:58 -0700904nsecs_t NativeInputManager::getKeyRepeatTimeout() {
905 if (! isScreenOn()) {
906 // Disable key repeat when the screen is off.
907 return -1;
908 } else {
909 // TODO use ViewConfiguration.getLongPressTimeout()
910 return milliseconds_to_nanoseconds(500);
911 }
912}
913
Jeff Brown349703e2010-06-22 01:27:15 -0700914void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArray) {
915#if DEBUG_FOCUS
916 LOGD("setInputWindows");
917#endif
918 { // acquire lock
919 AutoMutex _l(mDispatchLock);
920
921 sp<InputChannel> touchedWindowChannel;
922 if (mTouchedWindow) {
923 touchedWindowChannel = mTouchedWindow->inputChannel;
924 mTouchedWindow = NULL;
925 }
926 size_t numTouchedWallpapers = mTouchedWallpaperWindows.size();
927 if (numTouchedWallpapers != 0) {
928 for (size_t i = 0; i < numTouchedWallpapers; i++) {
929 mTempTouchedWallpaperChannels.push(mTouchedWallpaperWindows[i]->inputChannel);
930 }
931 mTouchedWallpaperWindows.clear();
932 }
933
Jeff Browne33348b2010-07-15 23:54:05 -0700934 bool hadFocusedWindow = mFocusedWindow != NULL;
935
Jeff Brown349703e2010-06-22 01:27:15 -0700936 mWindows.clear();
937 mFocusedWindow = NULL;
938 mWallpaperWindows.clear();
939
940 if (windowObjArray) {
941 mWindowsReady = true;
942
943 jsize length = env->GetArrayLength(windowObjArray);
944 for (jsize i = 0; i < length; i++) {
945 jobject inputTargetObj = env->GetObjectArrayElement(windowObjArray, i);
946 if (! inputTargetObj) {
947 break; // found null element indicating end of used portion of the array
948 }
949
950 mWindows.push();
951 InputWindow& window = mWindows.editTop();
952 bool valid = populateWindow(env, inputTargetObj, window);
953 if (! valid) {
954 mWindows.pop();
955 }
956
957 env->DeleteLocalRef(inputTargetObj);
958 }
959
960 size_t numWindows = mWindows.size();
961 for (size_t i = 0; i < numWindows; i++) {
962 InputWindow* window = & mWindows.editItemAt(i);
963 if (window->hasFocus) {
964 mFocusedWindow = window;
965 }
966
967 if (window->layoutParamsType == TYPE_WALLPAPER) {
968 mWallpaperWindows.push(window);
969
970 for (size_t j = 0; j < numTouchedWallpapers; j++) {
971 if (window->inputChannel == mTempTouchedWallpaperChannels[i]) {
972 mTouchedWallpaperWindows.push(window);
973 }
974 }
975 }
976
977 if (window->inputChannel == touchedWindowChannel) {
978 mTouchedWindow = window;
979 }
980 }
981 } else {
982 mWindowsReady = false;
983 }
984
985 mTempTouchedWallpaperChannels.clear();
986
Jeff Browne33348b2010-07-15 23:54:05 -0700987 if (hadFocusedWindow && ! mFocusedWindow
988 || mFocusedWindow && ! mFocusedWindow->visible) {
989 preemptInputDispatch();
990 }
991
Jeff Brown349703e2010-06-22 01:27:15 -0700992 mDispatchStateChanged.broadcast();
993
994#if DEBUG_FOCUS
Jeff Browne33348b2010-07-15 23:54:05 -0700995 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -0700996#endif
997 } // release lock
998}
999
1000bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj,
1001 InputWindow& outWindow) {
1002 bool valid = false;
1003
1004 jobject inputChannelObj = env->GetObjectField(windowObj,
1005 gInputWindowClassInfo.inputChannel);
1006 if (inputChannelObj) {
1007 sp<InputChannel> inputChannel =
1008 android_view_InputChannel_getInputChannel(env, inputChannelObj);
1009 if (inputChannel != NULL) {
1010 jint layoutParamsFlags = env->GetIntField(windowObj,
1011 gInputWindowClassInfo.layoutParamsFlags);
1012 jint layoutParamsType = env->GetIntField(windowObj,
1013 gInputWindowClassInfo.layoutParamsType);
1014 jlong dispatchingTimeoutNanos = env->GetLongField(windowObj,
1015 gInputWindowClassInfo.dispatchingTimeoutNanos);
1016 jint frameLeft = env->GetIntField(windowObj,
1017 gInputWindowClassInfo.frameLeft);
1018 jint frameTop = env->GetIntField(windowObj,
1019 gInputWindowClassInfo.frameTop);
1020 jint touchableAreaLeft = env->GetIntField(windowObj,
1021 gInputWindowClassInfo.touchableAreaLeft);
1022 jint touchableAreaTop = env->GetIntField(windowObj,
1023 gInputWindowClassInfo.touchableAreaTop);
1024 jint touchableAreaRight = env->GetIntField(windowObj,
1025 gInputWindowClassInfo.touchableAreaRight);
1026 jint touchableAreaBottom = env->GetIntField(windowObj,
1027 gInputWindowClassInfo.touchableAreaBottom);
1028 jboolean visible = env->GetBooleanField(windowObj,
1029 gInputWindowClassInfo.visible);
1030 jboolean hasFocus = env->GetBooleanField(windowObj,
1031 gInputWindowClassInfo.hasFocus);
1032 jboolean hasWallpaper = env->GetBooleanField(windowObj,
1033 gInputWindowClassInfo.hasWallpaper);
1034 jboolean paused = env->GetBooleanField(windowObj,
1035 gInputWindowClassInfo.paused);
1036 jint ownerPid = env->GetIntField(windowObj,
1037 gInputWindowClassInfo.ownerPid);
1038 jint ownerUid = env->GetIntField(windowObj,
1039 gInputWindowClassInfo.ownerUid);
1040
1041 outWindow.inputChannel = inputChannel;
1042 outWindow.layoutParamsFlags = layoutParamsFlags;
1043 outWindow.layoutParamsType = layoutParamsType;
1044 outWindow.dispatchingTimeout = dispatchingTimeoutNanos;
1045 outWindow.frameLeft = frameLeft;
1046 outWindow.frameTop = frameTop;
1047 outWindow.touchableAreaLeft = touchableAreaLeft;
1048 outWindow.touchableAreaTop = touchableAreaTop;
1049 outWindow.touchableAreaRight = touchableAreaRight;
1050 outWindow.touchableAreaBottom = touchableAreaBottom;
1051 outWindow.visible = visible;
1052 outWindow.hasFocus = hasFocus;
1053 outWindow.hasWallpaper = hasWallpaper;
1054 outWindow.paused = paused;
1055 outWindow.ownerPid = ownerPid;
1056 outWindow.ownerUid = ownerUid;
1057 valid = true;
1058 } else {
1059 LOGW("Dropping input target because its input channel is not initialized.");
1060 }
1061
1062 env->DeleteLocalRef(inputChannelObj);
1063 } else {
1064 LOGW("Dropping input target because the input channel object was null.");
1065 }
1066 return valid;
1067}
1068
1069void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) {
1070#if DEBUG_FOCUS
1071 LOGD("setFocusedApplication");
1072#endif
1073 { // acquire lock
1074 AutoMutex _l(mDispatchLock);
1075
1076 releaseFocusedApplicationLd(env);
1077
1078 if (applicationObj) {
1079 jstring nameObj = jstring(env->GetObjectField(applicationObj,
1080 gInputApplicationClassInfo.name));
1081 jlong dispatchingTimeoutNanos = env->GetLongField(applicationObj,
1082 gInputApplicationClassInfo.dispatchingTimeoutNanos);
1083 jobject tokenObj = env->GetObjectField(applicationObj,
1084 gInputApplicationClassInfo.token);
1085 jweak tokenObjWeak = env->NewWeakGlobalRef(tokenObj);
1086 if (! tokenObjWeak) {
1087 LOGE("Could not create weak reference for application token.");
1088 LOGE_EX(env);
1089 env->ExceptionClear();
1090 }
1091 env->DeleteLocalRef(tokenObj);
1092
1093 mFocusedApplication = & mFocusedApplicationStorage;
1094
1095 if (nameObj) {
1096 const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
1097 mFocusedApplication->name.setTo(nameStr);
1098 env->ReleaseStringUTFChars(nameObj, nameStr);
1099 env->DeleteLocalRef(nameObj);
1100 } else {
1101 LOGE("InputApplication.name should not be null.");
1102 mFocusedApplication->name.setTo("unknown");
1103 }
1104
1105 mFocusedApplication->dispatchingTimeout = dispatchingTimeoutNanos;
1106 mFocusedApplication->tokenObjWeak = tokenObjWeak;
1107 }
1108
1109 mDispatchStateChanged.broadcast();
1110
1111#if DEBUG_FOCUS
Jeff Browne33348b2010-07-15 23:54:05 -07001112 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001113#endif
1114 } // release lock
1115}
1116
1117void NativeInputManager::releaseFocusedApplicationLd(JNIEnv* env) {
1118 if (mFocusedApplication) {
1119 env->DeleteWeakGlobalRef(mFocusedApplication->tokenObjWeak);
1120 mFocusedApplication = NULL;
1121 }
1122}
1123
1124void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
1125#if DEBUG_FOCUS
1126 LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001127#endif
1128
Jeff Brown349703e2010-06-22 01:27:15 -07001129 { // acquire lock
1130 AutoMutex _l(mDispatchLock);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001131
Jeff Brown349703e2010-06-22 01:27:15 -07001132 if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
1133 mDispatchEnabled = enabled;
1134 mDispatchFrozen = frozen;
1135
1136 mDispatchStateChanged.broadcast();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001137 }
Jeff Brown349703e2010-06-22 01:27:15 -07001138
1139#if DEBUG_FOCUS
Jeff Browne33348b2010-07-15 23:54:05 -07001140 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001141#endif
1142 } // release lock
1143}
1144
1145void NativeInputManager::preemptInputDispatch() {
1146#if DEBUG_FOCUS
1147 LOGD("preemptInputDispatch");
1148#endif
1149
1150 mInputManager->preemptInputDispatch();
1151}
1152
1153int32_t NativeInputManager::waitForFocusedWindowLd(uint32_t policyFlags,
1154 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
1155 InputWindow*& outFocusedWindow) {
1156
1157 int32_t injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1158 bool firstIteration = true;
1159 ANRTimer anrTimer;
1160 for (;;) {
1161 if (firstIteration) {
1162 firstIteration = false;
1163 } else {
1164 if (! anrTimer.waitForDispatchStateChangeLd(this)) {
1165 LOGW("Dropping event because the dispatcher timed out waiting to identify "
1166 "the window that should receive it.");
1167 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1168 break;
1169 }
1170 }
1171
1172 // If dispatch is not enabled then fail.
1173 if (! mDispatchEnabled) {
1174 LOGI("Dropping event because input dispatch is disabled.");
1175 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1176 break;
1177 }
1178
1179 // If dispatch is frozen or we don't have valid window data yet then wait.
1180 if (mDispatchFrozen || ! mWindowsReady) {
1181#if DEBUG_FOCUS
1182 LOGD("Waiting because dispatch is frozen or windows are not ready.");
1183#endif
1184 anrTimer.dispatchFrozenBySystem();
1185 continue;
1186 }
1187
1188 // If there is no currently focused window and no focused application
1189 // then drop the event.
1190 if (! mFocusedWindow) {
1191 if (mFocusedApplication) {
1192#if DEBUG_FOCUS
1193 LOGD("Waiting because there is no focused window but there is a "
1194 "focused application that may yet introduce a new target: '%s'.",
1195 mFocusedApplication->name.string());
1196#endif
1197 continue;
1198 }
1199
1200 LOGI("Dropping event because there is no focused window or focused application.");
1201 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1202 break;
1203 }
1204
1205 // Check permissions.
1206 if (! checkInjectionPermission(mFocusedWindow, injectorPid, injectorUid)) {
1207 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1208 break;
1209 }
1210
1211 // If the currently focused window is paused then keep waiting.
1212 if (mFocusedWindow->paused) {
1213#if DEBUG_FOCUS
1214 LOGD("Waiting because focused window is paused.");
1215#endif
1216 anrTimer.dispatchPausedByApplication(mFocusedWindow);
1217 continue;
1218 }
1219
1220 // Success!
1221 break; // done waiting, exit loop
Jeff Brown9c3cda02010-06-15 01:31:58 -07001222 }
Jeff Brown349703e2010-06-22 01:27:15 -07001223
1224 // Output targets.
1225 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
1226 addTarget(mFocusedWindow, InputTarget::FLAG_SYNC,
1227 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
1228
1229 outFocusedWindow = mFocusedWindow;
1230 } else {
1231 outFocusedWindow = NULL;
1232 }
1233
1234#if DEBUG_FOCUS
1235 LOGD("waitForFocusedWindow finished: injectionResult=%d",
1236 injectionResult);
Jeff Browne33348b2010-07-15 23:54:05 -07001237 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001238#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001239 return injectionResult;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001240}
1241
Jeff Brownc5ed5912010-07-14 18:48:53 -07001242enum InjectionPermission {
1243 INJECTION_PERMISSION_UNKNOWN,
1244 INJECTION_PERMISSION_GRANTED,
1245 INJECTION_PERMISSION_DENIED
1246};
1247
Jeff Brown349703e2010-06-22 01:27:15 -07001248int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
1249 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
1250 InputWindow*& outTouchedWindow) {
1251 nsecs_t startTime = now();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001252
Jeff Brown349703e2010-06-22 01:27:15 -07001253 // For security reasons, we defer updating the touch state until we are sure that
1254 // event injection will be allowed.
1255 //
1256 // FIXME In the original code, screenWasOff could never be set to true.
1257 // The reason is that the POLICY_FLAG_WOKE_HERE
1258 // and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
1259 // EV_KEY, EV_REL and EV_ABS events. As it happens, the touch event was
1260 // actually enqueued using the policyFlags that appeared in the final EV_SYN
1261 // events upon which no preprocessing took place. So policyFlags was always 0.
1262 // In the new native input dispatcher we're a bit more careful about event
1263 // preprocessing so the touches we receive can actually have non-zero policyFlags.
1264 // Unfortunately we obtain undesirable behavior.
1265 //
1266 // Here's what happens:
1267 //
1268 // When the device dims in anticipation of going to sleep, touches
1269 // in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
1270 // the device to brighten and reset the user activity timer.
1271 // Touches on other windows (such as the launcher window)
1272 // are dropped. Then after a moment, the device goes to sleep. Oops.
1273 //
1274 // Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
1275 // instead of POLICY_FLAG_WOKE_HERE...
1276 //
1277 bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001278
1279 int32_t action = motionEvent->getAction();
1280
Jeff Brown349703e2010-06-22 01:27:15 -07001281 bool firstIteration = true;
1282 ANRTimer anrTimer;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001283 int32_t injectionResult;
1284 InjectionPermission injectionPermission;
Jeff Brown349703e2010-06-22 01:27:15 -07001285 for (;;) {
1286 if (firstIteration) {
1287 firstIteration = false;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001288 } else {
Jeff Brown349703e2010-06-22 01:27:15 -07001289 if (! anrTimer.waitForDispatchStateChangeLd(this)) {
1290 LOGW("Dropping event because the dispatcher timed out waiting to identify "
1291 "the window that should receive it.");
1292 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001293 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
1294 break; // timed out, exit wait loop
Jeff Brown349703e2010-06-22 01:27:15 -07001295 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001296 }
Jeff Brown349703e2010-06-22 01:27:15 -07001297
1298 // If dispatch is not enabled then fail.
1299 if (! mDispatchEnabled) {
1300 LOGI("Dropping event because input dispatch is disabled.");
1301 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001302 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
Jeff Brown349703e2010-06-22 01:27:15 -07001303 break; // failed, exit wait loop
1304 }
1305
1306 // If dispatch is frozen or we don't have valid window data yet then wait.
1307 if (mDispatchFrozen || ! mWindowsReady) {
1308#if DEBUG_INPUT_DISPATCHER_POLICY
1309 LOGD("Waiting because dispatch is frozen or windows are not ready.");
1310#endif
1311 anrTimer.dispatchFrozenBySystem();
1312 continue;
1313 }
1314
1315 // Update the touch state as needed based on the properties of the touch event.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001316 if (action == AMOTION_EVENT_ACTION_DOWN) {
1317 /* Case 1: ACTION_DOWN */
1318
Jeff Brown349703e2010-06-22 01:27:15 -07001319 InputWindow* newTouchedWindow = NULL;
1320 mTempTouchedOutsideWindows.clear();
1321
1322 int32_t x = int32_t(motionEvent->getX(0));
1323 int32_t y = int32_t(motionEvent->getY(0));
1324 InputWindow* topErrorWindow = NULL;
1325
1326 // Traverse windows from front to back to find touched window and outside targets.
1327 size_t numWindows = mWindows.size();
1328 for (size_t i = 0; i < numWindows; i++) {
1329 InputWindow* window = & mWindows.editItemAt(i);
1330 int32_t flags = window->layoutParamsFlags;
1331
1332 if (flags & FLAG_SYSTEM_ERROR) {
1333 if (! topErrorWindow) {
1334 topErrorWindow = window;
1335 }
1336 }
1337
1338 if (window->visible) {
1339 if (! (flags & FLAG_NOT_TOUCHABLE)) {
1340 bool isTouchModal = (flags &
1341 (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL)) == 0;
1342 if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
1343 if (! screenWasOff || flags & FLAG_TOUCHABLE_WHEN_WAKING) {
1344 newTouchedWindow = window;
1345 }
1346 break; // found touched window, exit window loop
1347 }
1348 }
1349
1350 if (flags & FLAG_WATCH_OUTSIDE_TOUCH) {
1351 mTempTouchedOutsideWindows.push(window);
1352 }
1353 }
1354 }
1355
1356 // If there is an error window but it is not taking focus (typically because
1357 // it is invisible) then wait for it. Any other focused window may in
1358 // fact be in ANR state.
1359 if (topErrorWindow && newTouchedWindow != topErrorWindow) {
1360#if DEBUG_INPUT_DISPATCHER_POLICY
1361 LOGD("Waiting because system error window is pending.");
1362#endif
1363 anrTimer.dispatchFrozenBySystem();
1364 continue; // wait some more
1365 }
1366
1367 // If we did not find a touched window then fail.
1368 if (! newTouchedWindow) {
1369 if (mFocusedApplication) {
1370#if DEBUG_FOCUS
1371 LOGD("Waiting because there is no focused window but there is a "
1372 "focused application that may yet introduce a new target: '%s'.",
1373 mFocusedApplication->name.string());
1374#endif
1375 continue;
1376 }
1377
1378 LOGI("Dropping event because there is no touched window or focused application.");
1379 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001380 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
Jeff Brown349703e2010-06-22 01:27:15 -07001381 break; // failed, exit wait loop
1382 }
1383
1384 // Check permissions.
1385 if (! checkInjectionPermission(newTouchedWindow, injectorPid, injectorUid)) {
1386 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001387 injectionPermission = INJECTION_PERMISSION_DENIED;
Jeff Brown349703e2010-06-22 01:27:15 -07001388 break; // failed, exit wait loop
1389 }
1390
1391 // If the touched window is paused then keep waiting.
1392 if (newTouchedWindow->paused) {
1393#if DEBUG_INPUT_DISPATCHER_POLICY
1394 LOGD("Waiting because touched window is paused.");
1395#endif
1396 anrTimer.dispatchPausedByApplication(newTouchedWindow);
1397 continue; // wait some more
1398 }
1399
1400 // Success! Update the touch dispatch state for real.
1401 releaseTouchedWindowLd();
1402
1403 mTouchedWindow = newTouchedWindow;
1404
1405 if (newTouchedWindow->hasWallpaper) {
1406 mTouchedWallpaperWindows.appendVector(mWallpaperWindows);
1407 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001408
1409 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1410 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001411 break; // done
1412 } else {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001413 /* Case 2: Everything but ACTION_DOWN */
1414
Jeff Brown349703e2010-06-22 01:27:15 -07001415 // Check permissions.
1416 if (! checkInjectionPermission(mTouchedWindow, injectorPid, injectorUid)) {
1417 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001418 injectionPermission = INJECTION_PERMISSION_DENIED;
1419 break; // failed, exit wait loop
1420 }
1421
1422 // If the pointer is not currently down, then ignore the event.
1423 if (! mTouchDown) {
1424 LOGI("Dropping event because the pointer is not down.");
1425 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1426 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001427 break; // failed, exit wait loop
1428 }
1429
1430 // If there is no currently touched window then fail.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001431 if (! mTouchedWindow) {
1432 LOGW("Dropping event because there is no touched window to receive it.");
Jeff Brown349703e2010-06-22 01:27:15 -07001433 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001434 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001435 break; // failed, exit wait loop
1436 }
1437
1438 // If the touched window is paused then keep waiting.
1439 if (mTouchedWindow->paused) {
1440#if DEBUG_INPUT_DISPATCHER_POLICY
1441 LOGD("Waiting because touched window is paused.");
1442#endif
1443 anrTimer.dispatchPausedByApplication(mTouchedWindow);
1444 continue; // wait some more
1445 }
1446
1447 // Success!
Jeff Brownc5ed5912010-07-14 18:48:53 -07001448 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1449 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001450 break; // done
1451 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001452 }
Jeff Brown349703e2010-06-22 01:27:15 -07001453
1454 // Output targets.
Jeff Brown349703e2010-06-22 01:27:15 -07001455 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
Jeff Brown349703e2010-06-22 01:27:15 -07001456 size_t numWallpaperWindows = mTouchedWallpaperWindows.size();
1457 for (size_t i = 0; i < numWallpaperWindows; i++) {
1458 addTarget(mTouchedWallpaperWindows[i], 0, 0, outTargets);
1459 }
1460
1461 size_t numOutsideWindows = mTempTouchedOutsideWindows.size();
1462 for (size_t i = 0; i < numOutsideWindows; i++) {
1463 addTarget(mTempTouchedOutsideWindows[i], InputTarget::FLAG_OUTSIDE, 0, outTargets);
1464 }
1465
1466 addTarget(mTouchedWindow, InputTarget::FLAG_SYNC,
1467 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
1468 outTouchedWindow = mTouchedWindow;
1469 } else {
Jeff Brown349703e2010-06-22 01:27:15 -07001470 outTouchedWindow = NULL;
1471 }
1472 mTempTouchedOutsideWindows.clear();
1473
Jeff Brownc5ed5912010-07-14 18:48:53 -07001474 // Check injection permission once and for all.
1475 if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
1476 if (checkInjectionPermission(action == AMOTION_EVENT_ACTION_DOWN ? NULL : mTouchedWindow,
1477 injectorPid, injectorUid)) {
1478 injectionPermission = INJECTION_PERMISSION_GRANTED;
1479 } else {
1480 injectionPermission = INJECTION_PERMISSION_DENIED;
1481 }
1482 }
1483
1484 // Update final pieces of touch state if the injector had permission.
1485 if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
1486 if (action == AMOTION_EVENT_ACTION_DOWN) {
Jeff Brown349703e2010-06-22 01:27:15 -07001487 if (mTouchDown) {
1488 // This is weird. We got a down but we thought it was already down!
1489 LOGW("Pointer down received while already down.");
1490 } else {
1491 mTouchDown = true;
1492 }
1493
1494 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1495 // Since we failed to identify a target for this touch down, we may still
1496 // be holding on to an earlier target from a previous touch down. Release it.
1497 releaseTouchedWindowLd();
1498 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001499 } else if (action == AMOTION_EVENT_ACTION_UP) {
Jeff Brown349703e2010-06-22 01:27:15 -07001500 mTouchDown = false;
1501 releaseTouchedWindowLd();
1502 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001503 } else {
1504 LOGW("Not updating touch focus because injection was denied.");
Jeff Brown349703e2010-06-22 01:27:15 -07001505 }
1506
1507#if DEBUG_FOCUS
1508 LOGD("waitForTouchedWindow finished: injectionResult=%d",
1509 injectionResult);
Jeff Browne33348b2010-07-15 23:54:05 -07001510 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001511#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001512 return injectionResult;
1513}
1514
Jeff Brown349703e2010-06-22 01:27:15 -07001515void NativeInputManager::releaseTouchedWindowLd() {
1516 mTouchedWindow = NULL;
1517 mTouchedWallpaperWindows.clear();
1518}
1519
1520void NativeInputManager::addTarget(const InputWindow* window, int32_t targetFlags,
1521 nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets) {
1522 nsecs_t timeout = window->dispatchingTimeout - timeSpentWaitingForApplication;
1523 if (timeout < MIN_INPUT_DISPATCHING_TIMEOUT) {
1524 timeout = MIN_INPUT_DISPATCHING_TIMEOUT;
1525 }
1526
1527 outTargets.push();
1528
1529 InputTarget& target = outTargets.editTop();
1530 target.inputChannel = window->inputChannel;
1531 target.flags = targetFlags;
1532 target.timeout = timeout;
1533 target.xOffset = - window->frameLeft;
1534 target.yOffset = - window->frameTop;
1535}
1536
1537bool NativeInputManager::checkInjectionPermission(const InputWindow* window,
1538 int32_t injectorPid, int32_t injectorUid) {
1539 if (injectorUid > 0 && (window == NULL || window->ownerUid != injectorUid)) {
1540 JNIEnv* env = jniEnv();
1541 jboolean result = env->CallBooleanMethod(mCallbacksObj,
1542 gCallbacksClassInfo.checkInjectEventsPermission, injectorPid, injectorUid);
1543 checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission");
1544
1545 if (! result) {
1546 if (window) {
1547 LOGW("Permission denied: injecting event from pid %d uid %d to window "
1548 "with input channel %s owned by uid %d",
1549 injectorPid, injectorUid, window->inputChannel->getName().string(),
1550 window->ownerUid);
1551 } else {
1552 LOGW("Permission denied: injecting event from pid %d uid %d",
1553 injectorPid, injectorUid);
1554 }
1555 return false;
1556 }
1557 }
1558
1559 return true;
1560}
1561
1562int32_t NativeInputManager::waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
1563 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets) {
1564#if DEBUG_INPUT_DISPATCHER_POLICY
1565 LOGD("waitForKeyEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1566 policyFlags, injectorPid, injectorUid);
1567#endif
1568
1569 int32_t windowType;
1570 { // acquire lock
1571 AutoMutex _l(mDispatchLock);
1572
1573 InputWindow* focusedWindow;
1574 int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
1575 injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
1576 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1577 return injectionResult;
1578 }
1579
1580 windowType = focusedWindow->layoutParamsType;
1581 } // release lock
1582
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001583 if (isPolicyKey(keyEvent->getKeyCode(), isScreenOn())) {
1584 const InputTarget& target = outTargets.top();
1585 bool consumed = interceptKeyBeforeDispatching(target, keyEvent, policyFlags);
1586 if (consumed) {
1587 outTargets.clear();
1588 return INPUT_EVENT_INJECTION_SUCCEEDED;
1589 }
Jeff Brown349703e2010-06-22 01:27:15 -07001590 }
1591
1592 pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
1593 return INPUT_EVENT_INJECTION_SUCCEEDED;
1594}
1595
1596int32_t NativeInputManager::waitForMotionEventTargets(MotionEvent* motionEvent,
1597 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001598 Vector<InputTarget>& outTargets) {
Jeff Brown349703e2010-06-22 01:27:15 -07001599#if DEBUG_INPUT_DISPATCHER_POLICY
1600 LOGD("waitForMotionEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1601 policyFlags, injectorPid, injectorUid);
1602#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001603
Jeff Brownc5ed5912010-07-14 18:48:53 -07001604 int32_t source = motionEvent->getSource();
1605 if (source & AINPUT_SOURCE_CLASS_POINTER) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001606 return waitForTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
Jeff Brown349703e2010-06-22 01:27:15 -07001607 outTargets);
Jeff Brownc5ed5912010-07-14 18:48:53 -07001608 } else {
1609 return waitForNonTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
1610 outTargets);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001611 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001612}
1613
Jeff Brownc5ed5912010-07-14 18:48:53 -07001614int32_t NativeInputManager::waitForNonTouchEventTargets(MotionEvent* motionEvent,
Jeff Brown349703e2010-06-22 01:27:15 -07001615 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
1616 Vector<InputTarget>& outTargets) {
1617#if DEBUG_INPUT_DISPATCHER_POLICY
Jeff Brownc5ed5912010-07-14 18:48:53 -07001618 LOGD("waitForNonTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
Jeff Brown349703e2010-06-22 01:27:15 -07001619 policyFlags, injectorPid, injectorUid);
1620#endif
1621
1622 int32_t windowType;
1623 { // acquire lock
1624 AutoMutex _l(mDispatchLock);
1625
1626 InputWindow* focusedWindow;
1627 int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
1628 injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
1629 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1630 return injectionResult;
1631 }
1632
1633 windowType = focusedWindow->layoutParamsType;
1634 } // release lock
1635
1636 pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
1637 return INPUT_EVENT_INJECTION_SUCCEEDED;
1638}
1639
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001640int32_t NativeInputManager::waitForTouchEventTargets(MotionEvent* motionEvent,
Jeff Brown349703e2010-06-22 01:27:15 -07001641 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
1642 Vector<InputTarget>& outTargets) {
1643#if DEBUG_INPUT_DISPATCHER_POLICY
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001644 LOGD("waitForTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
Jeff Brown349703e2010-06-22 01:27:15 -07001645 policyFlags, injectorPid, injectorUid);
1646#endif
1647
1648 int32_t windowType;
1649 { // acquire lock
1650 AutoMutex _l(mDispatchLock);
1651
1652 InputWindow* touchedWindow;
1653 int32_t injectionResult = waitForTouchedWindowLd(motionEvent, policyFlags,
1654 injectorPid, injectorUid, outTargets, /*out*/ touchedWindow);
1655 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1656 return injectionResult;
1657 }
1658
1659 windowType = touchedWindow->layoutParamsType;
1660 } // release lock
1661
1662 int32_t eventType;
1663 switch (motionEvent->getAction()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001664 case AMOTION_EVENT_ACTION_DOWN:
Jeff Brown349703e2010-06-22 01:27:15 -07001665 eventType = POWER_MANAGER_TOUCH_EVENT;
1666 break;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001667 case AMOTION_EVENT_ACTION_UP:
Jeff Brown349703e2010-06-22 01:27:15 -07001668 eventType = POWER_MANAGER_TOUCH_UP_EVENT;
1669 break;
1670 default:
1671 if (motionEvent->getEventTime() - motionEvent->getDownTime()
1672 >= EVENT_IGNORE_DURATION) {
1673 eventType = POWER_MANAGER_TOUCH_EVENT;
1674 } else {
1675 eventType = POWER_MANAGER_LONG_TOUCH_EVENT;
1676 }
1677 break;
1678 }
1679 pokeUserActivityIfNeeded(windowType, eventType);
1680 return INPUT_EVENT_INJECTION_SUCCEEDED;
1681}
1682
Jeff Brownd0097872010-06-30 14:41:59 -07001683bool NativeInputManager::interceptKeyBeforeDispatching(const InputTarget& target,
1684 const KeyEvent* keyEvent, uint32_t policyFlags) {
1685 JNIEnv* env = jniEnv();
1686
1687 jobject inputChannelObj = getInputChannelObjLocal(env, target.inputChannel);
1688 if (inputChannelObj) {
1689 jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
1690 gCallbacksClassInfo.interceptKeyBeforeDispatching,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001691 inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(),
1692 keyEvent->getKeyCode(), keyEvent->getMetaState(),
Jeff Brownd0097872010-06-30 14:41:59 -07001693 keyEvent->getRepeatCount(), policyFlags);
1694 bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
1695
1696 env->DeleteLocalRef(inputChannelObj);
1697
1698 return consumed && ! error;
1699 } else {
1700 LOGW("Could not apply key dispatch policy because input channel '%s' is "
1701 "no longer valid.", target.inputChannel->getName().string());
1702 return false;
1703 }
1704}
1705
Jeff Brown349703e2010-06-22 01:27:15 -07001706void NativeInputManager::pokeUserActivityIfNeeded(int32_t windowType, int32_t eventType) {
1707 if (windowType != TYPE_KEYGUARD) {
1708 nsecs_t eventTime = now();
1709 pokeUserActivity(eventTime, eventType);
1710 }
1711}
1712
1713void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001714 android_server_PowerManagerService_userActivity(eventTime, eventType);
Jeff Brown349703e2010-06-22 01:27:15 -07001715}
1716
Jeff Browne33348b2010-07-15 23:54:05 -07001717void NativeInputManager::logDispatchStateLd() {
1718 String8 dump;
1719 dumpDispatchStateLd(dump);
1720 LOGD("%s", dump.string());
1721}
1722
1723void NativeInputManager::dumpDispatchStateLd(String8& dump) {
1724 dump.appendFormat(" dispatchEnabled: %d\n", mDispatchEnabled);
1725 dump.appendFormat(" dispatchFrozen: %d\n", mDispatchFrozen);
1726 dump.appendFormat(" windowsReady: %d\n", mWindowsReady);
1727
Jeff Brown349703e2010-06-22 01:27:15 -07001728 if (mFocusedApplication) {
Jeff Browne33348b2010-07-15 23:54:05 -07001729 dump.appendFormat(" focusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001730 mFocusedApplication->name.string(),
1731 mFocusedApplication->dispatchingTimeout / 1000000.0);
1732 } else {
Jeff Browne33348b2010-07-15 23:54:05 -07001733 dump.append(" focusedApplication: <null>\n");
Jeff Brown349703e2010-06-22 01:27:15 -07001734 }
Jeff Browne33348b2010-07-15 23:54:05 -07001735 dump.appendFormat(" focusedWindow: '%s'\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001736 mFocusedWindow != NULL ? mFocusedWindow->inputChannel->getName().string() : "<null>");
Jeff Browne33348b2010-07-15 23:54:05 -07001737 dump.appendFormat(" touchedWindow: '%s', touchDown=%d\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001738 mTouchedWindow != NULL ? mTouchedWindow->inputChannel->getName().string() : "<null>",
1739 mTouchDown);
1740 for (size_t i = 0; i < mTouchedWallpaperWindows.size(); i++) {
Jeff Browne33348b2010-07-15 23:54:05 -07001741 dump.appendFormat(" touchedWallpaperWindows[%d]: '%s'\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001742 i, mTouchedWallpaperWindows[i]->inputChannel->getName().string());
1743 }
1744 for (size_t i = 0; i < mWindows.size(); i++) {
Jeff Browne33348b2010-07-15 23:54:05 -07001745 dump.appendFormat(" windows[%d]: '%s', paused=%d, hasFocus=%d, hasWallpaper=%d, "
1746 "visible=%d, flags=0x%08x, type=0x%08x, "
Jeff Brown349703e2010-06-22 01:27:15 -07001747 "frame=[%d,%d], touchableArea=[%d,%d][%d,%d], "
Jeff Browne33348b2010-07-15 23:54:05 -07001748 "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001749 i, mWindows[i].inputChannel->getName().string(),
1750 mWindows[i].paused, mWindows[i].hasFocus, mWindows[i].hasWallpaper,
1751 mWindows[i].visible, mWindows[i].layoutParamsFlags, mWindows[i].layoutParamsType,
1752 mWindows[i].frameLeft, mWindows[i].frameTop,
1753 mWindows[i].touchableAreaLeft, mWindows[i].touchableAreaTop,
1754 mWindows[i].touchableAreaRight, mWindows[i].touchableAreaBottom,
1755 mWindows[i].ownerPid, mWindows[i].ownerUid,
1756 mWindows[i].dispatchingTimeout / 1000000.0);
1757 }
Jeff Brown349703e2010-06-22 01:27:15 -07001758}
1759
1760// ----------------------------------------------------------------------------
1761
1762NativeInputManager::ANRTimer::ANRTimer() :
1763 mBudget(APPLICATION), mStartTime(now()), mFrozen(false), mPausedWindow(NULL) {
1764}
1765
1766void NativeInputManager::ANRTimer::dispatchFrozenBySystem() {
1767 mFrozen = true;
1768}
1769
1770void NativeInputManager::ANRTimer::dispatchPausedByApplication(InputWindow* pausedWindow) {
1771 mPausedWindow = pausedWindow;
1772}
1773
1774bool NativeInputManager::ANRTimer::waitForDispatchStateChangeLd(NativeInputManager* inputManager) {
1775 nsecs_t currentTime = now();
1776
1777 Budget newBudget;
1778 nsecs_t dispatchingTimeout;
1779 sp<InputChannel> pausedChannel = NULL;
1780 jobject tokenObj = NULL;
1781 if (mFrozen) {
1782 newBudget = SYSTEM;
1783 dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
1784 mFrozen = false;
1785 } else if (mPausedWindow) {
1786 newBudget = APPLICATION;
1787 dispatchingTimeout = mPausedWindow->dispatchingTimeout;
1788 pausedChannel = mPausedWindow->inputChannel;
1789 mPausedWindow = NULL;
1790 } else if (inputManager->mFocusedApplication) {
1791 newBudget = APPLICATION;
1792 dispatchingTimeout = inputManager->mFocusedApplication->dispatchingTimeout;
1793 tokenObj = jniEnv()->NewLocalRef(inputManager->mFocusedApplication->tokenObjWeak);
1794 } else {
1795 newBudget = APPLICATION;
1796 dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
1797 }
1798
1799 if (mBudget != newBudget) {
1800 mBudget = newBudget;
1801 mStartTime = currentTime;
1802 }
1803
1804 bool result = false;
1805 nsecs_t timeoutRemaining = mStartTime + dispatchingTimeout - currentTime;
1806 if (timeoutRemaining > 0
1807 && inputManager->mDispatchStateChanged.waitRelative(inputManager->mDispatchLock,
1808 timeoutRemaining) == OK) {
1809 result = true;
1810 } else {
1811 if (pausedChannel != NULL || tokenObj != NULL) {
1812 bool resumed;
1813 nsecs_t newTimeout = 0;
1814
1815 inputManager->mDispatchLock.unlock(); // release lock
1816 if (pausedChannel != NULL) {
1817 resumed = inputManager->notifyInputChannelANR(pausedChannel, /*out*/ newTimeout);
1818 } else {
1819 resumed = inputManager->notifyANR(tokenObj, /*out*/ newTimeout);
1820 }
1821 inputManager->mDispatchLock.lock(); // re-acquire lock
1822
1823 if (resumed) {
1824 mStartTime = now() - dispatchingTimeout + newTimeout;
1825 result = true;
1826 }
1827 }
1828 }
1829
1830 if (tokenObj) {
1831 jniEnv()->DeleteLocalRef(tokenObj);
1832 }
1833
1834 return result;
1835}
1836
1837nsecs_t NativeInputManager::ANRTimer::getTimeSpentWaitingForApplication() const {
1838 return mBudget == APPLICATION ? now() - mStartTime : 0;
1839}
Jeff Brown9c3cda02010-06-15 01:31:58 -07001840
1841// ----------------------------------------------------------------------------
1842
1843static sp<NativeInputManager> gNativeInputManager;
1844
Jeff Brown46b9ac02010-04-22 18:58:52 -07001845static bool checkInputManagerUnitialized(JNIEnv* env) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001846 if (gNativeInputManager == NULL) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001847 LOGE("Input manager not initialized.");
1848 jniThrowRuntimeException(env, "Input manager not initialized.");
1849 return true;
1850 }
1851 return false;
1852}
1853
1854static void android_server_InputManager_nativeInit(JNIEnv* env, jclass clazz,
1855 jobject callbacks) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001856 if (gNativeInputManager == NULL) {
1857 gNativeInputManager = new NativeInputManager(callbacks);
1858 } else {
1859 LOGE("Input manager already initialized.");
1860 jniThrowRuntimeException(env, "Input manager already initialized.");
Jeff Brown46b9ac02010-04-22 18:58:52 -07001861 }
1862}
1863
1864static void android_server_InputManager_nativeStart(JNIEnv* env, jclass clazz) {
1865 if (checkInputManagerUnitialized(env)) {
1866 return;
1867 }
1868
Jeff Brown9c3cda02010-06-15 01:31:58 -07001869 status_t result = gNativeInputManager->getInputManager()->start();
Jeff Brown46b9ac02010-04-22 18:58:52 -07001870 if (result) {
1871 jniThrowRuntimeException(env, "Input manager could not be started.");
1872 }
1873}
1874
1875static void android_server_InputManager_nativeSetDisplaySize(JNIEnv* env, jclass clazz,
1876 jint displayId, jint width, jint height) {
1877 if (checkInputManagerUnitialized(env)) {
1878 return;
1879 }
1880
1881 // XXX we could get this from the SurfaceFlinger directly instead of requiring it
1882 // to be passed in like this, not sure which is better but leaving it like this
1883 // keeps the window manager in direct control of when display transitions propagate down
1884 // to the input dispatcher
Jeff Brown9c3cda02010-06-15 01:31:58 -07001885 gNativeInputManager->setDisplaySize(displayId, width, height);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001886}
1887
1888static void android_server_InputManager_nativeSetDisplayOrientation(JNIEnv* env, jclass clazz,
1889 jint displayId, jint orientation) {
1890 if (checkInputManagerUnitialized(env)) {
1891 return;
1892 }
1893
Jeff Brown9c3cda02010-06-15 01:31:58 -07001894 gNativeInputManager->setDisplayOrientation(displayId, orientation);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001895}
1896
1897static jint android_server_InputManager_nativeGetScanCodeState(JNIEnv* env, jclass clazz,
1898 jint deviceId, jint deviceClasses, jint scanCode) {
1899 if (checkInputManagerUnitialized(env)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001900 return AKEY_STATE_UNKNOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001901 }
1902
Jeff Brown9c3cda02010-06-15 01:31:58 -07001903 return gNativeInputManager->getInputManager()->getScanCodeState(
1904 deviceId, deviceClasses, scanCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001905}
1906
1907static jint android_server_InputManager_nativeGetKeyCodeState(JNIEnv* env, jclass clazz,
1908 jint deviceId, jint deviceClasses, jint keyCode) {
1909 if (checkInputManagerUnitialized(env)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001910 return AKEY_STATE_UNKNOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001911 }
1912
Jeff Brown9c3cda02010-06-15 01:31:58 -07001913 return gNativeInputManager->getInputManager()->getKeyCodeState(
1914 deviceId, deviceClasses, keyCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001915}
1916
1917static jint android_server_InputManager_nativeGetSwitchState(JNIEnv* env, jclass clazz,
1918 jint deviceId, jint deviceClasses, jint sw) {
1919 if (checkInputManagerUnitialized(env)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001920 return AKEY_STATE_UNKNOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001921 }
1922
Jeff Brown9c3cda02010-06-15 01:31:58 -07001923 return gNativeInputManager->getInputManager()->getSwitchState(deviceId, deviceClasses, sw);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001924}
1925
1926static jboolean android_server_InputManager_nativeHasKeys(JNIEnv* env, jclass clazz,
1927 jintArray keyCodes, jbooleanArray outFlags) {
1928 if (checkInputManagerUnitialized(env)) {
1929 return JNI_FALSE;
1930 }
1931
1932 int32_t* codes = env->GetIntArrayElements(keyCodes, NULL);
1933 uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL);
1934 jsize numCodes = env->GetArrayLength(keyCodes);
1935 jboolean result;
1936 if (numCodes == env->GetArrayLength(outFlags)) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001937 result = gNativeInputManager->getInputManager()->hasKeys(numCodes, codes, flags);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001938 } else {
1939 result = JNI_FALSE;
1940 }
1941
1942 env->ReleaseBooleanArrayElements(outFlags, flags, 0);
1943 env->ReleaseIntArrayElements(keyCodes, codes, 0);
1944 return result;
1945}
1946
1947static void throwInputChannelNotInitialized(JNIEnv* env) {
1948 jniThrowException(env, "java/lang/IllegalStateException",
1949 "inputChannel is not initialized");
1950}
1951
1952static void android_server_InputManager_handleInputChannelDisposed(JNIEnv* env,
1953 jobject inputChannelObj, const sp<InputChannel>& inputChannel, void* data) {
1954 LOGW("Input channel object '%s' was disposed without first being unregistered with "
1955 "the input manager!", inputChannel->getName().string());
1956
Jeff Brown9c3cda02010-06-15 01:31:58 -07001957 if (gNativeInputManager != NULL) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001958 gNativeInputManager->unregisterInputChannel(env, inputChannel);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001959 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001960}
1961
1962static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
1963 jobject inputChannelObj) {
1964 if (checkInputManagerUnitialized(env)) {
1965 return;
1966 }
1967
1968 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
1969 inputChannelObj);
1970 if (inputChannel == NULL) {
1971 throwInputChannelNotInitialized(env);
1972 return;
1973 }
1974
Jeff Brown7fbdc842010-06-17 20:52:56 -07001975
1976 status_t status = gNativeInputManager->registerInputChannel(
1977 env, inputChannel, inputChannelObj);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001978 if (status) {
1979 jniThrowRuntimeException(env, "Failed to register input channel. "
1980 "Check logs for details.");
1981 return;
1982 }
1983
1984 android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
1985 android_server_InputManager_handleInputChannelDisposed, NULL);
1986}
1987
1988static void android_server_InputManager_nativeUnregisterInputChannel(JNIEnv* env, jclass clazz,
1989 jobject inputChannelObj) {
1990 if (checkInputManagerUnitialized(env)) {
1991 return;
1992 }
1993
1994 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
1995 inputChannelObj);
1996 if (inputChannel == NULL) {
1997 throwInputChannelNotInitialized(env);
1998 return;
1999 }
2000
2001 android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL);
2002
Jeff Brown7fbdc842010-06-17 20:52:56 -07002003 status_t status = gNativeInputManager->unregisterInputChannel(env, inputChannel);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002004 if (status) {
2005 jniThrowRuntimeException(env, "Failed to unregister input channel. "
2006 "Check logs for details.");
2007 }
2008}
2009
Jeff Brown7fbdc842010-06-17 20:52:56 -07002010static jint android_server_InputManager_nativeInjectKeyEvent(JNIEnv* env, jclass clazz,
Jeff Brownc5ed5912010-07-14 18:48:53 -07002011 jobject keyEventObj, jint injectorPid, jint injectorUid,
Jeff Brown7fbdc842010-06-17 20:52:56 -07002012 jboolean sync, jint timeoutMillis) {
2013 if (checkInputManagerUnitialized(env)) {
2014 return INPUT_EVENT_INJECTION_FAILED;
2015 }
2016
2017 KeyEvent keyEvent;
Jeff Brownc5ed5912010-07-14 18:48:53 -07002018 android_view_KeyEvent_toNative(env, keyEventObj, & keyEvent);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002019
2020 return gNativeInputManager->getInputManager()->injectInputEvent(& keyEvent,
2021 injectorPid, injectorUid, sync, timeoutMillis);
2022}
2023
2024static jint android_server_InputManager_nativeInjectMotionEvent(JNIEnv* env, jclass clazz,
Jeff Brownc5ed5912010-07-14 18:48:53 -07002025 jobject motionEventObj, jint injectorPid, jint injectorUid,
Jeff Brown7fbdc842010-06-17 20:52:56 -07002026 jboolean sync, jint timeoutMillis) {
2027 if (checkInputManagerUnitialized(env)) {
2028 return INPUT_EVENT_INJECTION_FAILED;
2029 }
2030
2031 MotionEvent motionEvent;
Jeff Brownc5ed5912010-07-14 18:48:53 -07002032 android_view_MotionEvent_toNative(env, motionEventObj, & motionEvent);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002033
2034 return gNativeInputManager->getInputManager()->injectInputEvent(& motionEvent,
2035 injectorPid, injectorUid, sync, timeoutMillis);
2036}
2037
Jeff Brown349703e2010-06-22 01:27:15 -07002038static void android_server_InputManager_nativeSetInputWindows(JNIEnv* env, jclass clazz,
2039 jobjectArray windowObjArray) {
2040 if (checkInputManagerUnitialized(env)) {
2041 return;
2042 }
2043
2044 gNativeInputManager->setInputWindows(env, windowObjArray);
2045}
2046
2047static void android_server_InputManager_nativeSetFocusedApplication(JNIEnv* env, jclass clazz,
2048 jobject applicationObj) {
2049 if (checkInputManagerUnitialized(env)) {
2050 return;
2051 }
2052
2053 gNativeInputManager->setFocusedApplication(env, applicationObj);
2054}
2055
2056static void android_server_InputManager_nativeSetInputDispatchMode(JNIEnv* env,
2057 jclass clazz, jboolean enabled, jboolean frozen) {
2058 if (checkInputManagerUnitialized(env)) {
2059 return;
2060 }
2061
2062 gNativeInputManager->setInputDispatchMode(enabled, frozen);
2063}
2064
2065static void android_server_InputManager_nativePreemptInputDispatch(JNIEnv* env,
2066 jclass clazz) {
2067 if (checkInputManagerUnitialized(env)) {
2068 return;
2069 }
2070
2071 gNativeInputManager->preemptInputDispatch();
2072}
2073
Jeff Browne33348b2010-07-15 23:54:05 -07002074static jstring android_server_InputManager_nativeDump(JNIEnv* env, jclass clazz) {
2075 if (checkInputManagerUnitialized(env)) {
2076 return NULL;
2077 }
2078
2079 String8 dump(gNativeInputManager->dump());
2080 return env->NewStringUTF(dump.string());
2081}
2082
Jeff Brown9c3cda02010-06-15 01:31:58 -07002083// ----------------------------------------------------------------------------
2084
Jeff Brown46b9ac02010-04-22 18:58:52 -07002085static JNINativeMethod gInputManagerMethods[] = {
2086 /* name, signature, funcPtr */
2087 { "nativeInit", "(Lcom/android/server/InputManager$Callbacks;)V",
2088 (void*) android_server_InputManager_nativeInit },
2089 { "nativeStart", "()V",
2090 (void*) android_server_InputManager_nativeStart },
2091 { "nativeSetDisplaySize", "(III)V",
2092 (void*) android_server_InputManager_nativeSetDisplaySize },
2093 { "nativeSetDisplayOrientation", "(II)V",
2094 (void*) android_server_InputManager_nativeSetDisplayOrientation },
2095 { "nativeGetScanCodeState", "(III)I",
2096 (void*) android_server_InputManager_nativeGetScanCodeState },
2097 { "nativeGetKeyCodeState", "(III)I",
2098 (void*) android_server_InputManager_nativeGetKeyCodeState },
2099 { "nativeGetSwitchState", "(III)I",
2100 (void*) android_server_InputManager_nativeGetSwitchState },
2101 { "nativeHasKeys", "([I[Z)Z",
2102 (void*) android_server_InputManager_nativeHasKeys },
2103 { "nativeRegisterInputChannel", "(Landroid/view/InputChannel;)V",
2104 (void*) android_server_InputManager_nativeRegisterInputChannel },
2105 { "nativeUnregisterInputChannel", "(Landroid/view/InputChannel;)V",
Jeff Brown7fbdc842010-06-17 20:52:56 -07002106 (void*) android_server_InputManager_nativeUnregisterInputChannel },
Jeff Brownc5ed5912010-07-14 18:48:53 -07002107 { "nativeInjectKeyEvent", "(Landroid/view/KeyEvent;IIZI)I",
Jeff Brown7fbdc842010-06-17 20:52:56 -07002108 (void*) android_server_InputManager_nativeInjectKeyEvent },
Jeff Brownc5ed5912010-07-14 18:48:53 -07002109 { "nativeInjectMotionEvent", "(Landroid/view/MotionEvent;IIZI)I",
Jeff Brown349703e2010-06-22 01:27:15 -07002110 (void*) android_server_InputManager_nativeInjectMotionEvent },
2111 { "nativeSetInputWindows", "([Lcom/android/server/InputWindow;)V",
2112 (void*) android_server_InputManager_nativeSetInputWindows },
2113 { "nativeSetFocusedApplication", "(Lcom/android/server/InputApplication;)V",
2114 (void*) android_server_InputManager_nativeSetFocusedApplication },
2115 { "nativeSetInputDispatchMode", "(ZZ)V",
2116 (void*) android_server_InputManager_nativeSetInputDispatchMode },
2117 { "nativePreemptInputDispatch", "()V",
Jeff Browne33348b2010-07-15 23:54:05 -07002118 (void*) android_server_InputManager_nativePreemptInputDispatch },
2119 { "nativeDump", "()Ljava/lang/String;",
2120 (void*) android_server_InputManager_nativeDump },
Jeff Brown46b9ac02010-04-22 18:58:52 -07002121};
2122
2123#define FIND_CLASS(var, className) \
2124 var = env->FindClass(className); \
2125 LOG_FATAL_IF(! var, "Unable to find class " className); \
2126 var = jclass(env->NewGlobalRef(var));
2127
2128#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
2129 var = env->GetMethodID(clazz, methodName, methodDescriptor); \
2130 LOG_FATAL_IF(! var, "Unable to find method " methodName);
2131
2132#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
2133 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
2134 LOG_FATAL_IF(! var, "Unable to find field " fieldName);
2135
2136int register_android_server_InputManager(JNIEnv* env) {
2137 int res = jniRegisterNativeMethods(env, "com/android/server/InputManager",
2138 gInputManagerMethods, NELEM(gInputManagerMethods));
2139 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
2140
Jeff Brown9c3cda02010-06-15 01:31:58 -07002141 // Callbacks
Jeff Brown46b9ac02010-04-22 18:58:52 -07002142
2143 FIND_CLASS(gCallbacksClassInfo.clazz, "com/android/server/InputManager$Callbacks");
2144
Jeff Brown46b9ac02010-04-22 18:58:52 -07002145 GET_METHOD_ID(gCallbacksClassInfo.notifyConfigurationChanged, gCallbacksClassInfo.clazz,
2146 "notifyConfigurationChanged", "(JIII)V");
2147
2148 GET_METHOD_ID(gCallbacksClassInfo.notifyLidSwitchChanged, gCallbacksClassInfo.clazz,
2149 "notifyLidSwitchChanged", "(JZ)V");
2150
Jeff Brown7fbdc842010-06-17 20:52:56 -07002151 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelBroken, gCallbacksClassInfo.clazz,
2152 "notifyInputChannelBroken", "(Landroid/view/InputChannel;)V");
2153
2154 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelANR, gCallbacksClassInfo.clazz,
2155 "notifyInputChannelANR", "(Landroid/view/InputChannel;)J");
2156
2157 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelRecoveredFromANR, gCallbacksClassInfo.clazz,
2158 "notifyInputChannelRecoveredFromANR", "(Landroid/view/InputChannel;)V");
2159
Jeff Brown349703e2010-06-22 01:27:15 -07002160 GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
2161 "notifyANR", "(Ljava/lang/Object;)J");
2162
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002163 GET_METHOD_ID(gCallbacksClassInfo.virtualKeyDownFeedback, gCallbacksClassInfo.clazz,
2164 "virtualKeyDownFeedback", "()V");
Jeff Brown46b9ac02010-04-22 18:58:52 -07002165
Jeff Brown349703e2010-06-22 01:27:15 -07002166 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002167 "interceptKeyBeforeQueueing", "(JIZIZ)I");
Jeff Brown349703e2010-06-22 01:27:15 -07002168
2169 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002170 "interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIIIII)Z");
Jeff Brown349703e2010-06-22 01:27:15 -07002171
2172 GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,
2173 "checkInjectEventsPermission", "(II)Z");
Jeff Brown46b9ac02010-04-22 18:58:52 -07002174
Jeff Brown46b9ac02010-04-22 18:58:52 -07002175 GET_METHOD_ID(gCallbacksClassInfo.notifyAppSwitchComing, gCallbacksClassInfo.clazz,
2176 "notifyAppSwitchComing", "()V");
2177
2178 GET_METHOD_ID(gCallbacksClassInfo.filterTouchEvents, gCallbacksClassInfo.clazz,
2179 "filterTouchEvents", "()Z");
2180
2181 GET_METHOD_ID(gCallbacksClassInfo.filterJumpyTouchEvents, gCallbacksClassInfo.clazz,
2182 "filterJumpyTouchEvents", "()Z");
2183
2184 GET_METHOD_ID(gCallbacksClassInfo.getVirtualKeyDefinitions, gCallbacksClassInfo.clazz,
2185 "getVirtualKeyDefinitions",
2186 "(Ljava/lang/String;)[Lcom/android/server/InputManager$VirtualKeyDefinition;");
2187
2188 GET_METHOD_ID(gCallbacksClassInfo.getExcludedDeviceNames, gCallbacksClassInfo.clazz,
2189 "getExcludedDeviceNames", "()[Ljava/lang/String;");
2190
Jeff Brown46b9ac02010-04-22 18:58:52 -07002191 // VirtualKeyDefinition
2192
2193 FIND_CLASS(gVirtualKeyDefinitionClassInfo.clazz,
2194 "com/android/server/InputManager$VirtualKeyDefinition");
2195
2196 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.scanCode, gVirtualKeyDefinitionClassInfo.clazz,
2197 "scanCode", "I");
2198
2199 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerX, gVirtualKeyDefinitionClassInfo.clazz,
2200 "centerX", "I");
2201
2202 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerY, gVirtualKeyDefinitionClassInfo.clazz,
2203 "centerY", "I");
2204
2205 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.width, gVirtualKeyDefinitionClassInfo.clazz,
2206 "width", "I");
2207
2208 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.height, gVirtualKeyDefinitionClassInfo.clazz,
2209 "height", "I");
2210
Jeff Brown349703e2010-06-22 01:27:15 -07002211 // InputWindow
Jeff Brown7fbdc842010-06-17 20:52:56 -07002212
Jeff Brown349703e2010-06-22 01:27:15 -07002213 FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002214
Jeff Brown349703e2010-06-22 01:27:15 -07002215 GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
2216 "inputChannel", "Landroid/view/InputChannel;");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002217
Jeff Brown349703e2010-06-22 01:27:15 -07002218 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
2219 "layoutParamsFlags", "I");
2220
2221 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
2222 "layoutParamsType", "I");
2223
2224 GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
2225 "dispatchingTimeoutNanos", "J");
2226
2227 GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
2228 "frameLeft", "I");
2229
2230 GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
2231 "frameTop", "I");
2232
2233 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
2234 "touchableAreaLeft", "I");
2235
2236 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
2237 "touchableAreaTop", "I");
2238
2239 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
2240 "touchableAreaRight", "I");
2241
2242 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
2243 "touchableAreaBottom", "I");
2244
2245 GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
2246 "visible", "Z");
2247
2248 GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
2249 "hasFocus", "Z");
2250
2251 GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
2252 "hasWallpaper", "Z");
2253
2254 GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
2255 "paused", "Z");
2256
2257 GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
2258 "ownerPid", "I");
2259
2260 GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
2261 "ownerUid", "I");
2262
2263 // InputApplication
2264
2265 FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication");
2266
2267 GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
2268 "name", "Ljava/lang/String;");
2269
2270 GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
2271 gInputApplicationClassInfo.clazz,
2272 "dispatchingTimeoutNanos", "J");
2273
2274 GET_FIELD_ID(gInputApplicationClassInfo.token, gInputApplicationClassInfo.clazz,
2275 "token", "Ljava/lang/Object;");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002276
Jeff Brown46b9ac02010-04-22 18:58:52 -07002277 return 0;
2278}
2279
Jeff Brown46b9ac02010-04-22 18:58:52 -07002280} /* namespace android */