blob: 0992b33f877d2988ce6fb3d031c3c5a16f4c3a13 [file] [log] [blame]
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "InputManager-JNI"
18
Jeff Brown9c3cda02010-06-15 01:31:58 -070019//#define LOG_NDEBUG 0
20
21// Log debug messages about InputReaderPolicy
Jeff Brown349703e2010-06-22 01:27:15 -070022#define DEBUG_INPUT_READER_POLICY 0
Jeff Brown9c3cda02010-06-15 01:31:58 -070023
24// Log debug messages about InputDispatcherPolicy
Jeff Brown349703e2010-06-22 01:27:15 -070025#define DEBUG_INPUT_DISPATCHER_POLICY 0
Jeff Brown9c3cda02010-06-15 01:31:58 -070026
Jeff Brown349703e2010-06-22 01:27:15 -070027// Log debug messages about input focus tracking
28#define DEBUG_FOCUS 0
Jeff Brown9c3cda02010-06-15 01:31:58 -070029
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070030#include "JNIHelp.h"
31#include "jni.h"
Jeff Brown349703e2010-06-22 01:27:15 -070032#include <limits.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070033#include <android_runtime/AndroidRuntime.h>
Jeff Brown9c3cda02010-06-15 01:31:58 -070034#include <ui/InputReader.h>
35#include <ui/InputDispatcher.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070036#include <ui/InputManager.h>
37#include <ui/InputTransport.h>
38#include <utils/Log.h>
39#include <utils/threads.h>
40#include "../../core/jni/android_view_KeyEvent.h"
41#include "../../core/jni/android_view_MotionEvent.h"
42#include "../../core/jni/android_view_InputChannel.h"
Jeff Brown00fa7bd2010-07-02 15:37:36 -070043#include "com_android_server_PowerManagerService.h"
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070044
45namespace android {
46
Jeff Brown349703e2010-06-22 01:27:15 -070047// Window flags from WindowManager.LayoutParams
48enum {
49 FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
50 FLAG_DIM_BEHIND = 0x00000002,
51 FLAG_BLUR_BEHIND = 0x00000004,
52 FLAG_NOT_FOCUSABLE = 0x00000008,
53 FLAG_NOT_TOUCHABLE = 0x00000010,
54 FLAG_NOT_TOUCH_MODAL = 0x00000020,
55 FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
56 FLAG_KEEP_SCREEN_ON = 0x00000080,
57 FLAG_LAYOUT_IN_SCREEN = 0x00000100,
58 FLAG_LAYOUT_NO_LIMITS = 0x00000200,
59 FLAG_FULLSCREEN = 0x00000400,
60 FLAG_FORCE_NOT_FULLSCREEN = 0x00000800,
61 FLAG_DITHER = 0x00001000,
62 FLAG_SECURE = 0x00002000,
63 FLAG_SCALED = 0x00004000,
64 FLAG_IGNORE_CHEEK_PRESSES = 0x00008000,
65 FLAG_LAYOUT_INSET_DECOR = 0x00010000,
66 FLAG_ALT_FOCUSABLE_IM = 0x00020000,
67 FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
68 FLAG_SHOW_WHEN_LOCKED = 0x00080000,
69 FLAG_SHOW_WALLPAPER = 0x00100000,
70 FLAG_TURN_SCREEN_ON = 0x00200000,
71 FLAG_DISMISS_KEYGUARD = 0x00400000,
72 FLAG_IMMERSIVE = 0x00800000,
73 FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000,
74 FLAG_COMPATIBLE_WINDOW = 0x20000000,
75 FLAG_SYSTEM_ERROR = 0x40000000,
76};
77
78// Window types from WindowManager.LayoutParams
79enum {
80 FIRST_APPLICATION_WINDOW = 1,
81 TYPE_BASE_APPLICATION = 1,
82 TYPE_APPLICATION = 2,
83 TYPE_APPLICATION_STARTING = 3,
84 LAST_APPLICATION_WINDOW = 99,
85 FIRST_SUB_WINDOW = 1000,
86 TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW,
87 TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1,
88 TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2,
89 TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3,
90 TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4,
91 LAST_SUB_WINDOW = 1999,
92 FIRST_SYSTEM_WINDOW = 2000,
93 TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW,
94 TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1,
95 TYPE_PHONE = FIRST_SYSTEM_WINDOW+2,
96 TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3,
97 TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4,
98 TYPE_TOAST = FIRST_SYSTEM_WINDOW+5,
99 TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6,
100 TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7,
101 TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8,
102 TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9,
103 TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10,
104 TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11,
105 TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
106 TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13,
107 TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14,
108 LAST_SYSTEM_WINDOW = 2999,
109};
110
Jeff Brown349703e2010-06-22 01:27:15 -0700111// Delay between reporting long touch events to the power manager.
112const nsecs_t EVENT_IGNORE_DURATION = 300 * 1000000LL; // 300 ms
113
114// Default input dispatching timeout if there is no focused application or paused window
115// from which to determine an appropriate dispatching timeout.
116const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
117
118// Minimum amount of time to provide to the input dispatcher for delivery of an event
119// regardless of how long the application window was paused.
120const nsecs_t MIN_INPUT_DISPATCHING_TIMEOUT = 1000 * 1000000LL; // 1 sec
121
Jeff Brown9c3cda02010-06-15 01:31:58 -0700122// ----------------------------------------------------------------------------
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700123
124static struct {
125 jclass clazz;
126
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700127 jmethodID notifyConfigurationChanged;
128 jmethodID notifyLidSwitchChanged;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700129 jmethodID notifyInputChannelBroken;
130 jmethodID notifyInputChannelANR;
131 jmethodID notifyInputChannelRecoveredFromANR;
Jeff Brown349703e2010-06-22 01:27:15 -0700132 jmethodID notifyANR;
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700133 jmethodID virtualKeyDownFeedback;
Jeff Brown349703e2010-06-22 01:27:15 -0700134 jmethodID interceptKeyBeforeQueueing;
135 jmethodID interceptKeyBeforeDispatching;
136 jmethodID checkInjectEventsPermission;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700137 jmethodID notifyAppSwitchComing;
138 jmethodID filterTouchEvents;
139 jmethodID filterJumpyTouchEvents;
140 jmethodID getVirtualKeyDefinitions;
141 jmethodID getExcludedDeviceNames;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700142} gCallbacksClassInfo;
143
144static struct {
145 jclass clazz;
146
147 jfieldID scanCode;
148 jfieldID centerX;
149 jfieldID centerY;
150 jfieldID width;
151 jfieldID height;
152} gVirtualKeyDefinitionClassInfo;
153
Jeff Brown7fbdc842010-06-17 20:52:56 -0700154static struct {
155 jclass clazz;
156
Jeff Brown349703e2010-06-22 01:27:15 -0700157 jfieldID inputChannel;
158 jfieldID layoutParamsFlags;
159 jfieldID layoutParamsType;
160 jfieldID dispatchingTimeoutNanos;
161 jfieldID frameLeft;
162 jfieldID frameTop;
163 jfieldID touchableAreaLeft;
164 jfieldID touchableAreaTop;
165 jfieldID touchableAreaRight;
166 jfieldID touchableAreaBottom;
167 jfieldID visible;
168 jfieldID hasFocus;
169 jfieldID hasWallpaper;
170 jfieldID paused;
171 jfieldID ownerPid;
172 jfieldID ownerUid;
173} gInputWindowClassInfo;
174
175static struct {
176 jclass clazz;
177
178 jfieldID name;
179 jfieldID dispatchingTimeoutNanos;
180 jfieldID token;
181} gInputApplicationClassInfo;
182
183// ----------------------------------------------------------------------------
184
185static inline nsecs_t now() {
186 return systemTime(SYSTEM_TIME_MONOTONIC);
187}
Jeff Brown7fbdc842010-06-17 20:52:56 -0700188
Jeff Brown9c3cda02010-06-15 01:31:58 -0700189// ----------------------------------------------------------------------------
190
191class NativeInputManager : public virtual RefBase,
192 public virtual InputReaderPolicyInterface,
193 public virtual InputDispatcherPolicyInterface {
194protected:
195 virtual ~NativeInputManager();
196
197public:
198 NativeInputManager(jobject callbacksObj);
199
200 inline sp<InputManager> getInputManager() const { return mInputManager; }
201
Jeff Browne33348b2010-07-15 23:54:05 -0700202 String8 dump();
203
Jeff Brown9c3cda02010-06-15 01:31:58 -0700204 void setDisplaySize(int32_t displayId, int32_t width, int32_t height);
205 void setDisplayOrientation(int32_t displayId, int32_t orientation);
206
Jeff Brown7fbdc842010-06-17 20:52:56 -0700207 status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
208 jweak inputChannelObjWeak);
209 status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
210
Jeff Brown349703e2010-06-22 01:27:15 -0700211 void setInputWindows(JNIEnv* env, jobjectArray windowObjArray);
212 void setFocusedApplication(JNIEnv* env, jobject applicationObj);
213 void setInputDispatchMode(bool enabled, bool frozen);
214 void preemptInputDispatch();
215
Jeff Brown9c3cda02010-06-15 01:31:58 -0700216 /* --- InputReaderPolicyInterface implementation --- */
217
218 virtual bool getDisplayInfo(int32_t displayId,
219 int32_t* width, int32_t* height, int32_t* orientation);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700220 virtual void virtualKeyDownFeedback();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700221 virtual int32_t interceptKey(nsecs_t when, int32_t deviceId,
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");
Jeff Brown00ba8842010-07-16 15:01:56 -0700413
414 { // acquire lock
415 AutoMutex _l(mDisplayLock);
416 dumpDispatchStateLd(dump);
417 } // release lock
Jeff Browne33348b2010-07-15 23:54:05 -0700418 return dump;
419}
420
Jeff Brown9c3cda02010-06-15 01:31:58 -0700421bool NativeInputManager::isAppSwitchKey(int32_t keyCode) {
Jeff Brownfd035822010-06-30 16:10:35 -0700422 return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700423}
424
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700425bool NativeInputManager::isPolicyKey(int32_t keyCode, bool isScreenOn) {
426 // Special keys that the WindowManagerPolicy might care about.
427 switch (keyCode) {
Jeff Brownfd035822010-06-30 16:10:35 -0700428 case AKEYCODE_VOLUME_UP:
429 case AKEYCODE_VOLUME_DOWN:
430 case AKEYCODE_ENDCALL:
431 case AKEYCODE_POWER:
432 case AKEYCODE_CALL:
433 case AKEYCODE_HOME:
434 case AKEYCODE_MENU:
435 case AKEYCODE_SEARCH:
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700436 // media keys
Jeff Brownfd035822010-06-30 16:10:35 -0700437 case AKEYCODE_HEADSETHOOK:
438 case AKEYCODE_MEDIA_PLAY_PAUSE:
439 case AKEYCODE_MEDIA_STOP:
440 case AKEYCODE_MEDIA_NEXT:
441 case AKEYCODE_MEDIA_PREVIOUS:
442 case AKEYCODE_MEDIA_REWIND:
443 case AKEYCODE_MEDIA_FAST_FORWARD:
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700444 return true;
445 default:
446 // We need to pass all keys to the policy in the following cases:
447 // - screen is off
448 // - keyguard is visible
449 // - policy is performing key chording
450 //return ! isScreenOn || keyguardVisible || chording;
451 return true; // XXX stubbed out for now
452 }
453}
454
Jeff Brown7fbdc842010-06-17 20:52:56 -0700455bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700456 if (env->ExceptionCheck()) {
457 LOGE("An exception was thrown by callback '%s'.", methodName);
458 LOGE_EX(env);
459 env->ExceptionClear();
460 return true;
461 }
462 return false;
463}
464
465void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height) {
466 if (displayId == 0) {
467 AutoMutex _l(mDisplayLock);
468
469 mDisplayWidth = width;
470 mDisplayHeight = height;
471 }
472}
473
474void NativeInputManager::setDisplayOrientation(int32_t displayId, int32_t orientation) {
475 if (displayId == 0) {
476 AutoMutex _l(mDisplayLock);
477
478 mDisplayOrientation = orientation;
479 }
480}
481
Jeff Brown7fbdc842010-06-17 20:52:56 -0700482status_t NativeInputManager::registerInputChannel(JNIEnv* env,
483 const sp<InputChannel>& inputChannel, jobject inputChannelObj) {
484 jweak inputChannelObjWeak = env->NewWeakGlobalRef(inputChannelObj);
485 if (! inputChannelObjWeak) {
486 LOGE("Could not create weak reference for input channel.");
487 LOGE_EX(env);
488 return NO_MEMORY;
489 }
490
491 status_t status;
492 {
493 AutoMutex _l(mInputChannelRegistryLock);
494
495 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
496 inputChannel->getReceivePipeFd());
497 if (index >= 0) {
498 LOGE("Input channel object '%s' has already been registered",
499 inputChannel->getName().string());
500 status = INVALID_OPERATION;
501 goto DeleteWeakRef;
502 }
503
504 mInputChannelObjWeakByReceiveFd.add(inputChannel->getReceivePipeFd(),
505 inputChannelObjWeak);
506 }
507
508 status = mInputManager->registerInputChannel(inputChannel);
509 if (! status) {
510 return OK;
511 }
512
513 {
514 AutoMutex _l(mInputChannelRegistryLock);
515 mInputChannelObjWeakByReceiveFd.removeItem(inputChannel->getReceivePipeFd());
516 }
517
518DeleteWeakRef:
519 env->DeleteWeakGlobalRef(inputChannelObjWeak);
520 return status;
521}
522
523status_t NativeInputManager::unregisterInputChannel(JNIEnv* env,
524 const sp<InputChannel>& inputChannel) {
525 jweak inputChannelObjWeak;
526 {
527 AutoMutex _l(mInputChannelRegistryLock);
528
529 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
530 inputChannel->getReceivePipeFd());
531 if (index < 0) {
532 LOGE("Input channel object '%s' is not currently registered",
533 inputChannel->getName().string());
534 return INVALID_OPERATION;
535 }
536
537 inputChannelObjWeak = mInputChannelObjWeakByReceiveFd.valueAt(index);
538 mInputChannelObjWeakByReceiveFd.removeItemsAt(index);
539 }
540
541 env->DeleteWeakGlobalRef(inputChannelObjWeak);
542
543 return mInputManager->unregisterInputChannel(inputChannel);
544}
545
546jobject NativeInputManager::getInputChannelObjLocal(JNIEnv* env,
547 const sp<InputChannel>& inputChannel) {
548 {
549 AutoMutex _l(mInputChannelRegistryLock);
550
551 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
552 inputChannel->getReceivePipeFd());
553 if (index < 0) {
554 return NULL;
555 }
556
557 jweak inputChannelObjWeak = mInputChannelObjWeakByReceiveFd.valueAt(index);
558 return env->NewLocalRef(inputChannelObjWeak);
559 }
560}
561
Jeff Brown9c3cda02010-06-15 01:31:58 -0700562bool NativeInputManager::getDisplayInfo(int32_t displayId,
563 int32_t* width, int32_t* height, int32_t* orientation) {
564 bool result = false;
565 if (displayId == 0) {
566 AutoMutex _l(mDisplayLock);
567
568 if (mDisplayWidth > 0) {
569 *width = mDisplayWidth;
570 *height = mDisplayHeight;
571 *orientation = mDisplayOrientation;
572 result = true;
573 }
574 }
575 return result;
576}
577
578bool NativeInputManager::isScreenOn() {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700579 return android_server_PowerManagerService_isScreenOn();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700580}
581
582bool NativeInputManager::isScreenBright() {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700583 return android_server_PowerManagerService_isScreenBright();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700584}
585
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700586void NativeInputManager::virtualKeyDownFeedback() {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700587#if DEBUG_INPUT_READER_POLICY
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700588 LOGD("virtualKeyDownFeedback");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700589#endif
590
591 JNIEnv* env = jniEnv();
592
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700593 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.virtualKeyDownFeedback);
594 checkAndClearExceptionFromCallback(env, "virtualKeyDownFeedback");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700595}
596
597int32_t NativeInputManager::interceptKey(nsecs_t when,
598 int32_t deviceId, bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) {
599#if DEBUG_INPUT_READER_POLICY
600 LOGD("interceptKey - when=%lld, deviceId=%d, down=%d, keyCode=%d, scanCode=%d, "
Jeff Brown349703e2010-06-22 01:27:15 -0700601 "policyFlags=0x%x",
Jeff Brown9c3cda02010-06-15 01:31:58 -0700602 when, deviceId, down, keyCode, scanCode, policyFlags);
603#endif
604
605 const int32_t WM_ACTION_PASS_TO_USER = 1;
606 const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2;
607 const int32_t WM_ACTION_GO_TO_SLEEP = 4;
608
Jeff Brown9c3cda02010-06-15 01:31:58 -0700609 bool isScreenOn = this->isScreenOn();
610 bool isScreenBright = this->isScreenBright();
611
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700612 jint wmActions = 0;
613 if (isPolicyKey(keyCode, isScreenOn)) {
614 JNIEnv* env = jniEnv();
615
616 wmActions = env->CallIntMethod(mCallbacksObj,
617 gCallbacksClassInfo.interceptKeyBeforeQueueing,
618 when, keyCode, down, policyFlags, isScreenOn);
619 if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
620 wmActions = 0;
621 }
622 } else {
623 wmActions = WM_ACTION_PASS_TO_USER;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700624 }
625
626 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
627 if (! isScreenOn) {
628 // Key presses and releases wake the device.
629 actions |= InputReaderPolicyInterface::ACTION_WOKE_HERE;
630 }
631
632 if (! isScreenBright) {
633 // Key presses and releases brighten the screen if dimmed.
634 actions |= InputReaderPolicyInterface::ACTION_BRIGHT_HERE;
635 }
636
637 if (wmActions & WM_ACTION_GO_TO_SLEEP) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700638 android_server_PowerManagerService_goToSleep(when);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700639 }
640
641 if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
Jeff Brown349703e2010-06-22 01:27:15 -0700642 pokeUserActivity(when, POWER_MANAGER_BUTTON_EVENT);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700643 }
644
645 if (wmActions & WM_ACTION_PASS_TO_USER) {
646 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700647
Jeff Brown9c3cda02010-06-15 01:31:58 -0700648 if (down && isAppSwitchKey(keyCode)) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700649 JNIEnv* env = jniEnv();
650
Jeff Brown9c3cda02010-06-15 01:31:58 -0700651 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyAppSwitchComing);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700652 checkAndClearExceptionFromCallback(env, "notifyAppSwitchComing");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700653
654 actions |= InputReaderPolicyInterface::ACTION_APP_SWITCH_COMING;
655 }
656 }
Jeff Brown349703e2010-06-22 01:27:15 -0700657
Jeff Brown9c3cda02010-06-15 01:31:58 -0700658 return actions;
659}
660
661int32_t NativeInputManager::interceptTouch(nsecs_t when) {
662#if DEBUG_INPUT_READER_POLICY
663 LOGD("interceptTouch - when=%lld", when);
664#endif
665
Jeff Brown5c225b12010-06-16 01:53:36 -0700666 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
667 if (isScreenOn()) {
668 // Only dispatch touch events when the device is awake.
Jeff Brown349703e2010-06-22 01:27:15 -0700669 // Do not wake the device.
Jeff Brown5c225b12010-06-16 01:53:36 -0700670 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700671
Jeff Brown349703e2010-06-22 01:27:15 -0700672 if (! isScreenBright()) {
673 // Brighten the screen if dimmed.
674 actions |= InputReaderPolicyInterface::ACTION_BRIGHT_HERE;
675 }
Jeff Brown5c225b12010-06-16 01:53:36 -0700676 }
677
678 return actions;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700679}
680
681int32_t NativeInputManager::interceptTrackball(nsecs_t when,
682 bool buttonChanged, bool buttonDown, bool rolled) {
683#if DEBUG_INPUT_READER_POLICY
684 LOGD("interceptTrackball - when=%lld, buttonChanged=%d, buttonDown=%d, rolled=%d",
685 when, buttonChanged, buttonDown, rolled);
686#endif
687
Jeff Brown5c225b12010-06-16 01:53:36 -0700688 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
689 if (isScreenOn()) {
690 // Only dispatch trackball events when the device is awake.
Jeff Brown349703e2010-06-22 01:27:15 -0700691 // Do not wake the device.
Jeff Brown5c225b12010-06-16 01:53:36 -0700692 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700693
Jeff Brown349703e2010-06-22 01:27:15 -0700694 if (! isScreenBright()) {
695 // Brighten the screen if dimmed.
696 actions |= InputReaderPolicyInterface::ACTION_BRIGHT_HERE;
697 }
Jeff Brown5c225b12010-06-16 01:53:36 -0700698 }
699
700 return actions;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700701}
702
703int32_t NativeInputManager::interceptSwitch(nsecs_t when, int32_t switchCode,
704 int32_t switchValue) {
705#if DEBUG_INPUT_READER_POLICY
706 LOGD("interceptSwitch - when=%lld, switchCode=%d, switchValue=%d",
707 when, switchCode, switchValue);
708#endif
709
710 JNIEnv* env = jniEnv();
711
712 switch (switchCode) {
713 case SW_LID:
714 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyLidSwitchChanged,
715 when, switchValue == 0);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700716 checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700717 break;
718 }
719
720 return InputReaderPolicyInterface::ACTION_NONE;
721}
722
723bool NativeInputManager::filterTouchEvents() {
724 if (mFilterTouchEvents < 0) {
725 JNIEnv* env = jniEnv();
726
727 jboolean result = env->CallBooleanMethod(mCallbacksObj,
728 gCallbacksClassInfo.filterTouchEvents);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700729 if (checkAndClearExceptionFromCallback(env, "filterTouchEvents")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700730 result = false;
731 }
732
733 mFilterTouchEvents = result ? 1 : 0;
734 }
735 return mFilterTouchEvents;
736}
737
738bool NativeInputManager::filterJumpyTouchEvents() {
739 if (mFilterJumpyTouchEvents < 0) {
740 JNIEnv* env = jniEnv();
741
742 jboolean result = env->CallBooleanMethod(mCallbacksObj,
743 gCallbacksClassInfo.filterJumpyTouchEvents);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700744 if (checkAndClearExceptionFromCallback(env, "filterJumpyTouchEvents")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700745 result = false;
746 }
747
748 mFilterJumpyTouchEvents = result ? 1 : 0;
749 }
750 return mFilterJumpyTouchEvents;
751}
752
753void NativeInputManager::getVirtualKeyDefinitions(const String8& deviceName,
754 Vector<InputReaderPolicyInterface::VirtualKeyDefinition>& outVirtualKeyDefinitions) {
755 JNIEnv* env = jniEnv();
756
757 jstring deviceNameStr = env->NewStringUTF(deviceName.string());
Jeff Brown7fbdc842010-06-17 20:52:56 -0700758 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700759 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
760 gCallbacksClassInfo.getVirtualKeyDefinitions, deviceNameStr));
Jeff Brown7fbdc842010-06-17 20:52:56 -0700761 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions") && result) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700762 jsize length = env->GetArrayLength(result);
763 for (jsize i = 0; i < length; i++) {
764 jobject item = env->GetObjectArrayElement(result, i);
765
766 outVirtualKeyDefinitions.add();
767 outVirtualKeyDefinitions.editTop().scanCode =
768 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.scanCode));
769 outVirtualKeyDefinitions.editTop().centerX =
770 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerX));
771 outVirtualKeyDefinitions.editTop().centerY =
772 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerY));
773 outVirtualKeyDefinitions.editTop().width =
774 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.width));
775 outVirtualKeyDefinitions.editTop().height =
776 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.height));
777
778 env->DeleteLocalRef(item);
779 }
780 env->DeleteLocalRef(result);
781 }
782 env->DeleteLocalRef(deviceNameStr);
783 }
784}
785
786void NativeInputManager::getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
787 JNIEnv* env = jniEnv();
788
789 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
790 gCallbacksClassInfo.getExcludedDeviceNames));
Jeff Brown7fbdc842010-06-17 20:52:56 -0700791 if (! checkAndClearExceptionFromCallback(env, "getExcludedDeviceNames") && result) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700792 jsize length = env->GetArrayLength(result);
793 for (jsize i = 0; i < length; i++) {
794 jstring item = jstring(env->GetObjectArrayElement(result, i));
795
796 const char* deviceNameChars = env->GetStringUTFChars(item, NULL);
797 outExcludedDeviceNames.add(String8(deviceNameChars));
798 env->ReleaseStringUTFChars(item, deviceNameChars);
799
800 env->DeleteLocalRef(item);
801 }
802 env->DeleteLocalRef(result);
803 }
804}
805
806void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
807#if DEBUG_INPUT_DISPATCHER_POLICY
808 LOGD("notifyConfigurationChanged - when=%lld", when);
809#endif
810
811 JNIEnv* env = jniEnv();
812
813 InputConfiguration config;
814 mInputManager->getInputConfiguration(& config);
815
816 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyConfigurationChanged,
817 when, config.touchScreen, config.keyboard, config.navigation);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700818 checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700819}
820
821void NativeInputManager::notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
822#if DEBUG_INPUT_DISPATCHER_POLICY
823 LOGD("notifyInputChannelBroken - inputChannel='%s'", inputChannel->getName().string());
824#endif
825
Jeff Brown7fbdc842010-06-17 20:52:56 -0700826 JNIEnv* env = jniEnv();
827
828 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
829 if (inputChannelObjLocal) {
830 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelBroken,
831 inputChannelObjLocal);
832 checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken");
833
834 env->DeleteLocalRef(inputChannelObjLocal);
835 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700836}
837
Jeff Brown7fbdc842010-06-17 20:52:56 -0700838bool NativeInputManager::notifyInputChannelANR(const sp<InputChannel>& inputChannel,
839 nsecs_t& outNewTimeout) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700840#if DEBUG_INPUT_DISPATCHER_POLICY
841 LOGD("notifyInputChannelANR - inputChannel='%s'",
842 inputChannel->getName().string());
843#endif
844
Jeff Brown7fbdc842010-06-17 20:52:56 -0700845 JNIEnv* env = jniEnv();
846
847 jlong newTimeout;
848 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
849 if (inputChannelObjLocal) {
850 newTimeout = env->CallLongMethod(mCallbacksObj,
851 gCallbacksClassInfo.notifyInputChannelANR, inputChannelObjLocal);
852 if (checkAndClearExceptionFromCallback(env, "notifyInputChannelANR")) {
853 newTimeout = -2;
854 }
855
856 env->DeleteLocalRef(inputChannelObjLocal);
857 } else {
858 newTimeout = -2;
859 }
860
861 if (newTimeout == -2) {
862 return false; // abort
863 }
864
865 outNewTimeout = newTimeout;
866 return true; // resume
Jeff Brown9c3cda02010-06-15 01:31:58 -0700867}
868
869void NativeInputManager::notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel) {
870#if DEBUG_INPUT_DISPATCHER_POLICY
871 LOGD("notifyInputChannelRecoveredFromANR - inputChannel='%s'",
872 inputChannel->getName().string());
873#endif
874
Jeff Brown7fbdc842010-06-17 20:52:56 -0700875 JNIEnv* env = jniEnv();
876
877 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
878 if (inputChannelObjLocal) {
879 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelRecoveredFromANR,
880 inputChannelObjLocal);
881 checkAndClearExceptionFromCallback(env, "notifyInputChannelRecoveredFromANR");
882
883 env->DeleteLocalRef(inputChannelObjLocal);
884 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700885}
886
Jeff Brown349703e2010-06-22 01:27:15 -0700887bool NativeInputManager::notifyANR(jobject tokenObj, nsecs_t& outNewTimeout) {
888#if DEBUG_INPUT_DISPATCHER_POLICY
889 LOGD("notifyANR");
890#endif
891
892 JNIEnv* env = jniEnv();
893
894 jlong newTimeout = env->CallLongMethod(mCallbacksObj,
895 gCallbacksClassInfo.notifyANR, tokenObj);
896 if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
897 newTimeout = -2;
898 }
899
900 if (newTimeout == -2) {
901 return false; // abort
902 }
903
904 outNewTimeout = newTimeout;
905 return true; // resume
906}
907
Jeff Brown9c3cda02010-06-15 01:31:58 -0700908nsecs_t NativeInputManager::getKeyRepeatTimeout() {
909 if (! isScreenOn()) {
910 // Disable key repeat when the screen is off.
911 return -1;
912 } else {
913 // TODO use ViewConfiguration.getLongPressTimeout()
914 return milliseconds_to_nanoseconds(500);
915 }
916}
917
Jeff Brown349703e2010-06-22 01:27:15 -0700918void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArray) {
919#if DEBUG_FOCUS
920 LOGD("setInputWindows");
921#endif
922 { // acquire lock
923 AutoMutex _l(mDispatchLock);
924
925 sp<InputChannel> touchedWindowChannel;
926 if (mTouchedWindow) {
927 touchedWindowChannel = mTouchedWindow->inputChannel;
928 mTouchedWindow = NULL;
929 }
930 size_t numTouchedWallpapers = mTouchedWallpaperWindows.size();
931 if (numTouchedWallpapers != 0) {
932 for (size_t i = 0; i < numTouchedWallpapers; i++) {
933 mTempTouchedWallpaperChannels.push(mTouchedWallpaperWindows[i]->inputChannel);
934 }
935 mTouchedWallpaperWindows.clear();
936 }
937
Jeff Browne33348b2010-07-15 23:54:05 -0700938 bool hadFocusedWindow = mFocusedWindow != NULL;
939
Jeff Brown349703e2010-06-22 01:27:15 -0700940 mWindows.clear();
941 mFocusedWindow = NULL;
942 mWallpaperWindows.clear();
943
944 if (windowObjArray) {
945 mWindowsReady = true;
946
947 jsize length = env->GetArrayLength(windowObjArray);
948 for (jsize i = 0; i < length; i++) {
949 jobject inputTargetObj = env->GetObjectArrayElement(windowObjArray, i);
950 if (! inputTargetObj) {
951 break; // found null element indicating end of used portion of the array
952 }
953
954 mWindows.push();
955 InputWindow& window = mWindows.editTop();
956 bool valid = populateWindow(env, inputTargetObj, window);
957 if (! valid) {
958 mWindows.pop();
959 }
960
961 env->DeleteLocalRef(inputTargetObj);
962 }
963
964 size_t numWindows = mWindows.size();
965 for (size_t i = 0; i < numWindows; i++) {
966 InputWindow* window = & mWindows.editItemAt(i);
967 if (window->hasFocus) {
968 mFocusedWindow = window;
969 }
970
971 if (window->layoutParamsType == TYPE_WALLPAPER) {
972 mWallpaperWindows.push(window);
973
974 for (size_t j = 0; j < numTouchedWallpapers; j++) {
975 if (window->inputChannel == mTempTouchedWallpaperChannels[i]) {
976 mTouchedWallpaperWindows.push(window);
977 }
978 }
979 }
980
981 if (window->inputChannel == touchedWindowChannel) {
982 mTouchedWindow = window;
983 }
984 }
985 } else {
986 mWindowsReady = false;
987 }
988
989 mTempTouchedWallpaperChannels.clear();
990
Jeff Brown00ba8842010-07-16 15:01:56 -0700991 if ((hadFocusedWindow && ! mFocusedWindow)
992 || (mFocusedWindow && ! mFocusedWindow->visible)) {
Jeff Browne33348b2010-07-15 23:54:05 -0700993 preemptInputDispatch();
994 }
995
Jeff Brown349703e2010-06-22 01:27:15 -0700996 mDispatchStateChanged.broadcast();
997
998#if DEBUG_FOCUS
Jeff Browne33348b2010-07-15 23:54:05 -0700999 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001000#endif
1001 } // release lock
1002}
1003
1004bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj,
1005 InputWindow& outWindow) {
1006 bool valid = false;
1007
1008 jobject inputChannelObj = env->GetObjectField(windowObj,
1009 gInputWindowClassInfo.inputChannel);
1010 if (inputChannelObj) {
1011 sp<InputChannel> inputChannel =
1012 android_view_InputChannel_getInputChannel(env, inputChannelObj);
1013 if (inputChannel != NULL) {
1014 jint layoutParamsFlags = env->GetIntField(windowObj,
1015 gInputWindowClassInfo.layoutParamsFlags);
1016 jint layoutParamsType = env->GetIntField(windowObj,
1017 gInputWindowClassInfo.layoutParamsType);
1018 jlong dispatchingTimeoutNanos = env->GetLongField(windowObj,
1019 gInputWindowClassInfo.dispatchingTimeoutNanos);
1020 jint frameLeft = env->GetIntField(windowObj,
1021 gInputWindowClassInfo.frameLeft);
1022 jint frameTop = env->GetIntField(windowObj,
1023 gInputWindowClassInfo.frameTop);
1024 jint touchableAreaLeft = env->GetIntField(windowObj,
1025 gInputWindowClassInfo.touchableAreaLeft);
1026 jint touchableAreaTop = env->GetIntField(windowObj,
1027 gInputWindowClassInfo.touchableAreaTop);
1028 jint touchableAreaRight = env->GetIntField(windowObj,
1029 gInputWindowClassInfo.touchableAreaRight);
1030 jint touchableAreaBottom = env->GetIntField(windowObj,
1031 gInputWindowClassInfo.touchableAreaBottom);
1032 jboolean visible = env->GetBooleanField(windowObj,
1033 gInputWindowClassInfo.visible);
1034 jboolean hasFocus = env->GetBooleanField(windowObj,
1035 gInputWindowClassInfo.hasFocus);
1036 jboolean hasWallpaper = env->GetBooleanField(windowObj,
1037 gInputWindowClassInfo.hasWallpaper);
1038 jboolean paused = env->GetBooleanField(windowObj,
1039 gInputWindowClassInfo.paused);
1040 jint ownerPid = env->GetIntField(windowObj,
1041 gInputWindowClassInfo.ownerPid);
1042 jint ownerUid = env->GetIntField(windowObj,
1043 gInputWindowClassInfo.ownerUid);
1044
1045 outWindow.inputChannel = inputChannel;
1046 outWindow.layoutParamsFlags = layoutParamsFlags;
1047 outWindow.layoutParamsType = layoutParamsType;
1048 outWindow.dispatchingTimeout = dispatchingTimeoutNanos;
1049 outWindow.frameLeft = frameLeft;
1050 outWindow.frameTop = frameTop;
1051 outWindow.touchableAreaLeft = touchableAreaLeft;
1052 outWindow.touchableAreaTop = touchableAreaTop;
1053 outWindow.touchableAreaRight = touchableAreaRight;
1054 outWindow.touchableAreaBottom = touchableAreaBottom;
1055 outWindow.visible = visible;
1056 outWindow.hasFocus = hasFocus;
1057 outWindow.hasWallpaper = hasWallpaper;
1058 outWindow.paused = paused;
1059 outWindow.ownerPid = ownerPid;
1060 outWindow.ownerUid = ownerUid;
1061 valid = true;
1062 } else {
1063 LOGW("Dropping input target because its input channel is not initialized.");
1064 }
1065
1066 env->DeleteLocalRef(inputChannelObj);
1067 } else {
1068 LOGW("Dropping input target because the input channel object was null.");
1069 }
1070 return valid;
1071}
1072
1073void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) {
1074#if DEBUG_FOCUS
1075 LOGD("setFocusedApplication");
1076#endif
1077 { // acquire lock
1078 AutoMutex _l(mDispatchLock);
1079
1080 releaseFocusedApplicationLd(env);
1081
1082 if (applicationObj) {
1083 jstring nameObj = jstring(env->GetObjectField(applicationObj,
1084 gInputApplicationClassInfo.name));
1085 jlong dispatchingTimeoutNanos = env->GetLongField(applicationObj,
1086 gInputApplicationClassInfo.dispatchingTimeoutNanos);
1087 jobject tokenObj = env->GetObjectField(applicationObj,
1088 gInputApplicationClassInfo.token);
1089 jweak tokenObjWeak = env->NewWeakGlobalRef(tokenObj);
1090 if (! tokenObjWeak) {
1091 LOGE("Could not create weak reference for application token.");
1092 LOGE_EX(env);
1093 env->ExceptionClear();
1094 }
1095 env->DeleteLocalRef(tokenObj);
1096
1097 mFocusedApplication = & mFocusedApplicationStorage;
1098
1099 if (nameObj) {
1100 const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
1101 mFocusedApplication->name.setTo(nameStr);
1102 env->ReleaseStringUTFChars(nameObj, nameStr);
1103 env->DeleteLocalRef(nameObj);
1104 } else {
1105 LOGE("InputApplication.name should not be null.");
1106 mFocusedApplication->name.setTo("unknown");
1107 }
1108
1109 mFocusedApplication->dispatchingTimeout = dispatchingTimeoutNanos;
1110 mFocusedApplication->tokenObjWeak = tokenObjWeak;
1111 }
1112
1113 mDispatchStateChanged.broadcast();
1114
1115#if DEBUG_FOCUS
Jeff Browne33348b2010-07-15 23:54:05 -07001116 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001117#endif
1118 } // release lock
1119}
1120
1121void NativeInputManager::releaseFocusedApplicationLd(JNIEnv* env) {
1122 if (mFocusedApplication) {
1123 env->DeleteWeakGlobalRef(mFocusedApplication->tokenObjWeak);
1124 mFocusedApplication = NULL;
1125 }
1126}
1127
1128void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
1129#if DEBUG_FOCUS
1130 LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001131#endif
1132
Jeff Brown349703e2010-06-22 01:27:15 -07001133 { // acquire lock
1134 AutoMutex _l(mDispatchLock);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001135
Jeff Brown349703e2010-06-22 01:27:15 -07001136 if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
1137 mDispatchEnabled = enabled;
1138 mDispatchFrozen = frozen;
1139
1140 mDispatchStateChanged.broadcast();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001141 }
Jeff Brown349703e2010-06-22 01:27:15 -07001142
1143#if DEBUG_FOCUS
Jeff Browne33348b2010-07-15 23:54:05 -07001144 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001145#endif
1146 } // release lock
1147}
1148
1149void NativeInputManager::preemptInputDispatch() {
1150#if DEBUG_FOCUS
1151 LOGD("preemptInputDispatch");
1152#endif
1153
1154 mInputManager->preemptInputDispatch();
1155}
1156
1157int32_t NativeInputManager::waitForFocusedWindowLd(uint32_t policyFlags,
1158 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
1159 InputWindow*& outFocusedWindow) {
1160
1161 int32_t injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1162 bool firstIteration = true;
1163 ANRTimer anrTimer;
1164 for (;;) {
1165 if (firstIteration) {
1166 firstIteration = false;
1167 } else {
1168 if (! anrTimer.waitForDispatchStateChangeLd(this)) {
1169 LOGW("Dropping event because the dispatcher timed out waiting to identify "
1170 "the window that should receive it.");
1171 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1172 break;
1173 }
1174 }
1175
1176 // If dispatch is not enabled then fail.
1177 if (! mDispatchEnabled) {
1178 LOGI("Dropping event because input dispatch is disabled.");
1179 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1180 break;
1181 }
1182
1183 // If dispatch is frozen or we don't have valid window data yet then wait.
1184 if (mDispatchFrozen || ! mWindowsReady) {
1185#if DEBUG_FOCUS
1186 LOGD("Waiting because dispatch is frozen or windows are not ready.");
1187#endif
1188 anrTimer.dispatchFrozenBySystem();
1189 continue;
1190 }
1191
1192 // If there is no currently focused window and no focused application
1193 // then drop the event.
1194 if (! mFocusedWindow) {
1195 if (mFocusedApplication) {
1196#if DEBUG_FOCUS
1197 LOGD("Waiting because there is no focused window but there is a "
1198 "focused application that may yet introduce a new target: '%s'.",
1199 mFocusedApplication->name.string());
1200#endif
1201 continue;
1202 }
1203
1204 LOGI("Dropping event because there is no focused window or focused application.");
1205 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1206 break;
1207 }
1208
1209 // Check permissions.
1210 if (! checkInjectionPermission(mFocusedWindow, injectorPid, injectorUid)) {
1211 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1212 break;
1213 }
1214
1215 // If the currently focused window is paused then keep waiting.
1216 if (mFocusedWindow->paused) {
1217#if DEBUG_FOCUS
1218 LOGD("Waiting because focused window is paused.");
1219#endif
1220 anrTimer.dispatchPausedByApplication(mFocusedWindow);
1221 continue;
1222 }
1223
1224 // Success!
1225 break; // done waiting, exit loop
Jeff Brown9c3cda02010-06-15 01:31:58 -07001226 }
Jeff Brown349703e2010-06-22 01:27:15 -07001227
1228 // Output targets.
1229 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
1230 addTarget(mFocusedWindow, InputTarget::FLAG_SYNC,
1231 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
1232
1233 outFocusedWindow = mFocusedWindow;
1234 } else {
1235 outFocusedWindow = NULL;
1236 }
1237
1238#if DEBUG_FOCUS
1239 LOGD("waitForFocusedWindow finished: injectionResult=%d",
1240 injectionResult);
Jeff Browne33348b2010-07-15 23:54:05 -07001241 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001242#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001243 return injectionResult;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001244}
1245
Jeff Brownc5ed5912010-07-14 18:48:53 -07001246enum InjectionPermission {
1247 INJECTION_PERMISSION_UNKNOWN,
1248 INJECTION_PERMISSION_GRANTED,
1249 INJECTION_PERMISSION_DENIED
1250};
1251
Jeff Brown349703e2010-06-22 01:27:15 -07001252int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
1253 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
1254 InputWindow*& outTouchedWindow) {
1255 nsecs_t startTime = now();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001256
Jeff Brown349703e2010-06-22 01:27:15 -07001257 // For security reasons, we defer updating the touch state until we are sure that
1258 // event injection will be allowed.
1259 //
1260 // FIXME In the original code, screenWasOff could never be set to true.
1261 // The reason is that the POLICY_FLAG_WOKE_HERE
1262 // and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
1263 // EV_KEY, EV_REL and EV_ABS events. As it happens, the touch event was
1264 // actually enqueued using the policyFlags that appeared in the final EV_SYN
1265 // events upon which no preprocessing took place. So policyFlags was always 0.
1266 // In the new native input dispatcher we're a bit more careful about event
1267 // preprocessing so the touches we receive can actually have non-zero policyFlags.
1268 // Unfortunately we obtain undesirable behavior.
1269 //
1270 // Here's what happens:
1271 //
1272 // When the device dims in anticipation of going to sleep, touches
1273 // in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
1274 // the device to brighten and reset the user activity timer.
1275 // Touches on other windows (such as the launcher window)
1276 // are dropped. Then after a moment, the device goes to sleep. Oops.
1277 //
1278 // Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
1279 // instead of POLICY_FLAG_WOKE_HERE...
1280 //
1281 bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001282
1283 int32_t action = motionEvent->getAction();
1284
Jeff Brown349703e2010-06-22 01:27:15 -07001285 bool firstIteration = true;
1286 ANRTimer anrTimer;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001287 int32_t injectionResult;
1288 InjectionPermission injectionPermission;
Jeff Brown349703e2010-06-22 01:27:15 -07001289 for (;;) {
1290 if (firstIteration) {
1291 firstIteration = false;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001292 } else {
Jeff Brown349703e2010-06-22 01:27:15 -07001293 if (! anrTimer.waitForDispatchStateChangeLd(this)) {
1294 LOGW("Dropping event because the dispatcher timed out waiting to identify "
1295 "the window that should receive it.");
1296 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001297 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
1298 break; // timed out, exit wait loop
Jeff Brown349703e2010-06-22 01:27:15 -07001299 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001300 }
Jeff Brown349703e2010-06-22 01:27:15 -07001301
1302 // If dispatch is not enabled then fail.
1303 if (! mDispatchEnabled) {
1304 LOGI("Dropping event because input dispatch is disabled.");
1305 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001306 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
Jeff Brown349703e2010-06-22 01:27:15 -07001307 break; // failed, exit wait loop
1308 }
1309
1310 // If dispatch is frozen or we don't have valid window data yet then wait.
1311 if (mDispatchFrozen || ! mWindowsReady) {
1312#if DEBUG_INPUT_DISPATCHER_POLICY
1313 LOGD("Waiting because dispatch is frozen or windows are not ready.");
1314#endif
1315 anrTimer.dispatchFrozenBySystem();
1316 continue;
1317 }
1318
1319 // Update the touch state as needed based on the properties of the touch event.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001320 if (action == AMOTION_EVENT_ACTION_DOWN) {
1321 /* Case 1: ACTION_DOWN */
1322
Jeff Brown349703e2010-06-22 01:27:15 -07001323 InputWindow* newTouchedWindow = NULL;
1324 mTempTouchedOutsideWindows.clear();
1325
1326 int32_t x = int32_t(motionEvent->getX(0));
1327 int32_t y = int32_t(motionEvent->getY(0));
1328 InputWindow* topErrorWindow = NULL;
1329
1330 // Traverse windows from front to back to find touched window and outside targets.
1331 size_t numWindows = mWindows.size();
1332 for (size_t i = 0; i < numWindows; i++) {
1333 InputWindow* window = & mWindows.editItemAt(i);
1334 int32_t flags = window->layoutParamsFlags;
1335
1336 if (flags & FLAG_SYSTEM_ERROR) {
1337 if (! topErrorWindow) {
1338 topErrorWindow = window;
1339 }
1340 }
1341
1342 if (window->visible) {
1343 if (! (flags & FLAG_NOT_TOUCHABLE)) {
1344 bool isTouchModal = (flags &
1345 (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL)) == 0;
1346 if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
1347 if (! screenWasOff || flags & FLAG_TOUCHABLE_WHEN_WAKING) {
1348 newTouchedWindow = window;
1349 }
1350 break; // found touched window, exit window loop
1351 }
1352 }
1353
1354 if (flags & FLAG_WATCH_OUTSIDE_TOUCH) {
1355 mTempTouchedOutsideWindows.push(window);
1356 }
1357 }
1358 }
1359
1360 // If there is an error window but it is not taking focus (typically because
1361 // it is invisible) then wait for it. Any other focused window may in
1362 // fact be in ANR state.
1363 if (topErrorWindow && newTouchedWindow != topErrorWindow) {
1364#if DEBUG_INPUT_DISPATCHER_POLICY
1365 LOGD("Waiting because system error window is pending.");
1366#endif
1367 anrTimer.dispatchFrozenBySystem();
1368 continue; // wait some more
1369 }
1370
1371 // If we did not find a touched window then fail.
1372 if (! newTouchedWindow) {
1373 if (mFocusedApplication) {
1374#if DEBUG_FOCUS
1375 LOGD("Waiting because there is no focused window but there is a "
1376 "focused application that may yet introduce a new target: '%s'.",
1377 mFocusedApplication->name.string());
1378#endif
1379 continue;
1380 }
1381
1382 LOGI("Dropping event because there is no touched window or focused application.");
1383 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001384 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
Jeff Brown349703e2010-06-22 01:27:15 -07001385 break; // failed, exit wait loop
1386 }
1387
1388 // Check permissions.
1389 if (! checkInjectionPermission(newTouchedWindow, injectorPid, injectorUid)) {
1390 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001391 injectionPermission = INJECTION_PERMISSION_DENIED;
Jeff Brown349703e2010-06-22 01:27:15 -07001392 break; // failed, exit wait loop
1393 }
1394
1395 // If the touched window is paused then keep waiting.
1396 if (newTouchedWindow->paused) {
1397#if DEBUG_INPUT_DISPATCHER_POLICY
1398 LOGD("Waiting because touched window is paused.");
1399#endif
1400 anrTimer.dispatchPausedByApplication(newTouchedWindow);
1401 continue; // wait some more
1402 }
1403
1404 // Success! Update the touch dispatch state for real.
1405 releaseTouchedWindowLd();
1406
1407 mTouchedWindow = newTouchedWindow;
1408
1409 if (newTouchedWindow->hasWallpaper) {
1410 mTouchedWallpaperWindows.appendVector(mWallpaperWindows);
1411 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001412
1413 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1414 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001415 break; // done
1416 } else {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001417 /* Case 2: Everything but ACTION_DOWN */
1418
Jeff Brown349703e2010-06-22 01:27:15 -07001419 // Check permissions.
1420 if (! checkInjectionPermission(mTouchedWindow, injectorPid, injectorUid)) {
1421 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001422 injectionPermission = INJECTION_PERMISSION_DENIED;
1423 break; // failed, exit wait loop
1424 }
1425
1426 // If the pointer is not currently down, then ignore the event.
1427 if (! mTouchDown) {
1428 LOGI("Dropping event because the pointer is not down.");
1429 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1430 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001431 break; // failed, exit wait loop
1432 }
1433
1434 // If there is no currently touched window then fail.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001435 if (! mTouchedWindow) {
1436 LOGW("Dropping event because there is no touched window to receive it.");
Jeff Brown349703e2010-06-22 01:27:15 -07001437 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001438 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001439 break; // failed, exit wait loop
1440 }
1441
1442 // If the touched window is paused then keep waiting.
1443 if (mTouchedWindow->paused) {
1444#if DEBUG_INPUT_DISPATCHER_POLICY
1445 LOGD("Waiting because touched window is paused.");
1446#endif
1447 anrTimer.dispatchPausedByApplication(mTouchedWindow);
1448 continue; // wait some more
1449 }
1450
1451 // Success!
Jeff Brownc5ed5912010-07-14 18:48:53 -07001452 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1453 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001454 break; // done
1455 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001456 }
Jeff Brown349703e2010-06-22 01:27:15 -07001457
1458 // Output targets.
Jeff Brown349703e2010-06-22 01:27:15 -07001459 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
Jeff Brown349703e2010-06-22 01:27:15 -07001460 size_t numWallpaperWindows = mTouchedWallpaperWindows.size();
1461 for (size_t i = 0; i < numWallpaperWindows; i++) {
1462 addTarget(mTouchedWallpaperWindows[i], 0, 0, outTargets);
1463 }
1464
1465 size_t numOutsideWindows = mTempTouchedOutsideWindows.size();
1466 for (size_t i = 0; i < numOutsideWindows; i++) {
1467 addTarget(mTempTouchedOutsideWindows[i], InputTarget::FLAG_OUTSIDE, 0, outTargets);
1468 }
1469
1470 addTarget(mTouchedWindow, InputTarget::FLAG_SYNC,
1471 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
1472 outTouchedWindow = mTouchedWindow;
1473 } else {
Jeff Brown349703e2010-06-22 01:27:15 -07001474 outTouchedWindow = NULL;
1475 }
1476 mTempTouchedOutsideWindows.clear();
1477
Jeff Brownc5ed5912010-07-14 18:48:53 -07001478 // Check injection permission once and for all.
1479 if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
1480 if (checkInjectionPermission(action == AMOTION_EVENT_ACTION_DOWN ? NULL : mTouchedWindow,
1481 injectorPid, injectorUid)) {
1482 injectionPermission = INJECTION_PERMISSION_GRANTED;
1483 } else {
1484 injectionPermission = INJECTION_PERMISSION_DENIED;
1485 }
1486 }
1487
1488 // Update final pieces of touch state if the injector had permission.
1489 if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
1490 if (action == AMOTION_EVENT_ACTION_DOWN) {
Jeff Brown349703e2010-06-22 01:27:15 -07001491 if (mTouchDown) {
1492 // This is weird. We got a down but we thought it was already down!
1493 LOGW("Pointer down received while already down.");
1494 } else {
1495 mTouchDown = true;
1496 }
1497
1498 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1499 // Since we failed to identify a target for this touch down, we may still
1500 // be holding on to an earlier target from a previous touch down. Release it.
1501 releaseTouchedWindowLd();
1502 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001503 } else if (action == AMOTION_EVENT_ACTION_UP) {
Jeff Brown349703e2010-06-22 01:27:15 -07001504 mTouchDown = false;
1505 releaseTouchedWindowLd();
1506 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001507 } else {
1508 LOGW("Not updating touch focus because injection was denied.");
Jeff Brown349703e2010-06-22 01:27:15 -07001509 }
1510
1511#if DEBUG_FOCUS
1512 LOGD("waitForTouchedWindow finished: injectionResult=%d",
1513 injectionResult);
Jeff Browne33348b2010-07-15 23:54:05 -07001514 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001515#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001516 return injectionResult;
1517}
1518
Jeff Brown349703e2010-06-22 01:27:15 -07001519void NativeInputManager::releaseTouchedWindowLd() {
1520 mTouchedWindow = NULL;
1521 mTouchedWallpaperWindows.clear();
1522}
1523
1524void NativeInputManager::addTarget(const InputWindow* window, int32_t targetFlags,
1525 nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets) {
1526 nsecs_t timeout = window->dispatchingTimeout - timeSpentWaitingForApplication;
1527 if (timeout < MIN_INPUT_DISPATCHING_TIMEOUT) {
1528 timeout = MIN_INPUT_DISPATCHING_TIMEOUT;
1529 }
1530
1531 outTargets.push();
1532
1533 InputTarget& target = outTargets.editTop();
1534 target.inputChannel = window->inputChannel;
1535 target.flags = targetFlags;
1536 target.timeout = timeout;
1537 target.xOffset = - window->frameLeft;
1538 target.yOffset = - window->frameTop;
1539}
1540
1541bool NativeInputManager::checkInjectionPermission(const InputWindow* window,
1542 int32_t injectorPid, int32_t injectorUid) {
1543 if (injectorUid > 0 && (window == NULL || window->ownerUid != injectorUid)) {
1544 JNIEnv* env = jniEnv();
1545 jboolean result = env->CallBooleanMethod(mCallbacksObj,
1546 gCallbacksClassInfo.checkInjectEventsPermission, injectorPid, injectorUid);
1547 checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission");
1548
1549 if (! result) {
1550 if (window) {
1551 LOGW("Permission denied: injecting event from pid %d uid %d to window "
1552 "with input channel %s owned by uid %d",
1553 injectorPid, injectorUid, window->inputChannel->getName().string(),
1554 window->ownerUid);
1555 } else {
1556 LOGW("Permission denied: injecting event from pid %d uid %d",
1557 injectorPid, injectorUid);
1558 }
1559 return false;
1560 }
1561 }
1562
1563 return true;
1564}
1565
1566int32_t NativeInputManager::waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
1567 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets) {
1568#if DEBUG_INPUT_DISPATCHER_POLICY
1569 LOGD("waitForKeyEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1570 policyFlags, injectorPid, injectorUid);
1571#endif
1572
1573 int32_t windowType;
1574 { // acquire lock
1575 AutoMutex _l(mDispatchLock);
1576
1577 InputWindow* focusedWindow;
1578 int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
1579 injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
1580 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1581 return injectionResult;
1582 }
1583
1584 windowType = focusedWindow->layoutParamsType;
1585 } // release lock
1586
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001587 if (isPolicyKey(keyEvent->getKeyCode(), isScreenOn())) {
1588 const InputTarget& target = outTargets.top();
1589 bool consumed = interceptKeyBeforeDispatching(target, keyEvent, policyFlags);
1590 if (consumed) {
1591 outTargets.clear();
1592 return INPUT_EVENT_INJECTION_SUCCEEDED;
1593 }
Jeff Brown349703e2010-06-22 01:27:15 -07001594 }
1595
1596 pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
1597 return INPUT_EVENT_INJECTION_SUCCEEDED;
1598}
1599
1600int32_t NativeInputManager::waitForMotionEventTargets(MotionEvent* motionEvent,
1601 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001602 Vector<InputTarget>& outTargets) {
Jeff Brown349703e2010-06-22 01:27:15 -07001603#if DEBUG_INPUT_DISPATCHER_POLICY
1604 LOGD("waitForMotionEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1605 policyFlags, injectorPid, injectorUid);
1606#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001607
Jeff Brownc5ed5912010-07-14 18:48:53 -07001608 int32_t source = motionEvent->getSource();
1609 if (source & AINPUT_SOURCE_CLASS_POINTER) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001610 return waitForTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
Jeff Brown349703e2010-06-22 01:27:15 -07001611 outTargets);
Jeff Brownc5ed5912010-07-14 18:48:53 -07001612 } else {
1613 return waitForNonTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
1614 outTargets);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001615 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001616}
1617
Jeff Brownc5ed5912010-07-14 18:48:53 -07001618int32_t NativeInputManager::waitForNonTouchEventTargets(MotionEvent* motionEvent,
Jeff Brown349703e2010-06-22 01:27:15 -07001619 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
1620 Vector<InputTarget>& outTargets) {
1621#if DEBUG_INPUT_DISPATCHER_POLICY
Jeff Brownc5ed5912010-07-14 18:48:53 -07001622 LOGD("waitForNonTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
Jeff Brown349703e2010-06-22 01:27:15 -07001623 policyFlags, injectorPid, injectorUid);
1624#endif
1625
1626 int32_t windowType;
1627 { // acquire lock
1628 AutoMutex _l(mDispatchLock);
1629
1630 InputWindow* focusedWindow;
1631 int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
1632 injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
1633 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1634 return injectionResult;
1635 }
1636
1637 windowType = focusedWindow->layoutParamsType;
1638 } // release lock
1639
1640 pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
1641 return INPUT_EVENT_INJECTION_SUCCEEDED;
1642}
1643
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001644int32_t NativeInputManager::waitForTouchEventTargets(MotionEvent* motionEvent,
Jeff Brown349703e2010-06-22 01:27:15 -07001645 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
1646 Vector<InputTarget>& outTargets) {
1647#if DEBUG_INPUT_DISPATCHER_POLICY
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001648 LOGD("waitForTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
Jeff Brown349703e2010-06-22 01:27:15 -07001649 policyFlags, injectorPid, injectorUid);
1650#endif
1651
1652 int32_t windowType;
1653 { // acquire lock
1654 AutoMutex _l(mDispatchLock);
1655
1656 InputWindow* touchedWindow;
1657 int32_t injectionResult = waitForTouchedWindowLd(motionEvent, policyFlags,
1658 injectorPid, injectorUid, outTargets, /*out*/ touchedWindow);
1659 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1660 return injectionResult;
1661 }
1662
1663 windowType = touchedWindow->layoutParamsType;
1664 } // release lock
1665
1666 int32_t eventType;
1667 switch (motionEvent->getAction()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001668 case AMOTION_EVENT_ACTION_DOWN:
Jeff Brown349703e2010-06-22 01:27:15 -07001669 eventType = POWER_MANAGER_TOUCH_EVENT;
1670 break;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001671 case AMOTION_EVENT_ACTION_UP:
Jeff Brown349703e2010-06-22 01:27:15 -07001672 eventType = POWER_MANAGER_TOUCH_UP_EVENT;
1673 break;
1674 default:
1675 if (motionEvent->getEventTime() - motionEvent->getDownTime()
1676 >= EVENT_IGNORE_DURATION) {
1677 eventType = POWER_MANAGER_TOUCH_EVENT;
1678 } else {
1679 eventType = POWER_MANAGER_LONG_TOUCH_EVENT;
1680 }
1681 break;
1682 }
1683 pokeUserActivityIfNeeded(windowType, eventType);
1684 return INPUT_EVENT_INJECTION_SUCCEEDED;
1685}
1686
Jeff Brownd0097872010-06-30 14:41:59 -07001687bool NativeInputManager::interceptKeyBeforeDispatching(const InputTarget& target,
1688 const KeyEvent* keyEvent, uint32_t policyFlags) {
1689 JNIEnv* env = jniEnv();
1690
1691 jobject inputChannelObj = getInputChannelObjLocal(env, target.inputChannel);
1692 if (inputChannelObj) {
1693 jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
1694 gCallbacksClassInfo.interceptKeyBeforeDispatching,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001695 inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(),
1696 keyEvent->getKeyCode(), keyEvent->getMetaState(),
Jeff Brownd0097872010-06-30 14:41:59 -07001697 keyEvent->getRepeatCount(), policyFlags);
1698 bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
1699
1700 env->DeleteLocalRef(inputChannelObj);
1701
1702 return consumed && ! error;
1703 } else {
1704 LOGW("Could not apply key dispatch policy because input channel '%s' is "
1705 "no longer valid.", target.inputChannel->getName().string());
1706 return false;
1707 }
1708}
1709
Jeff Brown349703e2010-06-22 01:27:15 -07001710void NativeInputManager::pokeUserActivityIfNeeded(int32_t windowType, int32_t eventType) {
1711 if (windowType != TYPE_KEYGUARD) {
1712 nsecs_t eventTime = now();
1713 pokeUserActivity(eventTime, eventType);
1714 }
1715}
1716
1717void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001718 android_server_PowerManagerService_userActivity(eventTime, eventType);
Jeff Brown349703e2010-06-22 01:27:15 -07001719}
1720
Jeff Browne33348b2010-07-15 23:54:05 -07001721void NativeInputManager::logDispatchStateLd() {
1722 String8 dump;
1723 dumpDispatchStateLd(dump);
1724 LOGD("%s", dump.string());
1725}
1726
1727void NativeInputManager::dumpDispatchStateLd(String8& dump) {
1728 dump.appendFormat(" dispatchEnabled: %d\n", mDispatchEnabled);
1729 dump.appendFormat(" dispatchFrozen: %d\n", mDispatchFrozen);
1730 dump.appendFormat(" windowsReady: %d\n", mWindowsReady);
1731
Jeff Brown349703e2010-06-22 01:27:15 -07001732 if (mFocusedApplication) {
Jeff Browne33348b2010-07-15 23:54:05 -07001733 dump.appendFormat(" focusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001734 mFocusedApplication->name.string(),
1735 mFocusedApplication->dispatchingTimeout / 1000000.0);
1736 } else {
Jeff Browne33348b2010-07-15 23:54:05 -07001737 dump.append(" focusedApplication: <null>\n");
Jeff Brown349703e2010-06-22 01:27:15 -07001738 }
Jeff Browne33348b2010-07-15 23:54:05 -07001739 dump.appendFormat(" focusedWindow: '%s'\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001740 mFocusedWindow != NULL ? mFocusedWindow->inputChannel->getName().string() : "<null>");
Jeff Browne33348b2010-07-15 23:54:05 -07001741 dump.appendFormat(" touchedWindow: '%s', touchDown=%d\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001742 mTouchedWindow != NULL ? mTouchedWindow->inputChannel->getName().string() : "<null>",
1743 mTouchDown);
1744 for (size_t i = 0; i < mTouchedWallpaperWindows.size(); i++) {
Jeff Browne33348b2010-07-15 23:54:05 -07001745 dump.appendFormat(" touchedWallpaperWindows[%d]: '%s'\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001746 i, mTouchedWallpaperWindows[i]->inputChannel->getName().string());
1747 }
1748 for (size_t i = 0; i < mWindows.size(); i++) {
Jeff Browne33348b2010-07-15 23:54:05 -07001749 dump.appendFormat(" windows[%d]: '%s', paused=%d, hasFocus=%d, hasWallpaper=%d, "
1750 "visible=%d, flags=0x%08x, type=0x%08x, "
Jeff Brown349703e2010-06-22 01:27:15 -07001751 "frame=[%d,%d], touchableArea=[%d,%d][%d,%d], "
Jeff Browne33348b2010-07-15 23:54:05 -07001752 "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001753 i, mWindows[i].inputChannel->getName().string(),
1754 mWindows[i].paused, mWindows[i].hasFocus, mWindows[i].hasWallpaper,
1755 mWindows[i].visible, mWindows[i].layoutParamsFlags, mWindows[i].layoutParamsType,
1756 mWindows[i].frameLeft, mWindows[i].frameTop,
1757 mWindows[i].touchableAreaLeft, mWindows[i].touchableAreaTop,
1758 mWindows[i].touchableAreaRight, mWindows[i].touchableAreaBottom,
1759 mWindows[i].ownerPid, mWindows[i].ownerUid,
1760 mWindows[i].dispatchingTimeout / 1000000.0);
1761 }
Jeff Brown349703e2010-06-22 01:27:15 -07001762}
1763
1764// ----------------------------------------------------------------------------
1765
1766NativeInputManager::ANRTimer::ANRTimer() :
1767 mBudget(APPLICATION), mStartTime(now()), mFrozen(false), mPausedWindow(NULL) {
1768}
1769
1770void NativeInputManager::ANRTimer::dispatchFrozenBySystem() {
1771 mFrozen = true;
1772}
1773
1774void NativeInputManager::ANRTimer::dispatchPausedByApplication(InputWindow* pausedWindow) {
1775 mPausedWindow = pausedWindow;
1776}
1777
1778bool NativeInputManager::ANRTimer::waitForDispatchStateChangeLd(NativeInputManager* inputManager) {
1779 nsecs_t currentTime = now();
1780
1781 Budget newBudget;
1782 nsecs_t dispatchingTimeout;
1783 sp<InputChannel> pausedChannel = NULL;
1784 jobject tokenObj = NULL;
1785 if (mFrozen) {
1786 newBudget = SYSTEM;
1787 dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
1788 mFrozen = false;
1789 } else if (mPausedWindow) {
1790 newBudget = APPLICATION;
1791 dispatchingTimeout = mPausedWindow->dispatchingTimeout;
1792 pausedChannel = mPausedWindow->inputChannel;
1793 mPausedWindow = NULL;
1794 } else if (inputManager->mFocusedApplication) {
1795 newBudget = APPLICATION;
1796 dispatchingTimeout = inputManager->mFocusedApplication->dispatchingTimeout;
1797 tokenObj = jniEnv()->NewLocalRef(inputManager->mFocusedApplication->tokenObjWeak);
1798 } else {
1799 newBudget = APPLICATION;
1800 dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
1801 }
1802
1803 if (mBudget != newBudget) {
1804 mBudget = newBudget;
1805 mStartTime = currentTime;
1806 }
1807
1808 bool result = false;
1809 nsecs_t timeoutRemaining = mStartTime + dispatchingTimeout - currentTime;
1810 if (timeoutRemaining > 0
1811 && inputManager->mDispatchStateChanged.waitRelative(inputManager->mDispatchLock,
1812 timeoutRemaining) == OK) {
1813 result = true;
1814 } else {
1815 if (pausedChannel != NULL || tokenObj != NULL) {
1816 bool resumed;
1817 nsecs_t newTimeout = 0;
1818
1819 inputManager->mDispatchLock.unlock(); // release lock
1820 if (pausedChannel != NULL) {
1821 resumed = inputManager->notifyInputChannelANR(pausedChannel, /*out*/ newTimeout);
1822 } else {
1823 resumed = inputManager->notifyANR(tokenObj, /*out*/ newTimeout);
1824 }
1825 inputManager->mDispatchLock.lock(); // re-acquire lock
1826
1827 if (resumed) {
1828 mStartTime = now() - dispatchingTimeout + newTimeout;
1829 result = true;
1830 }
1831 }
1832 }
1833
1834 if (tokenObj) {
1835 jniEnv()->DeleteLocalRef(tokenObj);
1836 }
1837
1838 return result;
1839}
1840
1841nsecs_t NativeInputManager::ANRTimer::getTimeSpentWaitingForApplication() const {
1842 return mBudget == APPLICATION ? now() - mStartTime : 0;
1843}
Jeff Brown9c3cda02010-06-15 01:31:58 -07001844
1845// ----------------------------------------------------------------------------
1846
1847static sp<NativeInputManager> gNativeInputManager;
1848
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001849static bool checkInputManagerUnitialized(JNIEnv* env) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001850 if (gNativeInputManager == NULL) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001851 LOGE("Input manager not initialized.");
1852 jniThrowRuntimeException(env, "Input manager not initialized.");
1853 return true;
1854 }
1855 return false;
1856}
1857
1858static void android_server_InputManager_nativeInit(JNIEnv* env, jclass clazz,
1859 jobject callbacks) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001860 if (gNativeInputManager == NULL) {
1861 gNativeInputManager = new NativeInputManager(callbacks);
1862 } else {
1863 LOGE("Input manager already initialized.");
1864 jniThrowRuntimeException(env, "Input manager already initialized.");
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001865 }
1866}
1867
1868static void android_server_InputManager_nativeStart(JNIEnv* env, jclass clazz) {
1869 if (checkInputManagerUnitialized(env)) {
1870 return;
1871 }
1872
Jeff Brown9c3cda02010-06-15 01:31:58 -07001873 status_t result = gNativeInputManager->getInputManager()->start();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001874 if (result) {
1875 jniThrowRuntimeException(env, "Input manager could not be started.");
1876 }
1877}
1878
1879static void android_server_InputManager_nativeSetDisplaySize(JNIEnv* env, jclass clazz,
1880 jint displayId, jint width, jint height) {
1881 if (checkInputManagerUnitialized(env)) {
1882 return;
1883 }
1884
1885 // XXX we could get this from the SurfaceFlinger directly instead of requiring it
1886 // to be passed in like this, not sure which is better but leaving it like this
1887 // keeps the window manager in direct control of when display transitions propagate down
1888 // to the input dispatcher
Jeff Brown9c3cda02010-06-15 01:31:58 -07001889 gNativeInputManager->setDisplaySize(displayId, width, height);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001890}
1891
1892static void android_server_InputManager_nativeSetDisplayOrientation(JNIEnv* env, jclass clazz,
1893 jint displayId, jint orientation) {
1894 if (checkInputManagerUnitialized(env)) {
1895 return;
1896 }
1897
Jeff Brown9c3cda02010-06-15 01:31:58 -07001898 gNativeInputManager->setDisplayOrientation(displayId, orientation);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001899}
1900
1901static jint android_server_InputManager_nativeGetScanCodeState(JNIEnv* env, jclass clazz,
1902 jint deviceId, jint deviceClasses, jint scanCode) {
1903 if (checkInputManagerUnitialized(env)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001904 return AKEY_STATE_UNKNOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001905 }
1906
Jeff Brown9c3cda02010-06-15 01:31:58 -07001907 return gNativeInputManager->getInputManager()->getScanCodeState(
1908 deviceId, deviceClasses, scanCode);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001909}
1910
1911static jint android_server_InputManager_nativeGetKeyCodeState(JNIEnv* env, jclass clazz,
1912 jint deviceId, jint deviceClasses, jint keyCode) {
1913 if (checkInputManagerUnitialized(env)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001914 return AKEY_STATE_UNKNOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001915 }
1916
Jeff Brown9c3cda02010-06-15 01:31:58 -07001917 return gNativeInputManager->getInputManager()->getKeyCodeState(
1918 deviceId, deviceClasses, keyCode);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001919}
1920
1921static jint android_server_InputManager_nativeGetSwitchState(JNIEnv* env, jclass clazz,
1922 jint deviceId, jint deviceClasses, jint sw) {
1923 if (checkInputManagerUnitialized(env)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001924 return AKEY_STATE_UNKNOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001925 }
1926
Jeff Brown9c3cda02010-06-15 01:31:58 -07001927 return gNativeInputManager->getInputManager()->getSwitchState(deviceId, deviceClasses, sw);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001928}
1929
1930static jboolean android_server_InputManager_nativeHasKeys(JNIEnv* env, jclass clazz,
1931 jintArray keyCodes, jbooleanArray outFlags) {
1932 if (checkInputManagerUnitialized(env)) {
1933 return JNI_FALSE;
1934 }
1935
1936 int32_t* codes = env->GetIntArrayElements(keyCodes, NULL);
1937 uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL);
1938 jsize numCodes = env->GetArrayLength(keyCodes);
1939 jboolean result;
1940 if (numCodes == env->GetArrayLength(outFlags)) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001941 result = gNativeInputManager->getInputManager()->hasKeys(numCodes, codes, flags);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001942 } else {
1943 result = JNI_FALSE;
1944 }
1945
1946 env->ReleaseBooleanArrayElements(outFlags, flags, 0);
1947 env->ReleaseIntArrayElements(keyCodes, codes, 0);
1948 return result;
1949}
1950
1951static void throwInputChannelNotInitialized(JNIEnv* env) {
1952 jniThrowException(env, "java/lang/IllegalStateException",
1953 "inputChannel is not initialized");
1954}
1955
1956static void android_server_InputManager_handleInputChannelDisposed(JNIEnv* env,
1957 jobject inputChannelObj, const sp<InputChannel>& inputChannel, void* data) {
1958 LOGW("Input channel object '%s' was disposed without first being unregistered with "
1959 "the input manager!", inputChannel->getName().string());
1960
Jeff Brown9c3cda02010-06-15 01:31:58 -07001961 if (gNativeInputManager != NULL) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001962 gNativeInputManager->unregisterInputChannel(env, inputChannel);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001963 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001964}
1965
1966static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
1967 jobject inputChannelObj) {
1968 if (checkInputManagerUnitialized(env)) {
1969 return;
1970 }
1971
1972 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
1973 inputChannelObj);
1974 if (inputChannel == NULL) {
1975 throwInputChannelNotInitialized(env);
1976 return;
1977 }
1978
Jeff Brown7fbdc842010-06-17 20:52:56 -07001979
1980 status_t status = gNativeInputManager->registerInputChannel(
1981 env, inputChannel, inputChannelObj);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001982 if (status) {
1983 jniThrowRuntimeException(env, "Failed to register input channel. "
1984 "Check logs for details.");
1985 return;
1986 }
1987
1988 android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
1989 android_server_InputManager_handleInputChannelDisposed, NULL);
1990}
1991
1992static void android_server_InputManager_nativeUnregisterInputChannel(JNIEnv* env, jclass clazz,
1993 jobject inputChannelObj) {
1994 if (checkInputManagerUnitialized(env)) {
1995 return;
1996 }
1997
1998 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
1999 inputChannelObj);
2000 if (inputChannel == NULL) {
2001 throwInputChannelNotInitialized(env);
2002 return;
2003 }
2004
2005 android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL);
2006
Jeff Brown7fbdc842010-06-17 20:52:56 -07002007 status_t status = gNativeInputManager->unregisterInputChannel(env, inputChannel);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002008 if (status) {
2009 jniThrowRuntimeException(env, "Failed to unregister input channel. "
2010 "Check logs for details.");
2011 }
2012}
2013
Jeff Brown7fbdc842010-06-17 20:52:56 -07002014static jint android_server_InputManager_nativeInjectKeyEvent(JNIEnv* env, jclass clazz,
Jeff Brownc5ed5912010-07-14 18:48:53 -07002015 jobject keyEventObj, jint injectorPid, jint injectorUid,
Jeff Brown7fbdc842010-06-17 20:52:56 -07002016 jboolean sync, jint timeoutMillis) {
2017 if (checkInputManagerUnitialized(env)) {
2018 return INPUT_EVENT_INJECTION_FAILED;
2019 }
2020
2021 KeyEvent keyEvent;
Jeff Brownc5ed5912010-07-14 18:48:53 -07002022 android_view_KeyEvent_toNative(env, keyEventObj, & keyEvent);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002023
2024 return gNativeInputManager->getInputManager()->injectInputEvent(& keyEvent,
2025 injectorPid, injectorUid, sync, timeoutMillis);
2026}
2027
2028static jint android_server_InputManager_nativeInjectMotionEvent(JNIEnv* env, jclass clazz,
Jeff Brownc5ed5912010-07-14 18:48:53 -07002029 jobject motionEventObj, jint injectorPid, jint injectorUid,
Jeff Brown7fbdc842010-06-17 20:52:56 -07002030 jboolean sync, jint timeoutMillis) {
2031 if (checkInputManagerUnitialized(env)) {
2032 return INPUT_EVENT_INJECTION_FAILED;
2033 }
2034
2035 MotionEvent motionEvent;
Jeff Brownc5ed5912010-07-14 18:48:53 -07002036 android_view_MotionEvent_toNative(env, motionEventObj, & motionEvent);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002037
2038 return gNativeInputManager->getInputManager()->injectInputEvent(& motionEvent,
2039 injectorPid, injectorUid, sync, timeoutMillis);
2040}
2041
Jeff Brown349703e2010-06-22 01:27:15 -07002042static void android_server_InputManager_nativeSetInputWindows(JNIEnv* env, jclass clazz,
2043 jobjectArray windowObjArray) {
2044 if (checkInputManagerUnitialized(env)) {
2045 return;
2046 }
2047
2048 gNativeInputManager->setInputWindows(env, windowObjArray);
2049}
2050
2051static void android_server_InputManager_nativeSetFocusedApplication(JNIEnv* env, jclass clazz,
2052 jobject applicationObj) {
2053 if (checkInputManagerUnitialized(env)) {
2054 return;
2055 }
2056
2057 gNativeInputManager->setFocusedApplication(env, applicationObj);
2058}
2059
2060static void android_server_InputManager_nativeSetInputDispatchMode(JNIEnv* env,
2061 jclass clazz, jboolean enabled, jboolean frozen) {
2062 if (checkInputManagerUnitialized(env)) {
2063 return;
2064 }
2065
2066 gNativeInputManager->setInputDispatchMode(enabled, frozen);
2067}
2068
2069static void android_server_InputManager_nativePreemptInputDispatch(JNIEnv* env,
2070 jclass clazz) {
2071 if (checkInputManagerUnitialized(env)) {
2072 return;
2073 }
2074
2075 gNativeInputManager->preemptInputDispatch();
2076}
2077
Jeff Browne33348b2010-07-15 23:54:05 -07002078static jstring android_server_InputManager_nativeDump(JNIEnv* env, jclass clazz) {
2079 if (checkInputManagerUnitialized(env)) {
2080 return NULL;
2081 }
2082
2083 String8 dump(gNativeInputManager->dump());
2084 return env->NewStringUTF(dump.string());
2085}
2086
Jeff Brown9c3cda02010-06-15 01:31:58 -07002087// ----------------------------------------------------------------------------
2088
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002089static JNINativeMethod gInputManagerMethods[] = {
2090 /* name, signature, funcPtr */
2091 { "nativeInit", "(Lcom/android/server/InputManager$Callbacks;)V",
2092 (void*) android_server_InputManager_nativeInit },
2093 { "nativeStart", "()V",
2094 (void*) android_server_InputManager_nativeStart },
2095 { "nativeSetDisplaySize", "(III)V",
2096 (void*) android_server_InputManager_nativeSetDisplaySize },
2097 { "nativeSetDisplayOrientation", "(II)V",
2098 (void*) android_server_InputManager_nativeSetDisplayOrientation },
2099 { "nativeGetScanCodeState", "(III)I",
2100 (void*) android_server_InputManager_nativeGetScanCodeState },
2101 { "nativeGetKeyCodeState", "(III)I",
2102 (void*) android_server_InputManager_nativeGetKeyCodeState },
2103 { "nativeGetSwitchState", "(III)I",
2104 (void*) android_server_InputManager_nativeGetSwitchState },
2105 { "nativeHasKeys", "([I[Z)Z",
2106 (void*) android_server_InputManager_nativeHasKeys },
2107 { "nativeRegisterInputChannel", "(Landroid/view/InputChannel;)V",
2108 (void*) android_server_InputManager_nativeRegisterInputChannel },
2109 { "nativeUnregisterInputChannel", "(Landroid/view/InputChannel;)V",
Jeff Brown7fbdc842010-06-17 20:52:56 -07002110 (void*) android_server_InputManager_nativeUnregisterInputChannel },
Jeff Brownc5ed5912010-07-14 18:48:53 -07002111 { "nativeInjectKeyEvent", "(Landroid/view/KeyEvent;IIZI)I",
Jeff Brown7fbdc842010-06-17 20:52:56 -07002112 (void*) android_server_InputManager_nativeInjectKeyEvent },
Jeff Brownc5ed5912010-07-14 18:48:53 -07002113 { "nativeInjectMotionEvent", "(Landroid/view/MotionEvent;IIZI)I",
Jeff Brown349703e2010-06-22 01:27:15 -07002114 (void*) android_server_InputManager_nativeInjectMotionEvent },
2115 { "nativeSetInputWindows", "([Lcom/android/server/InputWindow;)V",
2116 (void*) android_server_InputManager_nativeSetInputWindows },
2117 { "nativeSetFocusedApplication", "(Lcom/android/server/InputApplication;)V",
2118 (void*) android_server_InputManager_nativeSetFocusedApplication },
2119 { "nativeSetInputDispatchMode", "(ZZ)V",
2120 (void*) android_server_InputManager_nativeSetInputDispatchMode },
2121 { "nativePreemptInputDispatch", "()V",
Jeff Browne33348b2010-07-15 23:54:05 -07002122 (void*) android_server_InputManager_nativePreemptInputDispatch },
2123 { "nativeDump", "()Ljava/lang/String;",
2124 (void*) android_server_InputManager_nativeDump },
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002125};
2126
2127#define FIND_CLASS(var, className) \
2128 var = env->FindClass(className); \
2129 LOG_FATAL_IF(! var, "Unable to find class " className); \
2130 var = jclass(env->NewGlobalRef(var));
2131
2132#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
2133 var = env->GetMethodID(clazz, methodName, methodDescriptor); \
2134 LOG_FATAL_IF(! var, "Unable to find method " methodName);
2135
2136#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
2137 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
2138 LOG_FATAL_IF(! var, "Unable to find field " fieldName);
2139
2140int register_android_server_InputManager(JNIEnv* env) {
2141 int res = jniRegisterNativeMethods(env, "com/android/server/InputManager",
2142 gInputManagerMethods, NELEM(gInputManagerMethods));
2143 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
2144
Jeff Brown9c3cda02010-06-15 01:31:58 -07002145 // Callbacks
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002146
2147 FIND_CLASS(gCallbacksClassInfo.clazz, "com/android/server/InputManager$Callbacks");
2148
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002149 GET_METHOD_ID(gCallbacksClassInfo.notifyConfigurationChanged, gCallbacksClassInfo.clazz,
2150 "notifyConfigurationChanged", "(JIII)V");
2151
2152 GET_METHOD_ID(gCallbacksClassInfo.notifyLidSwitchChanged, gCallbacksClassInfo.clazz,
2153 "notifyLidSwitchChanged", "(JZ)V");
2154
Jeff Brown7fbdc842010-06-17 20:52:56 -07002155 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelBroken, gCallbacksClassInfo.clazz,
2156 "notifyInputChannelBroken", "(Landroid/view/InputChannel;)V");
2157
2158 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelANR, gCallbacksClassInfo.clazz,
2159 "notifyInputChannelANR", "(Landroid/view/InputChannel;)J");
2160
2161 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelRecoveredFromANR, gCallbacksClassInfo.clazz,
2162 "notifyInputChannelRecoveredFromANR", "(Landroid/view/InputChannel;)V");
2163
Jeff Brown349703e2010-06-22 01:27:15 -07002164 GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
2165 "notifyANR", "(Ljava/lang/Object;)J");
2166
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002167 GET_METHOD_ID(gCallbacksClassInfo.virtualKeyDownFeedback, gCallbacksClassInfo.clazz,
2168 "virtualKeyDownFeedback", "()V");
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002169
Jeff Brown349703e2010-06-22 01:27:15 -07002170 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002171 "interceptKeyBeforeQueueing", "(JIZIZ)I");
Jeff Brown349703e2010-06-22 01:27:15 -07002172
2173 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002174 "interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIIIII)Z");
Jeff Brown349703e2010-06-22 01:27:15 -07002175
2176 GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,
2177 "checkInjectEventsPermission", "(II)Z");
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002178
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002179 GET_METHOD_ID(gCallbacksClassInfo.notifyAppSwitchComing, gCallbacksClassInfo.clazz,
2180 "notifyAppSwitchComing", "()V");
2181
2182 GET_METHOD_ID(gCallbacksClassInfo.filterTouchEvents, gCallbacksClassInfo.clazz,
2183 "filterTouchEvents", "()Z");
2184
2185 GET_METHOD_ID(gCallbacksClassInfo.filterJumpyTouchEvents, gCallbacksClassInfo.clazz,
2186 "filterJumpyTouchEvents", "()Z");
2187
2188 GET_METHOD_ID(gCallbacksClassInfo.getVirtualKeyDefinitions, gCallbacksClassInfo.clazz,
2189 "getVirtualKeyDefinitions",
2190 "(Ljava/lang/String;)[Lcom/android/server/InputManager$VirtualKeyDefinition;");
2191
2192 GET_METHOD_ID(gCallbacksClassInfo.getExcludedDeviceNames, gCallbacksClassInfo.clazz,
2193 "getExcludedDeviceNames", "()[Ljava/lang/String;");
2194
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002195 // VirtualKeyDefinition
2196
2197 FIND_CLASS(gVirtualKeyDefinitionClassInfo.clazz,
2198 "com/android/server/InputManager$VirtualKeyDefinition");
2199
2200 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.scanCode, gVirtualKeyDefinitionClassInfo.clazz,
2201 "scanCode", "I");
2202
2203 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerX, gVirtualKeyDefinitionClassInfo.clazz,
2204 "centerX", "I");
2205
2206 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerY, gVirtualKeyDefinitionClassInfo.clazz,
2207 "centerY", "I");
2208
2209 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.width, gVirtualKeyDefinitionClassInfo.clazz,
2210 "width", "I");
2211
2212 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.height, gVirtualKeyDefinitionClassInfo.clazz,
2213 "height", "I");
2214
Jeff Brown349703e2010-06-22 01:27:15 -07002215 // InputWindow
Jeff Brown7fbdc842010-06-17 20:52:56 -07002216
Jeff Brown349703e2010-06-22 01:27:15 -07002217 FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002218
Jeff Brown349703e2010-06-22 01:27:15 -07002219 GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
2220 "inputChannel", "Landroid/view/InputChannel;");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002221
Jeff Brown349703e2010-06-22 01:27:15 -07002222 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
2223 "layoutParamsFlags", "I");
2224
2225 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
2226 "layoutParamsType", "I");
2227
2228 GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
2229 "dispatchingTimeoutNanos", "J");
2230
2231 GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
2232 "frameLeft", "I");
2233
2234 GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
2235 "frameTop", "I");
2236
2237 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
2238 "touchableAreaLeft", "I");
2239
2240 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
2241 "touchableAreaTop", "I");
2242
2243 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
2244 "touchableAreaRight", "I");
2245
2246 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
2247 "touchableAreaBottom", "I");
2248
2249 GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
2250 "visible", "Z");
2251
2252 GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
2253 "hasFocus", "Z");
2254
2255 GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
2256 "hasWallpaper", "Z");
2257
2258 GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
2259 "paused", "Z");
2260
2261 GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
2262 "ownerPid", "I");
2263
2264 GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
2265 "ownerUid", "I");
2266
2267 // InputApplication
2268
2269 FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication");
2270
2271 GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
2272 "name", "Ljava/lang/String;");
2273
2274 GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
2275 gInputApplicationClassInfo.clazz,
2276 "dispatchingTimeoutNanos", "J");
2277
2278 GET_FIELD_ID(gInputApplicationClassInfo.token, gInputApplicationClassInfo.clazz,
2279 "token", "Ljava/lang/Object;");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002280
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002281 return 0;
2282}
2283
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002284} /* namespace android */