blob: 26e105a75390e9b63e1b5f33fac9e24328c1b6fc [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
202 void setDisplaySize(int32_t displayId, int32_t width, int32_t height);
203 void setDisplayOrientation(int32_t displayId, int32_t orientation);
204
Jeff Brown7fbdc842010-06-17 20:52:56 -0700205 status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
206 jweak inputChannelObjWeak);
207 status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
208
Jeff Brown349703e2010-06-22 01:27:15 -0700209 void setInputWindows(JNIEnv* env, jobjectArray windowObjArray);
210 void setFocusedApplication(JNIEnv* env, jobject applicationObj);
211 void setInputDispatchMode(bool enabled, bool frozen);
212 void preemptInputDispatch();
213
Jeff Brown9c3cda02010-06-15 01:31:58 -0700214 /* --- InputReaderPolicyInterface implementation --- */
215
216 virtual bool getDisplayInfo(int32_t displayId,
217 int32_t* width, int32_t* height, int32_t* orientation);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700218 virtual void virtualKeyDownFeedback();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700219 virtual int32_t interceptKey(nsecs_t when, int32_t deviceId,
220 bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags);
221 virtual int32_t interceptTrackball(nsecs_t when, bool buttonChanged, bool buttonDown,
222 bool rolled);
223 virtual int32_t interceptTouch(nsecs_t when);
224 virtual int32_t interceptSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue);
225 virtual bool filterTouchEvents();
226 virtual bool filterJumpyTouchEvents();
227 virtual void getVirtualKeyDefinitions(const String8& deviceName,
228 Vector<InputReaderPolicyInterface::VirtualKeyDefinition>& outVirtualKeyDefinitions);
229 virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames);
230
231 /* --- InputDispatcherPolicyInterface implementation --- */
232
233 virtual void notifyConfigurationChanged(nsecs_t when);
234 virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700235 virtual bool notifyInputChannelANR(const sp<InputChannel>& inputChannel,
236 nsecs_t& outNewTimeout);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700237 virtual void notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel);
238 virtual nsecs_t getKeyRepeatTimeout();
Jeff Brown349703e2010-06-22 01:27:15 -0700239 virtual int32_t waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700240 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brown349703e2010-06-22 01:27:15 -0700241 virtual int32_t waitForMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700242 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700243
244private:
Jeff Brown349703e2010-06-22 01:27:15 -0700245 struct InputWindow {
246 sp<InputChannel> inputChannel;
247 int32_t layoutParamsFlags;
248 int32_t layoutParamsType;
249 nsecs_t dispatchingTimeout;
250 int32_t frameLeft;
251 int32_t frameTop;
252 int32_t touchableAreaLeft;
253 int32_t touchableAreaTop;
254 int32_t touchableAreaRight;
255 int32_t touchableAreaBottom;
256 bool visible;
257 bool hasFocus;
258 bool hasWallpaper;
259 bool paused;
260 int32_t ownerPid;
261 int32_t ownerUid;
262
263 inline bool touchableAreaContainsPoint(int32_t x, int32_t y) {
264 return x >= touchableAreaLeft && x <= touchableAreaRight
265 && y >= touchableAreaTop && y <= touchableAreaBottom;
266 }
267 };
268
269 struct InputApplication {
270 String8 name;
271 nsecs_t dispatchingTimeout;
272 jweak tokenObjWeak;
273 };
274
275 class ANRTimer {
276 enum Budget {
277 SYSTEM = 0,
278 APPLICATION = 1
279 };
280
281 Budget mBudget;
282 nsecs_t mStartTime;
283 bool mFrozen;
284 InputWindow* mPausedWindow;
285
286 public:
287 ANRTimer();
288
289 void dispatchFrozenBySystem();
290 void dispatchPausedByApplication(InputWindow* pausedWindow);
291 bool waitForDispatchStateChangeLd(NativeInputManager* inputManager);
292
293 nsecs_t getTimeSpentWaitingForApplication() const;
294 };
295
Jeff Brown9c3cda02010-06-15 01:31:58 -0700296 sp<InputManager> mInputManager;
297
298 jobject mCallbacksObj;
299
300 // Cached filtering policies.
301 int32_t mFilterTouchEvents;
302 int32_t mFilterJumpyTouchEvents;
303
304 // Cached display state. (lock mDisplayLock)
305 Mutex mDisplayLock;
306 int32_t mDisplayWidth, mDisplayHeight;
307 int32_t mDisplayOrientation;
308
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700309 // Power manager interactions.
Jeff Brown9c3cda02010-06-15 01:31:58 -0700310 bool isScreenOn();
311 bool isScreenBright();
312
Jeff Brown7fbdc842010-06-17 20:52:56 -0700313 // Weak references to all currently registered input channels by receive fd.
314 Mutex mInputChannelRegistryLock;
315 KeyedVector<int, jweak> mInputChannelObjWeakByReceiveFd;
316
317 jobject getInputChannelObjLocal(JNIEnv* env, const sp<InputChannel>& inputChannel);
318
Jeff Brown349703e2010-06-22 01:27:15 -0700319 // Input target and focus tracking. (lock mDispatchLock)
320 Mutex mDispatchLock;
321 Condition mDispatchStateChanged;
322
323 bool mDispatchEnabled;
324 bool mDispatchFrozen;
325 bool mWindowsReady;
326 Vector<InputWindow> mWindows;
327 Vector<InputWindow*> mWallpaperWindows;
328
329 // Focus tracking for keys, trackball, etc.
330 InputWindow* mFocusedWindow;
331
332 // Focus tracking for touch.
333 bool mTouchDown;
334 InputWindow* mTouchedWindow; // primary target for current down
335 Vector<InputWindow*> mTouchedWallpaperWindows; // wallpaper targets
336
337 Vector<InputWindow*> mTempTouchedOutsideWindows; // temporary outside touch targets
338 Vector<sp<InputChannel> > mTempTouchedWallpaperChannels; // temporary wallpaper targets
339
340 // Focused application.
341 InputApplication* mFocusedApplication;
342 InputApplication mFocusedApplicationStorage; // preallocated storage for mFocusedApplication
343
344 void dumpDispatchStateLd();
345
346 bool notifyANR(jobject tokenObj, nsecs_t& outNewTimeout);
347 void releaseFocusedApplicationLd(JNIEnv* env);
348
349 int32_t waitForFocusedWindowLd(uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
350 Vector<InputTarget>& outTargets, InputWindow*& outFocusedWindow);
351 int32_t waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
352 int32_t injectorPid, int32_t injectorUid,
353 Vector<InputTarget>& outTargets, InputWindow*& outTouchedWindow);
354
355 void releaseTouchedWindowLd();
356
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700357 int32_t waitForTrackballEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown349703e2010-06-22 01:27:15 -0700358 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700359 int32_t waitForTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown349703e2010-06-22 01:27:15 -0700360 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
361
Jeff Brownd0097872010-06-30 14:41:59 -0700362 bool interceptKeyBeforeDispatching(const InputTarget& target,
363 const KeyEvent* keyEvent, uint32_t policyFlags);
364
Jeff Brown349703e2010-06-22 01:27:15 -0700365 void pokeUserActivityIfNeeded(int32_t windowType, int32_t eventType);
366 void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
367 bool checkInjectionPermission(const InputWindow* window,
368 int32_t injectorPid, int32_t injectorUid);
369
370 static bool populateWindow(JNIEnv* env, jobject windowObj, InputWindow& outWindow);
371 static void addTarget(const InputWindow* window, int32_t targetFlags,
372 nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets);
373
Jeff Brown9c3cda02010-06-15 01:31:58 -0700374 static inline JNIEnv* jniEnv() {
375 return AndroidRuntime::getJNIEnv();
376 }
377
378 static bool isAppSwitchKey(int32_t keyCode);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700379 static bool isPolicyKey(int32_t keyCode, bool isScreenOn);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700380 static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700381};
382
383// ----------------------------------------------------------------------------
384
385NativeInputManager::NativeInputManager(jobject callbacksObj) :
386 mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1),
Jeff Brown0b72e822010-06-29 16:52:21 -0700387 mDisplayWidth(-1), mDisplayHeight(-1), mDisplayOrientation(ROTATION_0),
Jeff Brown349703e2010-06-22 01:27:15 -0700388 mDispatchEnabled(true), mDispatchFrozen(false), mWindowsReady(true),
389 mFocusedWindow(NULL), mTouchDown(false), mTouchedWindow(NULL),
390 mFocusedApplication(NULL) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700391 JNIEnv* env = jniEnv();
392
393 mCallbacksObj = env->NewGlobalRef(callbacksObj);
394
395 sp<EventHub> eventHub = new EventHub();
396 mInputManager = new InputManager(eventHub, this, this);
397}
398
399NativeInputManager::~NativeInputManager() {
400 JNIEnv* env = jniEnv();
401
402 env->DeleteGlobalRef(mCallbacksObj);
Jeff Brown349703e2010-06-22 01:27:15 -0700403
404 releaseFocusedApplicationLd(env);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700405}
406
407bool NativeInputManager::isAppSwitchKey(int32_t keyCode) {
Jeff Brownfd035822010-06-30 16:10:35 -0700408 return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700409}
410
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700411bool NativeInputManager::isPolicyKey(int32_t keyCode, bool isScreenOn) {
412 // Special keys that the WindowManagerPolicy might care about.
413 switch (keyCode) {
Jeff Brownfd035822010-06-30 16:10:35 -0700414 case AKEYCODE_VOLUME_UP:
415 case AKEYCODE_VOLUME_DOWN:
416 case AKEYCODE_ENDCALL:
417 case AKEYCODE_POWER:
418 case AKEYCODE_CALL:
419 case AKEYCODE_HOME:
420 case AKEYCODE_MENU:
421 case AKEYCODE_SEARCH:
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700422 // media keys
Jeff Brownfd035822010-06-30 16:10:35 -0700423 case AKEYCODE_HEADSETHOOK:
424 case AKEYCODE_MEDIA_PLAY_PAUSE:
425 case AKEYCODE_MEDIA_STOP:
426 case AKEYCODE_MEDIA_NEXT:
427 case AKEYCODE_MEDIA_PREVIOUS:
428 case AKEYCODE_MEDIA_REWIND:
429 case AKEYCODE_MEDIA_FAST_FORWARD:
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700430 return true;
431 default:
432 // We need to pass all keys to the policy in the following cases:
433 // - screen is off
434 // - keyguard is visible
435 // - policy is performing key chording
436 //return ! isScreenOn || keyguardVisible || chording;
437 return true; // XXX stubbed out for now
438 }
439}
440
Jeff Brown7fbdc842010-06-17 20:52:56 -0700441bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700442 if (env->ExceptionCheck()) {
443 LOGE("An exception was thrown by callback '%s'.", methodName);
444 LOGE_EX(env);
445 env->ExceptionClear();
446 return true;
447 }
448 return false;
449}
450
451void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height) {
452 if (displayId == 0) {
453 AutoMutex _l(mDisplayLock);
454
455 mDisplayWidth = width;
456 mDisplayHeight = height;
457 }
458}
459
460void NativeInputManager::setDisplayOrientation(int32_t displayId, int32_t orientation) {
461 if (displayId == 0) {
462 AutoMutex _l(mDisplayLock);
463
464 mDisplayOrientation = orientation;
465 }
466}
467
Jeff Brown7fbdc842010-06-17 20:52:56 -0700468status_t NativeInputManager::registerInputChannel(JNIEnv* env,
469 const sp<InputChannel>& inputChannel, jobject inputChannelObj) {
470 jweak inputChannelObjWeak = env->NewWeakGlobalRef(inputChannelObj);
471 if (! inputChannelObjWeak) {
472 LOGE("Could not create weak reference for input channel.");
473 LOGE_EX(env);
474 return NO_MEMORY;
475 }
476
477 status_t status;
478 {
479 AutoMutex _l(mInputChannelRegistryLock);
480
481 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
482 inputChannel->getReceivePipeFd());
483 if (index >= 0) {
484 LOGE("Input channel object '%s' has already been registered",
485 inputChannel->getName().string());
486 status = INVALID_OPERATION;
487 goto DeleteWeakRef;
488 }
489
490 mInputChannelObjWeakByReceiveFd.add(inputChannel->getReceivePipeFd(),
491 inputChannelObjWeak);
492 }
493
494 status = mInputManager->registerInputChannel(inputChannel);
495 if (! status) {
496 return OK;
497 }
498
499 {
500 AutoMutex _l(mInputChannelRegistryLock);
501 mInputChannelObjWeakByReceiveFd.removeItem(inputChannel->getReceivePipeFd());
502 }
503
504DeleteWeakRef:
505 env->DeleteWeakGlobalRef(inputChannelObjWeak);
506 return status;
507}
508
509status_t NativeInputManager::unregisterInputChannel(JNIEnv* env,
510 const sp<InputChannel>& inputChannel) {
511 jweak inputChannelObjWeak;
512 {
513 AutoMutex _l(mInputChannelRegistryLock);
514
515 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
516 inputChannel->getReceivePipeFd());
517 if (index < 0) {
518 LOGE("Input channel object '%s' is not currently registered",
519 inputChannel->getName().string());
520 return INVALID_OPERATION;
521 }
522
523 inputChannelObjWeak = mInputChannelObjWeakByReceiveFd.valueAt(index);
524 mInputChannelObjWeakByReceiveFd.removeItemsAt(index);
525 }
526
527 env->DeleteWeakGlobalRef(inputChannelObjWeak);
528
529 return mInputManager->unregisterInputChannel(inputChannel);
530}
531
532jobject NativeInputManager::getInputChannelObjLocal(JNIEnv* env,
533 const sp<InputChannel>& inputChannel) {
534 {
535 AutoMutex _l(mInputChannelRegistryLock);
536
537 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
538 inputChannel->getReceivePipeFd());
539 if (index < 0) {
540 return NULL;
541 }
542
543 jweak inputChannelObjWeak = mInputChannelObjWeakByReceiveFd.valueAt(index);
544 return env->NewLocalRef(inputChannelObjWeak);
545 }
546}
547
Jeff Brown9c3cda02010-06-15 01:31:58 -0700548bool NativeInputManager::getDisplayInfo(int32_t displayId,
549 int32_t* width, int32_t* height, int32_t* orientation) {
550 bool result = false;
551 if (displayId == 0) {
552 AutoMutex _l(mDisplayLock);
553
554 if (mDisplayWidth > 0) {
555 *width = mDisplayWidth;
556 *height = mDisplayHeight;
557 *orientation = mDisplayOrientation;
558 result = true;
559 }
560 }
561 return result;
562}
563
564bool NativeInputManager::isScreenOn() {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700565 return android_server_PowerManagerService_isScreenOn();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700566}
567
568bool NativeInputManager::isScreenBright() {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700569 return android_server_PowerManagerService_isScreenBright();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700570}
571
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700572void NativeInputManager::virtualKeyDownFeedback() {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700573#if DEBUG_INPUT_READER_POLICY
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700574 LOGD("virtualKeyDownFeedback");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700575#endif
576
577 JNIEnv* env = jniEnv();
578
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700579 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.virtualKeyDownFeedback);
580 checkAndClearExceptionFromCallback(env, "virtualKeyDownFeedback");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700581}
582
583int32_t NativeInputManager::interceptKey(nsecs_t when,
584 int32_t deviceId, bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) {
585#if DEBUG_INPUT_READER_POLICY
586 LOGD("interceptKey - when=%lld, deviceId=%d, down=%d, keyCode=%d, scanCode=%d, "
Jeff Brown349703e2010-06-22 01:27:15 -0700587 "policyFlags=0x%x",
Jeff Brown9c3cda02010-06-15 01:31:58 -0700588 when, deviceId, down, keyCode, scanCode, policyFlags);
589#endif
590
591 const int32_t WM_ACTION_PASS_TO_USER = 1;
592 const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2;
593 const int32_t WM_ACTION_GO_TO_SLEEP = 4;
594
Jeff Brown9c3cda02010-06-15 01:31:58 -0700595 bool isScreenOn = this->isScreenOn();
596 bool isScreenBright = this->isScreenBright();
597
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700598 jint wmActions = 0;
599 if (isPolicyKey(keyCode, isScreenOn)) {
600 JNIEnv* env = jniEnv();
601
602 wmActions = env->CallIntMethod(mCallbacksObj,
603 gCallbacksClassInfo.interceptKeyBeforeQueueing,
604 when, keyCode, down, policyFlags, isScreenOn);
605 if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
606 wmActions = 0;
607 }
608 } else {
609 wmActions = WM_ACTION_PASS_TO_USER;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700610 }
611
612 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
613 if (! isScreenOn) {
614 // Key presses and releases wake the device.
615 actions |= InputReaderPolicyInterface::ACTION_WOKE_HERE;
616 }
617
618 if (! isScreenBright) {
619 // Key presses and releases brighten the screen if dimmed.
620 actions |= InputReaderPolicyInterface::ACTION_BRIGHT_HERE;
621 }
622
623 if (wmActions & WM_ACTION_GO_TO_SLEEP) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700624 android_server_PowerManagerService_goToSleep(when);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700625 }
626
627 if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
Jeff Brown349703e2010-06-22 01:27:15 -0700628 pokeUserActivity(when, POWER_MANAGER_BUTTON_EVENT);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700629 }
630
631 if (wmActions & WM_ACTION_PASS_TO_USER) {
632 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700633
Jeff Brown9c3cda02010-06-15 01:31:58 -0700634 if (down && isAppSwitchKey(keyCode)) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700635 JNIEnv* env = jniEnv();
636
Jeff Brown9c3cda02010-06-15 01:31:58 -0700637 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyAppSwitchComing);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700638 checkAndClearExceptionFromCallback(env, "notifyAppSwitchComing");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700639
640 actions |= InputReaderPolicyInterface::ACTION_APP_SWITCH_COMING;
641 }
642 }
Jeff Brown349703e2010-06-22 01:27:15 -0700643
Jeff Brown9c3cda02010-06-15 01:31:58 -0700644 return actions;
645}
646
647int32_t NativeInputManager::interceptTouch(nsecs_t when) {
648#if DEBUG_INPUT_READER_POLICY
649 LOGD("interceptTouch - when=%lld", when);
650#endif
651
Jeff Brown5c225b12010-06-16 01:53:36 -0700652 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
653 if (isScreenOn()) {
654 // Only dispatch touch events when the device is awake.
Jeff Brown349703e2010-06-22 01:27:15 -0700655 // Do not wake the device.
Jeff Brown5c225b12010-06-16 01:53:36 -0700656 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700657
Jeff Brown349703e2010-06-22 01:27:15 -0700658 if (! isScreenBright()) {
659 // Brighten the screen if dimmed.
660 actions |= InputReaderPolicyInterface::ACTION_BRIGHT_HERE;
661 }
Jeff Brown5c225b12010-06-16 01:53:36 -0700662 }
663
664 return actions;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700665}
666
667int32_t NativeInputManager::interceptTrackball(nsecs_t when,
668 bool buttonChanged, bool buttonDown, bool rolled) {
669#if DEBUG_INPUT_READER_POLICY
670 LOGD("interceptTrackball - when=%lld, buttonChanged=%d, buttonDown=%d, rolled=%d",
671 when, buttonChanged, buttonDown, rolled);
672#endif
673
Jeff Brown5c225b12010-06-16 01:53:36 -0700674 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
675 if (isScreenOn()) {
676 // Only dispatch trackball events when the device is awake.
Jeff Brown349703e2010-06-22 01:27:15 -0700677 // Do not wake the device.
Jeff Brown5c225b12010-06-16 01:53:36 -0700678 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700679
Jeff Brown349703e2010-06-22 01:27:15 -0700680 if (! isScreenBright()) {
681 // Brighten the screen if dimmed.
682 actions |= InputReaderPolicyInterface::ACTION_BRIGHT_HERE;
683 }
Jeff Brown5c225b12010-06-16 01:53:36 -0700684 }
685
686 return actions;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700687}
688
689int32_t NativeInputManager::interceptSwitch(nsecs_t when, int32_t switchCode,
690 int32_t switchValue) {
691#if DEBUG_INPUT_READER_POLICY
692 LOGD("interceptSwitch - when=%lld, switchCode=%d, switchValue=%d",
693 when, switchCode, switchValue);
694#endif
695
696 JNIEnv* env = jniEnv();
697
698 switch (switchCode) {
699 case SW_LID:
700 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyLidSwitchChanged,
701 when, switchValue == 0);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700702 checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700703 break;
704 }
705
706 return InputReaderPolicyInterface::ACTION_NONE;
707}
708
709bool NativeInputManager::filterTouchEvents() {
710 if (mFilterTouchEvents < 0) {
711 JNIEnv* env = jniEnv();
712
713 jboolean result = env->CallBooleanMethod(mCallbacksObj,
714 gCallbacksClassInfo.filterTouchEvents);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700715 if (checkAndClearExceptionFromCallback(env, "filterTouchEvents")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700716 result = false;
717 }
718
719 mFilterTouchEvents = result ? 1 : 0;
720 }
721 return mFilterTouchEvents;
722}
723
724bool NativeInputManager::filterJumpyTouchEvents() {
725 if (mFilterJumpyTouchEvents < 0) {
726 JNIEnv* env = jniEnv();
727
728 jboolean result = env->CallBooleanMethod(mCallbacksObj,
729 gCallbacksClassInfo.filterJumpyTouchEvents);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700730 if (checkAndClearExceptionFromCallback(env, "filterJumpyTouchEvents")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700731 result = false;
732 }
733
734 mFilterJumpyTouchEvents = result ? 1 : 0;
735 }
736 return mFilterJumpyTouchEvents;
737}
738
739void NativeInputManager::getVirtualKeyDefinitions(const String8& deviceName,
740 Vector<InputReaderPolicyInterface::VirtualKeyDefinition>& outVirtualKeyDefinitions) {
741 JNIEnv* env = jniEnv();
742
743 jstring deviceNameStr = env->NewStringUTF(deviceName.string());
Jeff Brown7fbdc842010-06-17 20:52:56 -0700744 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700745 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
746 gCallbacksClassInfo.getVirtualKeyDefinitions, deviceNameStr));
Jeff Brown7fbdc842010-06-17 20:52:56 -0700747 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions") && result) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700748 jsize length = env->GetArrayLength(result);
749 for (jsize i = 0; i < length; i++) {
750 jobject item = env->GetObjectArrayElement(result, i);
751
752 outVirtualKeyDefinitions.add();
753 outVirtualKeyDefinitions.editTop().scanCode =
754 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.scanCode));
755 outVirtualKeyDefinitions.editTop().centerX =
756 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerX));
757 outVirtualKeyDefinitions.editTop().centerY =
758 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerY));
759 outVirtualKeyDefinitions.editTop().width =
760 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.width));
761 outVirtualKeyDefinitions.editTop().height =
762 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.height));
763
764 env->DeleteLocalRef(item);
765 }
766 env->DeleteLocalRef(result);
767 }
768 env->DeleteLocalRef(deviceNameStr);
769 }
770}
771
772void NativeInputManager::getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
773 JNIEnv* env = jniEnv();
774
775 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
776 gCallbacksClassInfo.getExcludedDeviceNames));
Jeff Brown7fbdc842010-06-17 20:52:56 -0700777 if (! checkAndClearExceptionFromCallback(env, "getExcludedDeviceNames") && result) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700778 jsize length = env->GetArrayLength(result);
779 for (jsize i = 0; i < length; i++) {
780 jstring item = jstring(env->GetObjectArrayElement(result, i));
781
782 const char* deviceNameChars = env->GetStringUTFChars(item, NULL);
783 outExcludedDeviceNames.add(String8(deviceNameChars));
784 env->ReleaseStringUTFChars(item, deviceNameChars);
785
786 env->DeleteLocalRef(item);
787 }
788 env->DeleteLocalRef(result);
789 }
790}
791
792void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
793#if DEBUG_INPUT_DISPATCHER_POLICY
794 LOGD("notifyConfigurationChanged - when=%lld", when);
795#endif
796
797 JNIEnv* env = jniEnv();
798
799 InputConfiguration config;
800 mInputManager->getInputConfiguration(& config);
801
802 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyConfigurationChanged,
803 when, config.touchScreen, config.keyboard, config.navigation);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700804 checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700805}
806
807void NativeInputManager::notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
808#if DEBUG_INPUT_DISPATCHER_POLICY
809 LOGD("notifyInputChannelBroken - inputChannel='%s'", inputChannel->getName().string());
810#endif
811
Jeff Brown7fbdc842010-06-17 20:52:56 -0700812 JNIEnv* env = jniEnv();
813
814 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
815 if (inputChannelObjLocal) {
816 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelBroken,
817 inputChannelObjLocal);
818 checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken");
819
820 env->DeleteLocalRef(inputChannelObjLocal);
821 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700822}
823
Jeff Brown7fbdc842010-06-17 20:52:56 -0700824bool NativeInputManager::notifyInputChannelANR(const sp<InputChannel>& inputChannel,
825 nsecs_t& outNewTimeout) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700826#if DEBUG_INPUT_DISPATCHER_POLICY
827 LOGD("notifyInputChannelANR - inputChannel='%s'",
828 inputChannel->getName().string());
829#endif
830
Jeff Brown7fbdc842010-06-17 20:52:56 -0700831 JNIEnv* env = jniEnv();
832
833 jlong newTimeout;
834 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
835 if (inputChannelObjLocal) {
836 newTimeout = env->CallLongMethod(mCallbacksObj,
837 gCallbacksClassInfo.notifyInputChannelANR, inputChannelObjLocal);
838 if (checkAndClearExceptionFromCallback(env, "notifyInputChannelANR")) {
839 newTimeout = -2;
840 }
841
842 env->DeleteLocalRef(inputChannelObjLocal);
843 } else {
844 newTimeout = -2;
845 }
846
847 if (newTimeout == -2) {
848 return false; // abort
849 }
850
851 outNewTimeout = newTimeout;
852 return true; // resume
Jeff Brown9c3cda02010-06-15 01:31:58 -0700853}
854
855void NativeInputManager::notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel) {
856#if DEBUG_INPUT_DISPATCHER_POLICY
857 LOGD("notifyInputChannelRecoveredFromANR - inputChannel='%s'",
858 inputChannel->getName().string());
859#endif
860
Jeff Brown7fbdc842010-06-17 20:52:56 -0700861 JNIEnv* env = jniEnv();
862
863 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
864 if (inputChannelObjLocal) {
865 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelRecoveredFromANR,
866 inputChannelObjLocal);
867 checkAndClearExceptionFromCallback(env, "notifyInputChannelRecoveredFromANR");
868
869 env->DeleteLocalRef(inputChannelObjLocal);
870 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700871}
872
Jeff Brown349703e2010-06-22 01:27:15 -0700873bool NativeInputManager::notifyANR(jobject tokenObj, nsecs_t& outNewTimeout) {
874#if DEBUG_INPUT_DISPATCHER_POLICY
875 LOGD("notifyANR");
876#endif
877
878 JNIEnv* env = jniEnv();
879
880 jlong newTimeout = env->CallLongMethod(mCallbacksObj,
881 gCallbacksClassInfo.notifyANR, tokenObj);
882 if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
883 newTimeout = -2;
884 }
885
886 if (newTimeout == -2) {
887 return false; // abort
888 }
889
890 outNewTimeout = newTimeout;
891 return true; // resume
892}
893
Jeff Brown9c3cda02010-06-15 01:31:58 -0700894nsecs_t NativeInputManager::getKeyRepeatTimeout() {
895 if (! isScreenOn()) {
896 // Disable key repeat when the screen is off.
897 return -1;
898 } else {
899 // TODO use ViewConfiguration.getLongPressTimeout()
900 return milliseconds_to_nanoseconds(500);
901 }
902}
903
Jeff Brown349703e2010-06-22 01:27:15 -0700904void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArray) {
905#if DEBUG_FOCUS
906 LOGD("setInputWindows");
907#endif
908 { // acquire lock
909 AutoMutex _l(mDispatchLock);
910
911 sp<InputChannel> touchedWindowChannel;
912 if (mTouchedWindow) {
913 touchedWindowChannel = mTouchedWindow->inputChannel;
914 mTouchedWindow = NULL;
915 }
916 size_t numTouchedWallpapers = mTouchedWallpaperWindows.size();
917 if (numTouchedWallpapers != 0) {
918 for (size_t i = 0; i < numTouchedWallpapers; i++) {
919 mTempTouchedWallpaperChannels.push(mTouchedWallpaperWindows[i]->inputChannel);
920 }
921 mTouchedWallpaperWindows.clear();
922 }
923
924 mWindows.clear();
925 mFocusedWindow = NULL;
926 mWallpaperWindows.clear();
927
928 if (windowObjArray) {
929 mWindowsReady = true;
930
931 jsize length = env->GetArrayLength(windowObjArray);
932 for (jsize i = 0; i < length; i++) {
933 jobject inputTargetObj = env->GetObjectArrayElement(windowObjArray, i);
934 if (! inputTargetObj) {
935 break; // found null element indicating end of used portion of the array
936 }
937
938 mWindows.push();
939 InputWindow& window = mWindows.editTop();
940 bool valid = populateWindow(env, inputTargetObj, window);
941 if (! valid) {
942 mWindows.pop();
943 }
944
945 env->DeleteLocalRef(inputTargetObj);
946 }
947
948 size_t numWindows = mWindows.size();
949 for (size_t i = 0; i < numWindows; i++) {
950 InputWindow* window = & mWindows.editItemAt(i);
951 if (window->hasFocus) {
952 mFocusedWindow = window;
953 }
954
955 if (window->layoutParamsType == TYPE_WALLPAPER) {
956 mWallpaperWindows.push(window);
957
958 for (size_t j = 0; j < numTouchedWallpapers; j++) {
959 if (window->inputChannel == mTempTouchedWallpaperChannels[i]) {
960 mTouchedWallpaperWindows.push(window);
961 }
962 }
963 }
964
965 if (window->inputChannel == touchedWindowChannel) {
966 mTouchedWindow = window;
967 }
968 }
969 } else {
970 mWindowsReady = false;
971 }
972
973 mTempTouchedWallpaperChannels.clear();
974
975 mDispatchStateChanged.broadcast();
976
977#if DEBUG_FOCUS
978 dumpDispatchStateLd();
979#endif
980 } // release lock
981}
982
983bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj,
984 InputWindow& outWindow) {
985 bool valid = false;
986
987 jobject inputChannelObj = env->GetObjectField(windowObj,
988 gInputWindowClassInfo.inputChannel);
989 if (inputChannelObj) {
990 sp<InputChannel> inputChannel =
991 android_view_InputChannel_getInputChannel(env, inputChannelObj);
992 if (inputChannel != NULL) {
993 jint layoutParamsFlags = env->GetIntField(windowObj,
994 gInputWindowClassInfo.layoutParamsFlags);
995 jint layoutParamsType = env->GetIntField(windowObj,
996 gInputWindowClassInfo.layoutParamsType);
997 jlong dispatchingTimeoutNanos = env->GetLongField(windowObj,
998 gInputWindowClassInfo.dispatchingTimeoutNanos);
999 jint frameLeft = env->GetIntField(windowObj,
1000 gInputWindowClassInfo.frameLeft);
1001 jint frameTop = env->GetIntField(windowObj,
1002 gInputWindowClassInfo.frameTop);
1003 jint touchableAreaLeft = env->GetIntField(windowObj,
1004 gInputWindowClassInfo.touchableAreaLeft);
1005 jint touchableAreaTop = env->GetIntField(windowObj,
1006 gInputWindowClassInfo.touchableAreaTop);
1007 jint touchableAreaRight = env->GetIntField(windowObj,
1008 gInputWindowClassInfo.touchableAreaRight);
1009 jint touchableAreaBottom = env->GetIntField(windowObj,
1010 gInputWindowClassInfo.touchableAreaBottom);
1011 jboolean visible = env->GetBooleanField(windowObj,
1012 gInputWindowClassInfo.visible);
1013 jboolean hasFocus = env->GetBooleanField(windowObj,
1014 gInputWindowClassInfo.hasFocus);
1015 jboolean hasWallpaper = env->GetBooleanField(windowObj,
1016 gInputWindowClassInfo.hasWallpaper);
1017 jboolean paused = env->GetBooleanField(windowObj,
1018 gInputWindowClassInfo.paused);
1019 jint ownerPid = env->GetIntField(windowObj,
1020 gInputWindowClassInfo.ownerPid);
1021 jint ownerUid = env->GetIntField(windowObj,
1022 gInputWindowClassInfo.ownerUid);
1023
1024 outWindow.inputChannel = inputChannel;
1025 outWindow.layoutParamsFlags = layoutParamsFlags;
1026 outWindow.layoutParamsType = layoutParamsType;
1027 outWindow.dispatchingTimeout = dispatchingTimeoutNanos;
1028 outWindow.frameLeft = frameLeft;
1029 outWindow.frameTop = frameTop;
1030 outWindow.touchableAreaLeft = touchableAreaLeft;
1031 outWindow.touchableAreaTop = touchableAreaTop;
1032 outWindow.touchableAreaRight = touchableAreaRight;
1033 outWindow.touchableAreaBottom = touchableAreaBottom;
1034 outWindow.visible = visible;
1035 outWindow.hasFocus = hasFocus;
1036 outWindow.hasWallpaper = hasWallpaper;
1037 outWindow.paused = paused;
1038 outWindow.ownerPid = ownerPid;
1039 outWindow.ownerUid = ownerUid;
1040 valid = true;
1041 } else {
1042 LOGW("Dropping input target because its input channel is not initialized.");
1043 }
1044
1045 env->DeleteLocalRef(inputChannelObj);
1046 } else {
1047 LOGW("Dropping input target because the input channel object was null.");
1048 }
1049 return valid;
1050}
1051
1052void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) {
1053#if DEBUG_FOCUS
1054 LOGD("setFocusedApplication");
1055#endif
1056 { // acquire lock
1057 AutoMutex _l(mDispatchLock);
1058
1059 releaseFocusedApplicationLd(env);
1060
1061 if (applicationObj) {
1062 jstring nameObj = jstring(env->GetObjectField(applicationObj,
1063 gInputApplicationClassInfo.name));
1064 jlong dispatchingTimeoutNanos = env->GetLongField(applicationObj,
1065 gInputApplicationClassInfo.dispatchingTimeoutNanos);
1066 jobject tokenObj = env->GetObjectField(applicationObj,
1067 gInputApplicationClassInfo.token);
1068 jweak tokenObjWeak = env->NewWeakGlobalRef(tokenObj);
1069 if (! tokenObjWeak) {
1070 LOGE("Could not create weak reference for application token.");
1071 LOGE_EX(env);
1072 env->ExceptionClear();
1073 }
1074 env->DeleteLocalRef(tokenObj);
1075
1076 mFocusedApplication = & mFocusedApplicationStorage;
1077
1078 if (nameObj) {
1079 const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
1080 mFocusedApplication->name.setTo(nameStr);
1081 env->ReleaseStringUTFChars(nameObj, nameStr);
1082 env->DeleteLocalRef(nameObj);
1083 } else {
1084 LOGE("InputApplication.name should not be null.");
1085 mFocusedApplication->name.setTo("unknown");
1086 }
1087
1088 mFocusedApplication->dispatchingTimeout = dispatchingTimeoutNanos;
1089 mFocusedApplication->tokenObjWeak = tokenObjWeak;
1090 }
1091
1092 mDispatchStateChanged.broadcast();
1093
1094#if DEBUG_FOCUS
1095 dumpDispatchStateLd();
1096#endif
1097 } // release lock
1098}
1099
1100void NativeInputManager::releaseFocusedApplicationLd(JNIEnv* env) {
1101 if (mFocusedApplication) {
1102 env->DeleteWeakGlobalRef(mFocusedApplication->tokenObjWeak);
1103 mFocusedApplication = NULL;
1104 }
1105}
1106
1107void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
1108#if DEBUG_FOCUS
1109 LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001110#endif
1111
Jeff Brown349703e2010-06-22 01:27:15 -07001112 { // acquire lock
1113 AutoMutex _l(mDispatchLock);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001114
Jeff Brown349703e2010-06-22 01:27:15 -07001115 if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
1116 mDispatchEnabled = enabled;
1117 mDispatchFrozen = frozen;
1118
1119 mDispatchStateChanged.broadcast();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001120 }
Jeff Brown349703e2010-06-22 01:27:15 -07001121
1122#if DEBUG_FOCUS
1123 dumpDispatchStateLd();
1124#endif
1125 } // release lock
1126}
1127
1128void NativeInputManager::preemptInputDispatch() {
1129#if DEBUG_FOCUS
1130 LOGD("preemptInputDispatch");
1131#endif
1132
1133 mInputManager->preemptInputDispatch();
1134}
1135
1136int32_t NativeInputManager::waitForFocusedWindowLd(uint32_t policyFlags,
1137 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
1138 InputWindow*& outFocusedWindow) {
1139
1140 int32_t injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1141 bool firstIteration = true;
1142 ANRTimer anrTimer;
1143 for (;;) {
1144 if (firstIteration) {
1145 firstIteration = false;
1146 } else {
1147 if (! anrTimer.waitForDispatchStateChangeLd(this)) {
1148 LOGW("Dropping event because the dispatcher timed out waiting to identify "
1149 "the window that should receive it.");
1150 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1151 break;
1152 }
1153 }
1154
1155 // If dispatch is not enabled then fail.
1156 if (! mDispatchEnabled) {
1157 LOGI("Dropping event because input dispatch is disabled.");
1158 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1159 break;
1160 }
1161
1162 // If dispatch is frozen or we don't have valid window data yet then wait.
1163 if (mDispatchFrozen || ! mWindowsReady) {
1164#if DEBUG_FOCUS
1165 LOGD("Waiting because dispatch is frozen or windows are not ready.");
1166#endif
1167 anrTimer.dispatchFrozenBySystem();
1168 continue;
1169 }
1170
1171 // If there is no currently focused window and no focused application
1172 // then drop the event.
1173 if (! mFocusedWindow) {
1174 if (mFocusedApplication) {
1175#if DEBUG_FOCUS
1176 LOGD("Waiting because there is no focused window but there is a "
1177 "focused application that may yet introduce a new target: '%s'.",
1178 mFocusedApplication->name.string());
1179#endif
1180 continue;
1181 }
1182
1183 LOGI("Dropping event because there is no focused window or focused application.");
1184 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1185 break;
1186 }
1187
1188 // Check permissions.
1189 if (! checkInjectionPermission(mFocusedWindow, injectorPid, injectorUid)) {
1190 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1191 break;
1192 }
1193
1194 // If the currently focused window is paused then keep waiting.
1195 if (mFocusedWindow->paused) {
1196#if DEBUG_FOCUS
1197 LOGD("Waiting because focused window is paused.");
1198#endif
1199 anrTimer.dispatchPausedByApplication(mFocusedWindow);
1200 continue;
1201 }
1202
1203 // Success!
1204 break; // done waiting, exit loop
Jeff Brown9c3cda02010-06-15 01:31:58 -07001205 }
Jeff Brown349703e2010-06-22 01:27:15 -07001206
1207 // Output targets.
1208 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
1209 addTarget(mFocusedWindow, InputTarget::FLAG_SYNC,
1210 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
1211
1212 outFocusedWindow = mFocusedWindow;
1213 } else {
1214 outFocusedWindow = NULL;
1215 }
1216
1217#if DEBUG_FOCUS
1218 LOGD("waitForFocusedWindow finished: injectionResult=%d",
1219 injectionResult);
1220 dumpDispatchStateLd();
1221#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001222 return injectionResult;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001223}
1224
Jeff Brown349703e2010-06-22 01:27:15 -07001225int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
1226 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
1227 InputWindow*& outTouchedWindow) {
1228 nsecs_t startTime = now();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001229
Jeff Brown349703e2010-06-22 01:27:15 -07001230 int32_t injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1231 int32_t action = motionEvent->getAction();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001232
Jeff Brown349703e2010-06-22 01:27:15 -07001233 // For security reasons, we defer updating the touch state until we are sure that
1234 // event injection will be allowed.
1235 //
1236 // FIXME In the original code, screenWasOff could never be set to true.
1237 // The reason is that the POLICY_FLAG_WOKE_HERE
1238 // and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
1239 // EV_KEY, EV_REL and EV_ABS events. As it happens, the touch event was
1240 // actually enqueued using the policyFlags that appeared in the final EV_SYN
1241 // events upon which no preprocessing took place. So policyFlags was always 0.
1242 // In the new native input dispatcher we're a bit more careful about event
1243 // preprocessing so the touches we receive can actually have non-zero policyFlags.
1244 // Unfortunately we obtain undesirable behavior.
1245 //
1246 // Here's what happens:
1247 //
1248 // When the device dims in anticipation of going to sleep, touches
1249 // in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
1250 // the device to brighten and reset the user activity timer.
1251 // Touches on other windows (such as the launcher window)
1252 // are dropped. Then after a moment, the device goes to sleep. Oops.
1253 //
1254 // Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
1255 // instead of POLICY_FLAG_WOKE_HERE...
1256 //
1257 bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
1258 bool firstIteration = true;
1259 ANRTimer anrTimer;
1260 for (;;) {
1261 if (firstIteration) {
1262 firstIteration = false;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001263 } else {
Jeff Brown349703e2010-06-22 01:27:15 -07001264 if (! anrTimer.waitForDispatchStateChangeLd(this)) {
1265 LOGW("Dropping event because the dispatcher timed out waiting to identify "
1266 "the window that should receive it.");
1267 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1268 break;
1269 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001270 }
Jeff Brown349703e2010-06-22 01:27:15 -07001271
1272 // If dispatch is not enabled then fail.
1273 if (! mDispatchEnabled) {
1274 LOGI("Dropping event because input dispatch is disabled.");
1275 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1276 break; // failed, exit wait loop
1277 }
1278
1279 // If dispatch is frozen or we don't have valid window data yet then wait.
1280 if (mDispatchFrozen || ! mWindowsReady) {
1281#if DEBUG_INPUT_DISPATCHER_POLICY
1282 LOGD("Waiting because dispatch is frozen or windows are not ready.");
1283#endif
1284 anrTimer.dispatchFrozenBySystem();
1285 continue;
1286 }
1287
1288 // Update the touch state as needed based on the properties of the touch event.
1289 if (action == MOTION_EVENT_ACTION_DOWN) {
1290 InputWindow* newTouchedWindow = NULL;
1291 mTempTouchedOutsideWindows.clear();
1292
1293 int32_t x = int32_t(motionEvent->getX(0));
1294 int32_t y = int32_t(motionEvent->getY(0));
1295 InputWindow* topErrorWindow = NULL;
1296
1297 // Traverse windows from front to back to find touched window and outside targets.
1298 size_t numWindows = mWindows.size();
1299 for (size_t i = 0; i < numWindows; i++) {
1300 InputWindow* window = & mWindows.editItemAt(i);
1301 int32_t flags = window->layoutParamsFlags;
1302
1303 if (flags & FLAG_SYSTEM_ERROR) {
1304 if (! topErrorWindow) {
1305 topErrorWindow = window;
1306 }
1307 }
1308
1309 if (window->visible) {
1310 if (! (flags & FLAG_NOT_TOUCHABLE)) {
1311 bool isTouchModal = (flags &
1312 (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL)) == 0;
1313 if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
1314 if (! screenWasOff || flags & FLAG_TOUCHABLE_WHEN_WAKING) {
1315 newTouchedWindow = window;
1316 }
1317 break; // found touched window, exit window loop
1318 }
1319 }
1320
1321 if (flags & FLAG_WATCH_OUTSIDE_TOUCH) {
1322 mTempTouchedOutsideWindows.push(window);
1323 }
1324 }
1325 }
1326
1327 // If there is an error window but it is not taking focus (typically because
1328 // it is invisible) then wait for it. Any other focused window may in
1329 // fact be in ANR state.
1330 if (topErrorWindow && newTouchedWindow != topErrorWindow) {
1331#if DEBUG_INPUT_DISPATCHER_POLICY
1332 LOGD("Waiting because system error window is pending.");
1333#endif
1334 anrTimer.dispatchFrozenBySystem();
1335 continue; // wait some more
1336 }
1337
1338 // If we did not find a touched window then fail.
1339 if (! newTouchedWindow) {
1340 if (mFocusedApplication) {
1341#if DEBUG_FOCUS
1342 LOGD("Waiting because there is no focused window but there is a "
1343 "focused application that may yet introduce a new target: '%s'.",
1344 mFocusedApplication->name.string());
1345#endif
1346 continue;
1347 }
1348
1349 LOGI("Dropping event because there is no touched window or focused application.");
1350 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1351 break; // failed, exit wait loop
1352 }
1353
1354 // Check permissions.
1355 if (! checkInjectionPermission(newTouchedWindow, injectorPid, injectorUid)) {
1356 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1357 break; // failed, exit wait loop
1358 }
1359
1360 // If the touched window is paused then keep waiting.
1361 if (newTouchedWindow->paused) {
1362#if DEBUG_INPUT_DISPATCHER_POLICY
1363 LOGD("Waiting because touched window is paused.");
1364#endif
1365 anrTimer.dispatchPausedByApplication(newTouchedWindow);
1366 continue; // wait some more
1367 }
1368
1369 // Success! Update the touch dispatch state for real.
1370 releaseTouchedWindowLd();
1371
1372 mTouchedWindow = newTouchedWindow;
1373
1374 if (newTouchedWindow->hasWallpaper) {
1375 mTouchedWallpaperWindows.appendVector(mWallpaperWindows);
1376 }
1377 break; // done
1378 } else {
1379 // Check permissions.
1380 if (! checkInjectionPermission(mTouchedWindow, injectorPid, injectorUid)) {
1381 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1382 break; // failed, exit wait loop
1383 }
1384
1385 // If there is no currently touched window then fail.
1386 if (! mTouchedWindow || ! mTouchDown) {
1387 LOGI("Dropping event because touched window is no longer valid.");
1388 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1389 break; // failed, exit wait loop
1390 }
1391
1392 // If the touched window is paused then keep waiting.
1393 if (mTouchedWindow->paused) {
1394#if DEBUG_INPUT_DISPATCHER_POLICY
1395 LOGD("Waiting because touched window is paused.");
1396#endif
1397 anrTimer.dispatchPausedByApplication(mTouchedWindow);
1398 continue; // wait some more
1399 }
1400
1401 // Success!
1402 break; // done
1403 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001404 }
Jeff Brown349703e2010-06-22 01:27:15 -07001405
1406 // Output targets.
1407 bool havePermission;
1408 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
1409 // Injection succeeded so the injector must have permission.
1410 havePermission = true;
1411
1412 size_t numWallpaperWindows = mTouchedWallpaperWindows.size();
1413 for (size_t i = 0; i < numWallpaperWindows; i++) {
1414 addTarget(mTouchedWallpaperWindows[i], 0, 0, outTargets);
1415 }
1416
1417 size_t numOutsideWindows = mTempTouchedOutsideWindows.size();
1418 for (size_t i = 0; i < numOutsideWindows; i++) {
1419 addTarget(mTempTouchedOutsideWindows[i], InputTarget::FLAG_OUTSIDE, 0, outTargets);
1420 }
1421
1422 addTarget(mTouchedWindow, InputTarget::FLAG_SYNC,
1423 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
1424 outTouchedWindow = mTouchedWindow;
1425 } else {
1426 if (injectionResult != INPUT_EVENT_INJECTION_PERMISSION_DENIED
1427 && checkInjectionPermission(NULL, injectorPid, injectorUid)) {
1428 // Injection failed but the injector does have permission to inject events.
1429 // While we might not have found a valid target for the injected event, we
1430 // still want to update the dispatch state to take it into account.
1431 havePermission = true;
1432 } else {
1433 // Injector does not have permission to inject events.
1434 // We make sure to leave the dispatch state unchanged.
1435 havePermission = false;
1436 }
1437 outTouchedWindow = NULL;
1438 }
1439 mTempTouchedOutsideWindows.clear();
1440
1441 // Update final pieces of touch state now that we know for sure whether the injector
1442 // had permission to perform the injection.
1443 if (havePermission) {
1444 if (action == MOTION_EVENT_ACTION_DOWN) {
1445 if (mTouchDown) {
1446 // This is weird. We got a down but we thought it was already down!
1447 LOGW("Pointer down received while already down.");
1448 } else {
1449 mTouchDown = true;
1450 }
1451
1452 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1453 // Since we failed to identify a target for this touch down, we may still
1454 // be holding on to an earlier target from a previous touch down. Release it.
1455 releaseTouchedWindowLd();
1456 }
1457 } else if (action == MOTION_EVENT_ACTION_UP) {
1458 mTouchDown = false;
1459 releaseTouchedWindowLd();
1460 }
1461 }
1462
1463#if DEBUG_FOCUS
1464 LOGD("waitForTouchedWindow finished: injectionResult=%d",
1465 injectionResult);
1466 dumpDispatchStateLd();
1467#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001468 return injectionResult;
1469}
1470
Jeff Brown349703e2010-06-22 01:27:15 -07001471void NativeInputManager::releaseTouchedWindowLd() {
1472 mTouchedWindow = NULL;
1473 mTouchedWallpaperWindows.clear();
1474}
1475
1476void NativeInputManager::addTarget(const InputWindow* window, int32_t targetFlags,
1477 nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets) {
1478 nsecs_t timeout = window->dispatchingTimeout - timeSpentWaitingForApplication;
1479 if (timeout < MIN_INPUT_DISPATCHING_TIMEOUT) {
1480 timeout = MIN_INPUT_DISPATCHING_TIMEOUT;
1481 }
1482
1483 outTargets.push();
1484
1485 InputTarget& target = outTargets.editTop();
1486 target.inputChannel = window->inputChannel;
1487 target.flags = targetFlags;
1488 target.timeout = timeout;
1489 target.xOffset = - window->frameLeft;
1490 target.yOffset = - window->frameTop;
1491}
1492
1493bool NativeInputManager::checkInjectionPermission(const InputWindow* window,
1494 int32_t injectorPid, int32_t injectorUid) {
1495 if (injectorUid > 0 && (window == NULL || window->ownerUid != injectorUid)) {
1496 JNIEnv* env = jniEnv();
1497 jboolean result = env->CallBooleanMethod(mCallbacksObj,
1498 gCallbacksClassInfo.checkInjectEventsPermission, injectorPid, injectorUid);
1499 checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission");
1500
1501 if (! result) {
1502 if (window) {
1503 LOGW("Permission denied: injecting event from pid %d uid %d to window "
1504 "with input channel %s owned by uid %d",
1505 injectorPid, injectorUid, window->inputChannel->getName().string(),
1506 window->ownerUid);
1507 } else {
1508 LOGW("Permission denied: injecting event from pid %d uid %d",
1509 injectorPid, injectorUid);
1510 }
1511 return false;
1512 }
1513 }
1514
1515 return true;
1516}
1517
1518int32_t NativeInputManager::waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
1519 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets) {
1520#if DEBUG_INPUT_DISPATCHER_POLICY
1521 LOGD("waitForKeyEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1522 policyFlags, injectorPid, injectorUid);
1523#endif
1524
1525 int32_t windowType;
1526 { // acquire lock
1527 AutoMutex _l(mDispatchLock);
1528
1529 InputWindow* focusedWindow;
1530 int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
1531 injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
1532 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1533 return injectionResult;
1534 }
1535
1536 windowType = focusedWindow->layoutParamsType;
1537 } // release lock
1538
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001539 if (isPolicyKey(keyEvent->getKeyCode(), isScreenOn())) {
1540 const InputTarget& target = outTargets.top();
1541 bool consumed = interceptKeyBeforeDispatching(target, keyEvent, policyFlags);
1542 if (consumed) {
1543 outTargets.clear();
1544 return INPUT_EVENT_INJECTION_SUCCEEDED;
1545 }
Jeff Brown349703e2010-06-22 01:27:15 -07001546 }
1547
1548 pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
1549 return INPUT_EVENT_INJECTION_SUCCEEDED;
1550}
1551
1552int32_t NativeInputManager::waitForMotionEventTargets(MotionEvent* motionEvent,
1553 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001554 Vector<InputTarget>& outTargets) {
Jeff Brown349703e2010-06-22 01:27:15 -07001555#if DEBUG_INPUT_DISPATCHER_POLICY
1556 LOGD("waitForMotionEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1557 policyFlags, injectorPid, injectorUid);
1558#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001559
Jeff Brown349703e2010-06-22 01:27:15 -07001560 switch (motionEvent->getNature()) {
1561 case INPUT_EVENT_NATURE_TRACKBALL:
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001562 return waitForTrackballEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
Jeff Brown349703e2010-06-22 01:27:15 -07001563 outTargets);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001564
Jeff Brown349703e2010-06-22 01:27:15 -07001565 case INPUT_EVENT_NATURE_TOUCH:
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001566 return waitForTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
Jeff Brown349703e2010-06-22 01:27:15 -07001567 outTargets);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001568
Jeff Brown349703e2010-06-22 01:27:15 -07001569 default:
1570 assert(false);
1571 return INPUT_EVENT_INJECTION_FAILED;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001572 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001573}
1574
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001575int32_t NativeInputManager::waitForTrackballEventTargets(MotionEvent* motionEvent,
Jeff Brown349703e2010-06-22 01:27:15 -07001576 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
1577 Vector<InputTarget>& outTargets) {
1578#if DEBUG_INPUT_DISPATCHER_POLICY
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001579 LOGD("waitForTrackballEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
Jeff Brown349703e2010-06-22 01:27:15 -07001580 policyFlags, injectorPid, injectorUid);
1581#endif
1582
1583 int32_t windowType;
1584 { // acquire lock
1585 AutoMutex _l(mDispatchLock);
1586
1587 InputWindow* focusedWindow;
1588 int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
1589 injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
1590 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1591 return injectionResult;
1592 }
1593
1594 windowType = focusedWindow->layoutParamsType;
1595 } // release lock
1596
1597 pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
1598 return INPUT_EVENT_INJECTION_SUCCEEDED;
1599}
1600
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001601int32_t NativeInputManager::waitForTouchEventTargets(MotionEvent* motionEvent,
Jeff Brown349703e2010-06-22 01:27:15 -07001602 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
1603 Vector<InputTarget>& outTargets) {
1604#if DEBUG_INPUT_DISPATCHER_POLICY
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001605 LOGD("waitForTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
Jeff Brown349703e2010-06-22 01:27:15 -07001606 policyFlags, injectorPid, injectorUid);
1607#endif
1608
1609 int32_t windowType;
1610 { // acquire lock
1611 AutoMutex _l(mDispatchLock);
1612
1613 InputWindow* touchedWindow;
1614 int32_t injectionResult = waitForTouchedWindowLd(motionEvent, policyFlags,
1615 injectorPid, injectorUid, outTargets, /*out*/ touchedWindow);
1616 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1617 return injectionResult;
1618 }
1619
1620 windowType = touchedWindow->layoutParamsType;
1621 } // release lock
1622
1623 int32_t eventType;
1624 switch (motionEvent->getAction()) {
1625 case MOTION_EVENT_ACTION_DOWN:
1626 eventType = POWER_MANAGER_TOUCH_EVENT;
1627 break;
1628 case MOTION_EVENT_ACTION_UP:
1629 eventType = POWER_MANAGER_TOUCH_UP_EVENT;
1630 break;
1631 default:
1632 if (motionEvent->getEventTime() - motionEvent->getDownTime()
1633 >= EVENT_IGNORE_DURATION) {
1634 eventType = POWER_MANAGER_TOUCH_EVENT;
1635 } else {
1636 eventType = POWER_MANAGER_LONG_TOUCH_EVENT;
1637 }
1638 break;
1639 }
1640 pokeUserActivityIfNeeded(windowType, eventType);
1641 return INPUT_EVENT_INJECTION_SUCCEEDED;
1642}
1643
Jeff Brownd0097872010-06-30 14:41:59 -07001644bool NativeInputManager::interceptKeyBeforeDispatching(const InputTarget& target,
1645 const KeyEvent* keyEvent, uint32_t policyFlags) {
1646 JNIEnv* env = jniEnv();
1647
1648 jobject inputChannelObj = getInputChannelObjLocal(env, target.inputChannel);
1649 if (inputChannelObj) {
1650 jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
1651 gCallbacksClassInfo.interceptKeyBeforeDispatching,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001652 inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(),
1653 keyEvent->getKeyCode(), keyEvent->getMetaState(),
Jeff Brownd0097872010-06-30 14:41:59 -07001654 keyEvent->getRepeatCount(), policyFlags);
1655 bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
1656
1657 env->DeleteLocalRef(inputChannelObj);
1658
1659 return consumed && ! error;
1660 } else {
1661 LOGW("Could not apply key dispatch policy because input channel '%s' is "
1662 "no longer valid.", target.inputChannel->getName().string());
1663 return false;
1664 }
1665}
1666
Jeff Brown349703e2010-06-22 01:27:15 -07001667void NativeInputManager::pokeUserActivityIfNeeded(int32_t windowType, int32_t eventType) {
1668 if (windowType != TYPE_KEYGUARD) {
1669 nsecs_t eventTime = now();
1670 pokeUserActivity(eventTime, eventType);
1671 }
1672}
1673
1674void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001675 android_server_PowerManagerService_userActivity(eventTime, eventType);
Jeff Brown349703e2010-06-22 01:27:15 -07001676}
1677
1678void NativeInputManager::dumpDispatchStateLd() {
1679#if DEBUG_FOCUS
1680 LOGD(" dispatcherState: dispatchEnabled=%d, dispatchFrozen=%d, windowsReady=%d",
1681 mDispatchEnabled, mDispatchFrozen, mWindowsReady);
1682 if (mFocusedApplication) {
1683 LOGD(" focusedApplication: name='%s', dispatchingTimeout=%0.3fms",
1684 mFocusedApplication->name.string(),
1685 mFocusedApplication->dispatchingTimeout / 1000000.0);
1686 } else {
1687 LOGD(" focusedApplication: <null>");
1688 }
1689 LOGD(" focusedWindow: '%s'",
1690 mFocusedWindow != NULL ? mFocusedWindow->inputChannel->getName().string() : "<null>");
1691 LOGD(" touchedWindow: '%s', touchDown=%d",
1692 mTouchedWindow != NULL ? mTouchedWindow->inputChannel->getName().string() : "<null>",
1693 mTouchDown);
1694 for (size_t i = 0; i < mTouchedWallpaperWindows.size(); i++) {
1695 LOGD(" touchedWallpaperWindows[%d]: '%s'",
1696 i, mTouchedWallpaperWindows[i]->inputChannel->getName().string());
1697 }
1698 for (size_t i = 0; i < mWindows.size(); i++) {
1699 LOGD(" windows[%d]: '%s', paused=%d, hasFocus=%d, hasWallpaper=%d, visible=%d, "
1700 "flags=0x%08x, type=0x%08x, "
1701 "frame=[%d,%d], touchableArea=[%d,%d][%d,%d], "
1702 "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms",
1703 i, mWindows[i].inputChannel->getName().string(),
1704 mWindows[i].paused, mWindows[i].hasFocus, mWindows[i].hasWallpaper,
1705 mWindows[i].visible, mWindows[i].layoutParamsFlags, mWindows[i].layoutParamsType,
1706 mWindows[i].frameLeft, mWindows[i].frameTop,
1707 mWindows[i].touchableAreaLeft, mWindows[i].touchableAreaTop,
1708 mWindows[i].touchableAreaRight, mWindows[i].touchableAreaBottom,
1709 mWindows[i].ownerPid, mWindows[i].ownerUid,
1710 mWindows[i].dispatchingTimeout / 1000000.0);
1711 }
1712#endif
1713}
1714
1715// ----------------------------------------------------------------------------
1716
1717NativeInputManager::ANRTimer::ANRTimer() :
1718 mBudget(APPLICATION), mStartTime(now()), mFrozen(false), mPausedWindow(NULL) {
1719}
1720
1721void NativeInputManager::ANRTimer::dispatchFrozenBySystem() {
1722 mFrozen = true;
1723}
1724
1725void NativeInputManager::ANRTimer::dispatchPausedByApplication(InputWindow* pausedWindow) {
1726 mPausedWindow = pausedWindow;
1727}
1728
1729bool NativeInputManager::ANRTimer::waitForDispatchStateChangeLd(NativeInputManager* inputManager) {
1730 nsecs_t currentTime = now();
1731
1732 Budget newBudget;
1733 nsecs_t dispatchingTimeout;
1734 sp<InputChannel> pausedChannel = NULL;
1735 jobject tokenObj = NULL;
1736 if (mFrozen) {
1737 newBudget = SYSTEM;
1738 dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
1739 mFrozen = false;
1740 } else if (mPausedWindow) {
1741 newBudget = APPLICATION;
1742 dispatchingTimeout = mPausedWindow->dispatchingTimeout;
1743 pausedChannel = mPausedWindow->inputChannel;
1744 mPausedWindow = NULL;
1745 } else if (inputManager->mFocusedApplication) {
1746 newBudget = APPLICATION;
1747 dispatchingTimeout = inputManager->mFocusedApplication->dispatchingTimeout;
1748 tokenObj = jniEnv()->NewLocalRef(inputManager->mFocusedApplication->tokenObjWeak);
1749 } else {
1750 newBudget = APPLICATION;
1751 dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
1752 }
1753
1754 if (mBudget != newBudget) {
1755 mBudget = newBudget;
1756 mStartTime = currentTime;
1757 }
1758
1759 bool result = false;
1760 nsecs_t timeoutRemaining = mStartTime + dispatchingTimeout - currentTime;
1761 if (timeoutRemaining > 0
1762 && inputManager->mDispatchStateChanged.waitRelative(inputManager->mDispatchLock,
1763 timeoutRemaining) == OK) {
1764 result = true;
1765 } else {
1766 if (pausedChannel != NULL || tokenObj != NULL) {
1767 bool resumed;
1768 nsecs_t newTimeout = 0;
1769
1770 inputManager->mDispatchLock.unlock(); // release lock
1771 if (pausedChannel != NULL) {
1772 resumed = inputManager->notifyInputChannelANR(pausedChannel, /*out*/ newTimeout);
1773 } else {
1774 resumed = inputManager->notifyANR(tokenObj, /*out*/ newTimeout);
1775 }
1776 inputManager->mDispatchLock.lock(); // re-acquire lock
1777
1778 if (resumed) {
1779 mStartTime = now() - dispatchingTimeout + newTimeout;
1780 result = true;
1781 }
1782 }
1783 }
1784
1785 if (tokenObj) {
1786 jniEnv()->DeleteLocalRef(tokenObj);
1787 }
1788
1789 return result;
1790}
1791
1792nsecs_t NativeInputManager::ANRTimer::getTimeSpentWaitingForApplication() const {
1793 return mBudget == APPLICATION ? now() - mStartTime : 0;
1794}
Jeff Brown9c3cda02010-06-15 01:31:58 -07001795
1796// ----------------------------------------------------------------------------
1797
1798static sp<NativeInputManager> gNativeInputManager;
1799
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001800static bool checkInputManagerUnitialized(JNIEnv* env) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001801 if (gNativeInputManager == NULL) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001802 LOGE("Input manager not initialized.");
1803 jniThrowRuntimeException(env, "Input manager not initialized.");
1804 return true;
1805 }
1806 return false;
1807}
1808
1809static void android_server_InputManager_nativeInit(JNIEnv* env, jclass clazz,
1810 jobject callbacks) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001811 if (gNativeInputManager == NULL) {
1812 gNativeInputManager = new NativeInputManager(callbacks);
1813 } else {
1814 LOGE("Input manager already initialized.");
1815 jniThrowRuntimeException(env, "Input manager already initialized.");
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001816 }
1817}
1818
1819static void android_server_InputManager_nativeStart(JNIEnv* env, jclass clazz) {
1820 if (checkInputManagerUnitialized(env)) {
1821 return;
1822 }
1823
Jeff Brown9c3cda02010-06-15 01:31:58 -07001824 status_t result = gNativeInputManager->getInputManager()->start();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001825 if (result) {
1826 jniThrowRuntimeException(env, "Input manager could not be started.");
1827 }
1828}
1829
1830static void android_server_InputManager_nativeSetDisplaySize(JNIEnv* env, jclass clazz,
1831 jint displayId, jint width, jint height) {
1832 if (checkInputManagerUnitialized(env)) {
1833 return;
1834 }
1835
1836 // XXX we could get this from the SurfaceFlinger directly instead of requiring it
1837 // to be passed in like this, not sure which is better but leaving it like this
1838 // keeps the window manager in direct control of when display transitions propagate down
1839 // to the input dispatcher
Jeff Brown9c3cda02010-06-15 01:31:58 -07001840 gNativeInputManager->setDisplaySize(displayId, width, height);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001841}
1842
1843static void android_server_InputManager_nativeSetDisplayOrientation(JNIEnv* env, jclass clazz,
1844 jint displayId, jint orientation) {
1845 if (checkInputManagerUnitialized(env)) {
1846 return;
1847 }
1848
Jeff Brown9c3cda02010-06-15 01:31:58 -07001849 gNativeInputManager->setDisplayOrientation(displayId, orientation);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001850}
1851
1852static jint android_server_InputManager_nativeGetScanCodeState(JNIEnv* env, jclass clazz,
1853 jint deviceId, jint deviceClasses, jint scanCode) {
1854 if (checkInputManagerUnitialized(env)) {
1855 return KEY_STATE_UNKNOWN;
1856 }
1857
Jeff Brown9c3cda02010-06-15 01:31:58 -07001858 return gNativeInputManager->getInputManager()->getScanCodeState(
1859 deviceId, deviceClasses, scanCode);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001860}
1861
1862static jint android_server_InputManager_nativeGetKeyCodeState(JNIEnv* env, jclass clazz,
1863 jint deviceId, jint deviceClasses, jint keyCode) {
1864 if (checkInputManagerUnitialized(env)) {
1865 return KEY_STATE_UNKNOWN;
1866 }
1867
Jeff Brown9c3cda02010-06-15 01:31:58 -07001868 return gNativeInputManager->getInputManager()->getKeyCodeState(
1869 deviceId, deviceClasses, keyCode);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001870}
1871
1872static jint android_server_InputManager_nativeGetSwitchState(JNIEnv* env, jclass clazz,
1873 jint deviceId, jint deviceClasses, jint sw) {
1874 if (checkInputManagerUnitialized(env)) {
1875 return KEY_STATE_UNKNOWN;
1876 }
1877
Jeff Brown9c3cda02010-06-15 01:31:58 -07001878 return gNativeInputManager->getInputManager()->getSwitchState(deviceId, deviceClasses, sw);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001879}
1880
1881static jboolean android_server_InputManager_nativeHasKeys(JNIEnv* env, jclass clazz,
1882 jintArray keyCodes, jbooleanArray outFlags) {
1883 if (checkInputManagerUnitialized(env)) {
1884 return JNI_FALSE;
1885 }
1886
1887 int32_t* codes = env->GetIntArrayElements(keyCodes, NULL);
1888 uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL);
1889 jsize numCodes = env->GetArrayLength(keyCodes);
1890 jboolean result;
1891 if (numCodes == env->GetArrayLength(outFlags)) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001892 result = gNativeInputManager->getInputManager()->hasKeys(numCodes, codes, flags);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001893 } else {
1894 result = JNI_FALSE;
1895 }
1896
1897 env->ReleaseBooleanArrayElements(outFlags, flags, 0);
1898 env->ReleaseIntArrayElements(keyCodes, codes, 0);
1899 return result;
1900}
1901
1902static void throwInputChannelNotInitialized(JNIEnv* env) {
1903 jniThrowException(env, "java/lang/IllegalStateException",
1904 "inputChannel is not initialized");
1905}
1906
1907static void android_server_InputManager_handleInputChannelDisposed(JNIEnv* env,
1908 jobject inputChannelObj, const sp<InputChannel>& inputChannel, void* data) {
1909 LOGW("Input channel object '%s' was disposed without first being unregistered with "
1910 "the input manager!", inputChannel->getName().string());
1911
Jeff Brown9c3cda02010-06-15 01:31:58 -07001912 if (gNativeInputManager != NULL) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001913 gNativeInputManager->unregisterInputChannel(env, inputChannel);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001914 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001915}
1916
1917static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
1918 jobject inputChannelObj) {
1919 if (checkInputManagerUnitialized(env)) {
1920 return;
1921 }
1922
1923 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
1924 inputChannelObj);
1925 if (inputChannel == NULL) {
1926 throwInputChannelNotInitialized(env);
1927 return;
1928 }
1929
Jeff Brown7fbdc842010-06-17 20:52:56 -07001930
1931 status_t status = gNativeInputManager->registerInputChannel(
1932 env, inputChannel, inputChannelObj);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001933 if (status) {
1934 jniThrowRuntimeException(env, "Failed to register input channel. "
1935 "Check logs for details.");
1936 return;
1937 }
1938
1939 android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
1940 android_server_InputManager_handleInputChannelDisposed, NULL);
1941}
1942
1943static void android_server_InputManager_nativeUnregisterInputChannel(JNIEnv* env, jclass clazz,
1944 jobject inputChannelObj) {
1945 if (checkInputManagerUnitialized(env)) {
1946 return;
1947 }
1948
1949 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
1950 inputChannelObj);
1951 if (inputChannel == NULL) {
1952 throwInputChannelNotInitialized(env);
1953 return;
1954 }
1955
1956 android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL);
1957
Jeff Brown7fbdc842010-06-17 20:52:56 -07001958 status_t status = gNativeInputManager->unregisterInputChannel(env, inputChannel);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001959 if (status) {
1960 jniThrowRuntimeException(env, "Failed to unregister input channel. "
1961 "Check logs for details.");
1962 }
1963}
1964
Jeff Brown7fbdc842010-06-17 20:52:56 -07001965static jint android_server_InputManager_nativeInjectKeyEvent(JNIEnv* env, jclass clazz,
1966 jobject keyEventObj, jint nature, jint injectorPid, jint injectorUid,
1967 jboolean sync, jint timeoutMillis) {
1968 if (checkInputManagerUnitialized(env)) {
1969 return INPUT_EVENT_INJECTION_FAILED;
1970 }
1971
1972 KeyEvent keyEvent;
1973 android_view_KeyEvent_toNative(env, keyEventObj, nature, & keyEvent);
1974
1975 return gNativeInputManager->getInputManager()->injectInputEvent(& keyEvent,
1976 injectorPid, injectorUid, sync, timeoutMillis);
1977}
1978
1979static jint android_server_InputManager_nativeInjectMotionEvent(JNIEnv* env, jclass clazz,
1980 jobject motionEventObj, jint nature, jint injectorPid, jint injectorUid,
1981 jboolean sync, jint timeoutMillis) {
1982 if (checkInputManagerUnitialized(env)) {
1983 return INPUT_EVENT_INJECTION_FAILED;
1984 }
1985
1986 MotionEvent motionEvent;
1987 android_view_MotionEvent_toNative(env, motionEventObj, nature, & motionEvent);
1988
1989 return gNativeInputManager->getInputManager()->injectInputEvent(& motionEvent,
1990 injectorPid, injectorUid, sync, timeoutMillis);
1991}
1992
Jeff Brown349703e2010-06-22 01:27:15 -07001993static void android_server_InputManager_nativeSetInputWindows(JNIEnv* env, jclass clazz,
1994 jobjectArray windowObjArray) {
1995 if (checkInputManagerUnitialized(env)) {
1996 return;
1997 }
1998
1999 gNativeInputManager->setInputWindows(env, windowObjArray);
2000}
2001
2002static void android_server_InputManager_nativeSetFocusedApplication(JNIEnv* env, jclass clazz,
2003 jobject applicationObj) {
2004 if (checkInputManagerUnitialized(env)) {
2005 return;
2006 }
2007
2008 gNativeInputManager->setFocusedApplication(env, applicationObj);
2009}
2010
2011static void android_server_InputManager_nativeSetInputDispatchMode(JNIEnv* env,
2012 jclass clazz, jboolean enabled, jboolean frozen) {
2013 if (checkInputManagerUnitialized(env)) {
2014 return;
2015 }
2016
2017 gNativeInputManager->setInputDispatchMode(enabled, frozen);
2018}
2019
2020static void android_server_InputManager_nativePreemptInputDispatch(JNIEnv* env,
2021 jclass clazz) {
2022 if (checkInputManagerUnitialized(env)) {
2023 return;
2024 }
2025
2026 gNativeInputManager->preemptInputDispatch();
2027}
2028
Jeff Brown9c3cda02010-06-15 01:31:58 -07002029// ----------------------------------------------------------------------------
2030
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002031static JNINativeMethod gInputManagerMethods[] = {
2032 /* name, signature, funcPtr */
2033 { "nativeInit", "(Lcom/android/server/InputManager$Callbacks;)V",
2034 (void*) android_server_InputManager_nativeInit },
2035 { "nativeStart", "()V",
2036 (void*) android_server_InputManager_nativeStart },
2037 { "nativeSetDisplaySize", "(III)V",
2038 (void*) android_server_InputManager_nativeSetDisplaySize },
2039 { "nativeSetDisplayOrientation", "(II)V",
2040 (void*) android_server_InputManager_nativeSetDisplayOrientation },
2041 { "nativeGetScanCodeState", "(III)I",
2042 (void*) android_server_InputManager_nativeGetScanCodeState },
2043 { "nativeGetKeyCodeState", "(III)I",
2044 (void*) android_server_InputManager_nativeGetKeyCodeState },
2045 { "nativeGetSwitchState", "(III)I",
2046 (void*) android_server_InputManager_nativeGetSwitchState },
2047 { "nativeHasKeys", "([I[Z)Z",
2048 (void*) android_server_InputManager_nativeHasKeys },
2049 { "nativeRegisterInputChannel", "(Landroid/view/InputChannel;)V",
2050 (void*) android_server_InputManager_nativeRegisterInputChannel },
2051 { "nativeUnregisterInputChannel", "(Landroid/view/InputChannel;)V",
Jeff Brown7fbdc842010-06-17 20:52:56 -07002052 (void*) android_server_InputManager_nativeUnregisterInputChannel },
2053 { "nativeInjectKeyEvent", "(Landroid/view/KeyEvent;IIIZI)I",
2054 (void*) android_server_InputManager_nativeInjectKeyEvent },
2055 { "nativeInjectMotionEvent", "(Landroid/view/MotionEvent;IIIZI)I",
Jeff Brown349703e2010-06-22 01:27:15 -07002056 (void*) android_server_InputManager_nativeInjectMotionEvent },
2057 { "nativeSetInputWindows", "([Lcom/android/server/InputWindow;)V",
2058 (void*) android_server_InputManager_nativeSetInputWindows },
2059 { "nativeSetFocusedApplication", "(Lcom/android/server/InputApplication;)V",
2060 (void*) android_server_InputManager_nativeSetFocusedApplication },
2061 { "nativeSetInputDispatchMode", "(ZZ)V",
2062 (void*) android_server_InputManager_nativeSetInputDispatchMode },
2063 { "nativePreemptInputDispatch", "()V",
2064 (void*) android_server_InputManager_nativePreemptInputDispatch }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002065};
2066
2067#define FIND_CLASS(var, className) \
2068 var = env->FindClass(className); \
2069 LOG_FATAL_IF(! var, "Unable to find class " className); \
2070 var = jclass(env->NewGlobalRef(var));
2071
2072#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
2073 var = env->GetMethodID(clazz, methodName, methodDescriptor); \
2074 LOG_FATAL_IF(! var, "Unable to find method " methodName);
2075
2076#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
2077 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
2078 LOG_FATAL_IF(! var, "Unable to find field " fieldName);
2079
2080int register_android_server_InputManager(JNIEnv* env) {
2081 int res = jniRegisterNativeMethods(env, "com/android/server/InputManager",
2082 gInputManagerMethods, NELEM(gInputManagerMethods));
2083 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
2084
Jeff Brown9c3cda02010-06-15 01:31:58 -07002085 // Callbacks
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002086
2087 FIND_CLASS(gCallbacksClassInfo.clazz, "com/android/server/InputManager$Callbacks");
2088
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002089 GET_METHOD_ID(gCallbacksClassInfo.notifyConfigurationChanged, gCallbacksClassInfo.clazz,
2090 "notifyConfigurationChanged", "(JIII)V");
2091
2092 GET_METHOD_ID(gCallbacksClassInfo.notifyLidSwitchChanged, gCallbacksClassInfo.clazz,
2093 "notifyLidSwitchChanged", "(JZ)V");
2094
Jeff Brown7fbdc842010-06-17 20:52:56 -07002095 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelBroken, gCallbacksClassInfo.clazz,
2096 "notifyInputChannelBroken", "(Landroid/view/InputChannel;)V");
2097
2098 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelANR, gCallbacksClassInfo.clazz,
2099 "notifyInputChannelANR", "(Landroid/view/InputChannel;)J");
2100
2101 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelRecoveredFromANR, gCallbacksClassInfo.clazz,
2102 "notifyInputChannelRecoveredFromANR", "(Landroid/view/InputChannel;)V");
2103
Jeff Brown349703e2010-06-22 01:27:15 -07002104 GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
2105 "notifyANR", "(Ljava/lang/Object;)J");
2106
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002107 GET_METHOD_ID(gCallbacksClassInfo.virtualKeyDownFeedback, gCallbacksClassInfo.clazz,
2108 "virtualKeyDownFeedback", "()V");
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002109
Jeff Brown349703e2010-06-22 01:27:15 -07002110 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002111 "interceptKeyBeforeQueueing", "(JIZIZ)I");
Jeff Brown349703e2010-06-22 01:27:15 -07002112
2113 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002114 "interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIIIII)Z");
Jeff Brown349703e2010-06-22 01:27:15 -07002115
2116 GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,
2117 "checkInjectEventsPermission", "(II)Z");
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002118
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002119 GET_METHOD_ID(gCallbacksClassInfo.notifyAppSwitchComing, gCallbacksClassInfo.clazz,
2120 "notifyAppSwitchComing", "()V");
2121
2122 GET_METHOD_ID(gCallbacksClassInfo.filterTouchEvents, gCallbacksClassInfo.clazz,
2123 "filterTouchEvents", "()Z");
2124
2125 GET_METHOD_ID(gCallbacksClassInfo.filterJumpyTouchEvents, gCallbacksClassInfo.clazz,
2126 "filterJumpyTouchEvents", "()Z");
2127
2128 GET_METHOD_ID(gCallbacksClassInfo.getVirtualKeyDefinitions, gCallbacksClassInfo.clazz,
2129 "getVirtualKeyDefinitions",
2130 "(Ljava/lang/String;)[Lcom/android/server/InputManager$VirtualKeyDefinition;");
2131
2132 GET_METHOD_ID(gCallbacksClassInfo.getExcludedDeviceNames, gCallbacksClassInfo.clazz,
2133 "getExcludedDeviceNames", "()[Ljava/lang/String;");
2134
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002135 // VirtualKeyDefinition
2136
2137 FIND_CLASS(gVirtualKeyDefinitionClassInfo.clazz,
2138 "com/android/server/InputManager$VirtualKeyDefinition");
2139
2140 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.scanCode, gVirtualKeyDefinitionClassInfo.clazz,
2141 "scanCode", "I");
2142
2143 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerX, gVirtualKeyDefinitionClassInfo.clazz,
2144 "centerX", "I");
2145
2146 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerY, gVirtualKeyDefinitionClassInfo.clazz,
2147 "centerY", "I");
2148
2149 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.width, gVirtualKeyDefinitionClassInfo.clazz,
2150 "width", "I");
2151
2152 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.height, gVirtualKeyDefinitionClassInfo.clazz,
2153 "height", "I");
2154
Jeff Brown349703e2010-06-22 01:27:15 -07002155 // InputWindow
Jeff Brown7fbdc842010-06-17 20:52:56 -07002156
Jeff Brown349703e2010-06-22 01:27:15 -07002157 FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002158
Jeff Brown349703e2010-06-22 01:27:15 -07002159 GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
2160 "inputChannel", "Landroid/view/InputChannel;");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002161
Jeff Brown349703e2010-06-22 01:27:15 -07002162 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
2163 "layoutParamsFlags", "I");
2164
2165 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
2166 "layoutParamsType", "I");
2167
2168 GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
2169 "dispatchingTimeoutNanos", "J");
2170
2171 GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
2172 "frameLeft", "I");
2173
2174 GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
2175 "frameTop", "I");
2176
2177 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
2178 "touchableAreaLeft", "I");
2179
2180 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
2181 "touchableAreaTop", "I");
2182
2183 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
2184 "touchableAreaRight", "I");
2185
2186 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
2187 "touchableAreaBottom", "I");
2188
2189 GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
2190 "visible", "Z");
2191
2192 GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
2193 "hasFocus", "Z");
2194
2195 GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
2196 "hasWallpaper", "Z");
2197
2198 GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
2199 "paused", "Z");
2200
2201 GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
2202 "ownerPid", "I");
2203
2204 GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
2205 "ownerUid", "I");
2206
2207 // InputApplication
2208
2209 FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication");
2210
2211 GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
2212 "name", "Ljava/lang/String;");
2213
2214 GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
2215 gInputApplicationClassInfo.clazz,
2216 "dispatchingTimeoutNanos", "J");
2217
2218 GET_FIELD_ID(gInputApplicationClassInfo.token, gInputApplicationClassInfo.clazz,
2219 "token", "Ljava/lang/Object;");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002220
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002221 return 0;
2222}
2223
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002224} /* namespace android */