Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2010 The Android Open Source Project
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define LOG_TAG "InputManager-JNI"
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
//#define LOG_NDEBUG 0
|
|
|
|
|
|
|
|
// Log debug messages about InputReaderPolicy
|
2010-06-22 01:27:15 -07:00
|
|
|
#define DEBUG_INPUT_READER_POLICY 0
|
2010-06-15 01:31:58 -07:00
|
|
|
|
|
|
|
// Log debug messages about InputDispatcherPolicy
|
2010-06-22 01:27:15 -07:00
|
|
|
#define DEBUG_INPUT_DISPATCHER_POLICY 0
|
2010-06-15 01:31:58 -07:00
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
// Log debug messages about input focus tracking
|
|
|
|
#define DEBUG_FOCUS 0
|
2010-06-15 01:31:58 -07:00
|
|
|
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
#include "JNIHelp.h"
|
|
|
|
#include "jni.h"
|
2010-06-22 01:27:15 -07:00
|
|
|
#include <limits.h>
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
#include <android_runtime/AndroidRuntime.h>
|
2010-06-15 01:31:58 -07:00
|
|
|
#include <ui/InputReader.h>
|
|
|
|
#include <ui/InputDispatcher.h>
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
#include <ui/InputManager.h>
|
|
|
|
#include <ui/InputTransport.h>
|
|
|
|
#include <utils/Log.h>
|
|
|
|
#include <utils/threads.h>
|
|
|
|
#include "../../core/jni/android_view_KeyEvent.h"
|
|
|
|
#include "../../core/jni/android_view_MotionEvent.h"
|
|
|
|
#include "../../core/jni/android_view_InputChannel.h"
|
2010-07-02 15:37:36 -07:00
|
|
|
#include "com_android_server_PowerManagerService.h"
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
|
|
|
|
namespace android {
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
// Window flags from WindowManager.LayoutParams
|
|
|
|
enum {
|
|
|
|
FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
|
|
|
|
FLAG_DIM_BEHIND = 0x00000002,
|
|
|
|
FLAG_BLUR_BEHIND = 0x00000004,
|
|
|
|
FLAG_NOT_FOCUSABLE = 0x00000008,
|
|
|
|
FLAG_NOT_TOUCHABLE = 0x00000010,
|
|
|
|
FLAG_NOT_TOUCH_MODAL = 0x00000020,
|
|
|
|
FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
|
|
|
|
FLAG_KEEP_SCREEN_ON = 0x00000080,
|
|
|
|
FLAG_LAYOUT_IN_SCREEN = 0x00000100,
|
|
|
|
FLAG_LAYOUT_NO_LIMITS = 0x00000200,
|
|
|
|
FLAG_FULLSCREEN = 0x00000400,
|
|
|
|
FLAG_FORCE_NOT_FULLSCREEN = 0x00000800,
|
|
|
|
FLAG_DITHER = 0x00001000,
|
|
|
|
FLAG_SECURE = 0x00002000,
|
|
|
|
FLAG_SCALED = 0x00004000,
|
|
|
|
FLAG_IGNORE_CHEEK_PRESSES = 0x00008000,
|
|
|
|
FLAG_LAYOUT_INSET_DECOR = 0x00010000,
|
|
|
|
FLAG_ALT_FOCUSABLE_IM = 0x00020000,
|
|
|
|
FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
|
|
|
|
FLAG_SHOW_WHEN_LOCKED = 0x00080000,
|
|
|
|
FLAG_SHOW_WALLPAPER = 0x00100000,
|
|
|
|
FLAG_TURN_SCREEN_ON = 0x00200000,
|
|
|
|
FLAG_DISMISS_KEYGUARD = 0x00400000,
|
|
|
|
FLAG_IMMERSIVE = 0x00800000,
|
|
|
|
FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000,
|
|
|
|
FLAG_COMPATIBLE_WINDOW = 0x20000000,
|
|
|
|
FLAG_SYSTEM_ERROR = 0x40000000,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Window types from WindowManager.LayoutParams
|
|
|
|
enum {
|
|
|
|
FIRST_APPLICATION_WINDOW = 1,
|
|
|
|
TYPE_BASE_APPLICATION = 1,
|
|
|
|
TYPE_APPLICATION = 2,
|
|
|
|
TYPE_APPLICATION_STARTING = 3,
|
|
|
|
LAST_APPLICATION_WINDOW = 99,
|
|
|
|
FIRST_SUB_WINDOW = 1000,
|
|
|
|
TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW,
|
|
|
|
TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1,
|
|
|
|
TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2,
|
|
|
|
TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3,
|
|
|
|
TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4,
|
|
|
|
LAST_SUB_WINDOW = 1999,
|
|
|
|
FIRST_SYSTEM_WINDOW = 2000,
|
|
|
|
TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW,
|
|
|
|
TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1,
|
|
|
|
TYPE_PHONE = FIRST_SYSTEM_WINDOW+2,
|
|
|
|
TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3,
|
|
|
|
TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4,
|
|
|
|
TYPE_TOAST = FIRST_SYSTEM_WINDOW+5,
|
|
|
|
TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6,
|
|
|
|
TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7,
|
|
|
|
TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8,
|
|
|
|
TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9,
|
|
|
|
TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10,
|
|
|
|
TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11,
|
|
|
|
TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
|
|
|
|
TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13,
|
|
|
|
TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14,
|
|
|
|
LAST_SYSTEM_WINDOW = 2999,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Delay between reporting long touch events to the power manager.
|
|
|
|
const nsecs_t EVENT_IGNORE_DURATION = 300 * 1000000LL; // 300 ms
|
|
|
|
|
|
|
|
// Default input dispatching timeout if there is no focused application or paused window
|
|
|
|
// from which to determine an appropriate dispatching timeout.
|
|
|
|
const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
|
|
|
|
|
|
|
|
// Minimum amount of time to provide to the input dispatcher for delivery of an event
|
|
|
|
// regardless of how long the application window was paused.
|
|
|
|
const nsecs_t MIN_INPUT_DISPATCHING_TIMEOUT = 1000 * 1000000LL; // 1 sec
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
static struct {
|
|
|
|
jclass clazz;
|
|
|
|
|
|
|
|
jmethodID notifyConfigurationChanged;
|
|
|
|
jmethodID notifyLidSwitchChanged;
|
2010-06-17 20:52:56 -07:00
|
|
|
jmethodID notifyInputChannelBroken;
|
|
|
|
jmethodID notifyInputChannelANR;
|
|
|
|
jmethodID notifyInputChannelRecoveredFromANR;
|
2010-06-22 01:27:15 -07:00
|
|
|
jmethodID notifyANR;
|
2010-07-02 15:37:36 -07:00
|
|
|
jmethodID virtualKeyDownFeedback;
|
2010-06-22 01:27:15 -07:00
|
|
|
jmethodID interceptKeyBeforeQueueing;
|
|
|
|
jmethodID interceptKeyBeforeDispatching;
|
|
|
|
jmethodID checkInjectEventsPermission;
|
2010-06-15 01:31:58 -07:00
|
|
|
jmethodID notifyAppSwitchComing;
|
|
|
|
jmethodID filterTouchEvents;
|
|
|
|
jmethodID filterJumpyTouchEvents;
|
|
|
|
jmethodID getVirtualKeyDefinitions;
|
2010-08-30 03:02:23 -07:00
|
|
|
jmethodID getInputDeviceCalibration;
|
2010-06-15 01:31:58 -07:00
|
|
|
jmethodID getExcludedDeviceNames;
|
2010-08-18 15:51:08 -07:00
|
|
|
jmethodID getMaxEventsPerSecond;
|
2010-06-15 01:31:58 -07:00
|
|
|
} gCallbacksClassInfo;
|
|
|
|
|
|
|
|
static struct {
|
|
|
|
jclass clazz;
|
|
|
|
|
|
|
|
jfieldID scanCode;
|
|
|
|
jfieldID centerX;
|
|
|
|
jfieldID centerY;
|
|
|
|
jfieldID width;
|
|
|
|
jfieldID height;
|
|
|
|
} gVirtualKeyDefinitionClassInfo;
|
|
|
|
|
2010-08-30 03:02:23 -07:00
|
|
|
static struct {
|
|
|
|
jclass clazz;
|
|
|
|
|
|
|
|
jfieldID keys;
|
|
|
|
jfieldID values;
|
|
|
|
} gInputDeviceCalibrationClassInfo;
|
|
|
|
|
2010-06-17 20:52:56 -07:00
|
|
|
static struct {
|
|
|
|
jclass clazz;
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
jfieldID inputChannel;
|
|
|
|
jfieldID layoutParamsFlags;
|
|
|
|
jfieldID layoutParamsType;
|
|
|
|
jfieldID dispatchingTimeoutNanos;
|
|
|
|
jfieldID frameLeft;
|
|
|
|
jfieldID frameTop;
|
2010-09-01 17:01:00 -07:00
|
|
|
jfieldID frameRight;
|
|
|
|
jfieldID frameBottom;
|
|
|
|
jfieldID visibleFrameLeft;
|
|
|
|
jfieldID visibleFrameTop;
|
|
|
|
jfieldID visibleFrameRight;
|
|
|
|
jfieldID visibleFrameBottom;
|
2010-06-22 01:27:15 -07:00
|
|
|
jfieldID touchableAreaLeft;
|
|
|
|
jfieldID touchableAreaTop;
|
|
|
|
jfieldID touchableAreaRight;
|
|
|
|
jfieldID touchableAreaBottom;
|
|
|
|
jfieldID visible;
|
|
|
|
jfieldID hasFocus;
|
|
|
|
jfieldID hasWallpaper;
|
|
|
|
jfieldID paused;
|
|
|
|
jfieldID ownerPid;
|
|
|
|
jfieldID ownerUid;
|
|
|
|
} gInputWindowClassInfo;
|
|
|
|
|
|
|
|
static struct {
|
|
|
|
jclass clazz;
|
|
|
|
|
|
|
|
jfieldID name;
|
|
|
|
jfieldID dispatchingTimeoutNanos;
|
|
|
|
jfieldID token;
|
|
|
|
} gInputApplicationClassInfo;
|
|
|
|
|
2010-07-28 15:48:59 -07:00
|
|
|
static struct {
|
|
|
|
jclass clazz;
|
|
|
|
} gKeyEventClassInfo;
|
|
|
|
|
|
|
|
static struct {
|
|
|
|
jclass clazz;
|
|
|
|
} gMotionEventClassInfo;
|
|
|
|
|
2010-08-30 03:02:23 -07:00
|
|
|
static struct {
|
|
|
|
jclass clazz;
|
|
|
|
|
|
|
|
jmethodID ctor;
|
|
|
|
jmethodID addMotionRange;
|
|
|
|
|
|
|
|
jfieldID mId;
|
|
|
|
jfieldID mName;
|
|
|
|
jfieldID mSources;
|
|
|
|
jfieldID mKeyboardType;
|
|
|
|
jfieldID mMotionRanges;
|
|
|
|
} gInputDeviceClassInfo;
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
static inline nsecs_t now() {
|
|
|
|
return systemTime(SYSTEM_TIME_MONOTONIC);
|
|
|
|
}
|
2010-06-17 20:52:56 -07:00
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
class NativeInputManager : public virtual RefBase,
|
|
|
|
public virtual InputReaderPolicyInterface,
|
|
|
|
public virtual InputDispatcherPolicyInterface {
|
|
|
|
protected:
|
|
|
|
virtual ~NativeInputManager();
|
|
|
|
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
public:
|
2010-06-15 01:31:58 -07:00
|
|
|
NativeInputManager(jobject callbacksObj);
|
|
|
|
|
|
|
|
inline sp<InputManager> getInputManager() const { return mInputManager; }
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
|
2010-07-15 23:54:05 -07:00
|
|
|
String8 dump();
|
|
|
|
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
void setDisplaySize(int32_t displayId, int32_t width, int32_t height);
|
|
|
|
void setDisplayOrientation(int32_t displayId, int32_t orientation);
|
|
|
|
|
2010-06-17 20:52:56 -07:00
|
|
|
status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
|
2010-08-11 14:46:32 -07:00
|
|
|
jweak inputChannelObjWeak, bool monitor);
|
2010-06-17 20:52:56 -07:00
|
|
|
status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
void setInputWindows(JNIEnv* env, jobjectArray windowObjArray);
|
|
|
|
void setFocusedApplication(JNIEnv* env, jobject applicationObj);
|
|
|
|
void setInputDispatchMode(bool enabled, bool frozen);
|
|
|
|
void preemptInputDispatch();
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
/* --- InputReaderPolicyInterface implementation --- */
|
|
|
|
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
virtual bool getDisplayInfo(int32_t displayId,
|
|
|
|
int32_t* width, int32_t* height, int32_t* orientation);
|
2010-07-02 15:37:36 -07:00
|
|
|
virtual void virtualKeyDownFeedback();
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
virtual int32_t interceptKey(nsecs_t when, int32_t deviceId,
|
2010-07-23 21:28:06 -07:00
|
|
|
bool down, int32_t keyCode, int32_t scanCode, uint32_t& policyFlags);
|
|
|
|
virtual int32_t interceptSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
|
|
|
|
uint32_t& policyFlags);
|
|
|
|
virtual int32_t interceptGeneric(nsecs_t when, uint32_t& policyFlags);
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
virtual bool filterTouchEvents();
|
|
|
|
virtual bool filterJumpyTouchEvents();
|
|
|
|
virtual void getVirtualKeyDefinitions(const String8& deviceName,
|
2010-08-30 03:02:23 -07:00
|
|
|
Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions);
|
|
|
|
virtual void getInputDeviceCalibration(const String8& deviceName,
|
|
|
|
InputDeviceCalibration& outCalibration);
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames);
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
/* --- InputDispatcherPolicyInterface implementation --- */
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
virtual void notifyConfigurationChanged(nsecs_t when);
|
|
|
|
virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel);
|
2010-06-17 20:52:56 -07:00
|
|
|
virtual bool notifyInputChannelANR(const sp<InputChannel>& inputChannel,
|
|
|
|
nsecs_t& outNewTimeout);
|
2010-06-15 01:31:58 -07:00
|
|
|
virtual void notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel);
|
|
|
|
virtual nsecs_t getKeyRepeatTimeout();
|
2010-06-22 01:27:15 -07:00
|
|
|
virtual int32_t waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
|
2010-06-17 20:52:56 -07:00
|
|
|
int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
|
2010-06-22 01:27:15 -07:00
|
|
|
virtual int32_t waitForMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
|
2010-06-17 20:52:56 -07:00
|
|
|
int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
|
2010-08-18 15:51:08 -07:00
|
|
|
virtual int32_t getMaxEventsPerSecond();
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
|
|
|
|
private:
|
2010-06-22 01:27:15 -07:00
|
|
|
struct InputWindow {
|
|
|
|
sp<InputChannel> inputChannel;
|
|
|
|
int32_t layoutParamsFlags;
|
|
|
|
int32_t layoutParamsType;
|
|
|
|
nsecs_t dispatchingTimeout;
|
|
|
|
int32_t frameLeft;
|
|
|
|
int32_t frameTop;
|
2010-09-01 17:01:00 -07:00
|
|
|
int32_t frameRight;
|
|
|
|
int32_t frameBottom;
|
|
|
|
int32_t visibleFrameLeft;
|
|
|
|
int32_t visibleFrameTop;
|
|
|
|
int32_t visibleFrameRight;
|
|
|
|
int32_t visibleFrameBottom;
|
2010-06-22 01:27:15 -07:00
|
|
|
int32_t touchableAreaLeft;
|
|
|
|
int32_t touchableAreaTop;
|
|
|
|
int32_t touchableAreaRight;
|
|
|
|
int32_t touchableAreaBottom;
|
|
|
|
bool visible;
|
|
|
|
bool hasFocus;
|
|
|
|
bool hasWallpaper;
|
|
|
|
bool paused;
|
|
|
|
int32_t ownerPid;
|
|
|
|
int32_t ownerUid;
|
|
|
|
|
2010-09-01 17:01:00 -07:00
|
|
|
bool visibleFrameIntersects(const InputWindow* other) const;
|
|
|
|
bool touchableAreaContainsPoint(int32_t x, int32_t y) const;
|
2010-06-22 01:27:15 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
struct InputApplication {
|
|
|
|
String8 name;
|
|
|
|
nsecs_t dispatchingTimeout;
|
|
|
|
jweak tokenObjWeak;
|
|
|
|
};
|
|
|
|
|
|
|
|
class ANRTimer {
|
|
|
|
enum Budget {
|
|
|
|
SYSTEM = 0,
|
|
|
|
APPLICATION = 1
|
|
|
|
};
|
|
|
|
|
|
|
|
Budget mBudget;
|
|
|
|
nsecs_t mStartTime;
|
|
|
|
bool mFrozen;
|
|
|
|
InputWindow* mPausedWindow;
|
|
|
|
|
|
|
|
public:
|
|
|
|
ANRTimer();
|
|
|
|
|
|
|
|
void dispatchFrozenBySystem();
|
|
|
|
void dispatchPausedByApplication(InputWindow* pausedWindow);
|
|
|
|
bool waitForDispatchStateChangeLd(NativeInputManager* inputManager);
|
|
|
|
|
|
|
|
nsecs_t getTimeSpentWaitingForApplication() const;
|
|
|
|
};
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
sp<InputManager> mInputManager;
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
jobject mCallbacksObj;
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
// Cached filtering policies.
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
int32_t mFilterTouchEvents;
|
|
|
|
int32_t mFilterJumpyTouchEvents;
|
|
|
|
|
2010-08-18 15:51:08 -07:00
|
|
|
// Cached throttling policy.
|
|
|
|
int32_t mMaxEventsPerSecond;
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
// Cached display state. (lock mDisplayLock)
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
Mutex mDisplayLock;
|
|
|
|
int32_t mDisplayWidth, mDisplayHeight;
|
|
|
|
int32_t mDisplayOrientation;
|
|
|
|
|
2010-07-02 15:37:36 -07:00
|
|
|
// Power manager interactions.
|
2010-06-15 01:31:58 -07:00
|
|
|
bool isScreenOn();
|
|
|
|
bool isScreenBright();
|
|
|
|
|
2010-08-17 15:59:26 -07:00
|
|
|
// Weak references to all currently registered input channels by connection pointer.
|
2010-06-17 20:52:56 -07:00
|
|
|
Mutex mInputChannelRegistryLock;
|
2010-08-17 15:59:26 -07:00
|
|
|
KeyedVector<InputChannel*, jweak> mInputChannelObjWeakTable;
|
2010-06-17 20:52:56 -07:00
|
|
|
|
|
|
|
jobject getInputChannelObjLocal(JNIEnv* env, const sp<InputChannel>& inputChannel);
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
// Input target and focus tracking. (lock mDispatchLock)
|
|
|
|
Mutex mDispatchLock;
|
|
|
|
Condition mDispatchStateChanged;
|
|
|
|
|
|
|
|
bool mDispatchEnabled;
|
|
|
|
bool mDispatchFrozen;
|
|
|
|
bool mWindowsReady;
|
|
|
|
Vector<InputWindow> mWindows;
|
|
|
|
Vector<InputWindow*> mWallpaperWindows;
|
2010-08-11 14:46:32 -07:00
|
|
|
Vector<sp<InputChannel> > mMonitoringChannels;
|
2010-06-22 01:27:15 -07:00
|
|
|
|
|
|
|
// Focus tracking for keys, trackball, etc.
|
|
|
|
InputWindow* mFocusedWindow;
|
|
|
|
|
|
|
|
// Focus tracking for touch.
|
|
|
|
bool mTouchDown;
|
|
|
|
InputWindow* mTouchedWindow; // primary target for current down
|
2010-09-01 17:01:00 -07:00
|
|
|
bool mTouchedWindowIsObscured; // true if other windows may obscure the target
|
2010-06-22 01:27:15 -07:00
|
|
|
Vector<InputWindow*> mTouchedWallpaperWindows; // wallpaper targets
|
2010-09-01 17:01:00 -07:00
|
|
|
struct OutsideTarget {
|
|
|
|
InputWindow* window;
|
|
|
|
bool obscured;
|
|
|
|
};
|
|
|
|
Vector<OutsideTarget> mTempTouchedOutsideTargets; // temporary outside touch targets
|
2010-06-22 01:27:15 -07:00
|
|
|
Vector<sp<InputChannel> > mTempTouchedWallpaperChannels; // temporary wallpaper targets
|
|
|
|
|
|
|
|
// Focused application.
|
|
|
|
InputApplication* mFocusedApplication;
|
|
|
|
InputApplication mFocusedApplicationStorage; // preallocated storage for mFocusedApplication
|
|
|
|
|
2010-07-23 21:28:06 -07:00
|
|
|
void dumpDeviceInfo(String8& dump);
|
2010-07-15 23:54:05 -07:00
|
|
|
void dumpDispatchStateLd(String8& dump);
|
|
|
|
void logDispatchStateLd();
|
2010-06-22 01:27:15 -07:00
|
|
|
|
|
|
|
bool notifyANR(jobject tokenObj, nsecs_t& outNewTimeout);
|
|
|
|
void releaseFocusedApplicationLd(JNIEnv* env);
|
|
|
|
|
|
|
|
int32_t waitForFocusedWindowLd(uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
|
|
|
|
Vector<InputTarget>& outTargets, InputWindow*& outFocusedWindow);
|
|
|
|
int32_t waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
|
|
|
|
int32_t injectorPid, int32_t injectorUid,
|
|
|
|
Vector<InputTarget>& outTargets, InputWindow*& outTouchedWindow);
|
2010-09-01 17:01:00 -07:00
|
|
|
bool isWindowObscuredLocked(const InputWindow* window);
|
2010-06-22 01:27:15 -07:00
|
|
|
|
|
|
|
void releaseTouchedWindowLd();
|
|
|
|
|
2010-07-14 18:48:53 -07:00
|
|
|
int32_t waitForNonTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
|
2010-06-22 01:27:15 -07:00
|
|
|
int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
|
2010-07-02 15:37:36 -07:00
|
|
|
int32_t waitForTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
|
2010-06-22 01:27:15 -07:00
|
|
|
int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
|
|
|
|
|
2010-06-30 14:41:59 -07:00
|
|
|
bool interceptKeyBeforeDispatching(const InputTarget& target,
|
|
|
|
const KeyEvent* keyEvent, uint32_t policyFlags);
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
void pokeUserActivityIfNeeded(int32_t windowType, int32_t eventType);
|
|
|
|
void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
|
|
|
|
bool checkInjectionPermission(const InputWindow* window,
|
|
|
|
int32_t injectorPid, int32_t injectorUid);
|
|
|
|
|
|
|
|
static bool populateWindow(JNIEnv* env, jobject windowObj, InputWindow& outWindow);
|
|
|
|
static void addTarget(const InputWindow* window, int32_t targetFlags,
|
|
|
|
nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets);
|
|
|
|
|
2010-08-11 14:46:32 -07:00
|
|
|
void registerMonitoringChannel(const sp<InputChannel>& inputChannel);
|
|
|
|
void unregisterMonitoringChannel(const sp<InputChannel>& inputChannel);
|
|
|
|
void addMonitoringTargetsLd(Vector<InputTarget>& outTargets);
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
static inline JNIEnv* jniEnv() {
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
return AndroidRuntime::getJNIEnv();
|
|
|
|
}
|
2010-06-15 01:31:58 -07:00
|
|
|
|
|
|
|
static bool isAppSwitchKey(int32_t keyCode);
|
2010-07-02 15:37:36 -07:00
|
|
|
static bool isPolicyKey(int32_t keyCode, bool isScreenOn);
|
2010-06-17 20:52:56 -07:00
|
|
|
static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
};
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
// ----------------------------------------------------------------------------
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
NativeInputManager::NativeInputManager(jobject callbacksObj) :
|
|
|
|
mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1),
|
2010-08-18 15:51:08 -07:00
|
|
|
mMaxEventsPerSecond(-1),
|
2010-06-29 16:52:21 -07:00
|
|
|
mDisplayWidth(-1), mDisplayHeight(-1), mDisplayOrientation(ROTATION_0),
|
2010-06-22 01:27:15 -07:00
|
|
|
mDispatchEnabled(true), mDispatchFrozen(false), mWindowsReady(true),
|
|
|
|
mFocusedWindow(NULL), mTouchDown(false), mTouchedWindow(NULL),
|
|
|
|
mFocusedApplication(NULL) {
|
2010-06-15 01:31:58 -07:00
|
|
|
JNIEnv* env = jniEnv();
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
mCallbacksObj = env->NewGlobalRef(callbacksObj);
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
sp<EventHub> eventHub = new EventHub();
|
|
|
|
mInputManager = new InputManager(eventHub, this, this);
|
|
|
|
}
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
NativeInputManager::~NativeInputManager() {
|
|
|
|
JNIEnv* env = jniEnv();
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
env->DeleteGlobalRef(mCallbacksObj);
|
2010-06-22 01:27:15 -07:00
|
|
|
|
|
|
|
releaseFocusedApplicationLd(env);
|
2010-06-15 01:31:58 -07:00
|
|
|
}
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
|
2010-07-15 23:54:05 -07:00
|
|
|
String8 NativeInputManager::dump() {
|
|
|
|
String8 dump;
|
2010-07-16 15:01:56 -07:00
|
|
|
{ // acquire lock
|
|
|
|
AutoMutex _l(mDisplayLock);
|
2010-07-23 21:28:06 -07:00
|
|
|
dump.append("Native Input Dispatcher State:\n");
|
2010-07-16 15:01:56 -07:00
|
|
|
dumpDispatchStateLd(dump);
|
2010-07-23 21:28:06 -07:00
|
|
|
dump.append("\n");
|
2010-07-16 15:01:56 -07:00
|
|
|
} // release lock
|
2010-07-23 21:28:06 -07:00
|
|
|
|
|
|
|
dump.append("Input Devices:\n");
|
|
|
|
dumpDeviceInfo(dump);
|
|
|
|
|
2010-07-15 23:54:05 -07:00
|
|
|
return dump;
|
|
|
|
}
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
bool NativeInputManager::isAppSwitchKey(int32_t keyCode) {
|
2010-06-30 16:10:35 -07:00
|
|
|
return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL;
|
2010-06-15 01:31:58 -07:00
|
|
|
}
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
|
2010-07-02 15:37:36 -07:00
|
|
|
bool NativeInputManager::isPolicyKey(int32_t keyCode, bool isScreenOn) {
|
|
|
|
// Special keys that the WindowManagerPolicy might care about.
|
|
|
|
switch (keyCode) {
|
2010-06-30 16:10:35 -07:00
|
|
|
case AKEYCODE_VOLUME_UP:
|
|
|
|
case AKEYCODE_VOLUME_DOWN:
|
|
|
|
case AKEYCODE_ENDCALL:
|
|
|
|
case AKEYCODE_POWER:
|
|
|
|
case AKEYCODE_CALL:
|
|
|
|
case AKEYCODE_HOME:
|
|
|
|
case AKEYCODE_MENU:
|
|
|
|
case AKEYCODE_SEARCH:
|
2010-07-02 15:37:36 -07:00
|
|
|
// media keys
|
2010-06-30 16:10:35 -07:00
|
|
|
case AKEYCODE_HEADSETHOOK:
|
|
|
|
case AKEYCODE_MEDIA_PLAY_PAUSE:
|
|
|
|
case AKEYCODE_MEDIA_STOP:
|
|
|
|
case AKEYCODE_MEDIA_NEXT:
|
|
|
|
case AKEYCODE_MEDIA_PREVIOUS:
|
|
|
|
case AKEYCODE_MEDIA_REWIND:
|
|
|
|
case AKEYCODE_MEDIA_FAST_FORWARD:
|
2010-07-02 15:37:36 -07:00
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
// We need to pass all keys to the policy in the following cases:
|
|
|
|
// - screen is off
|
|
|
|
// - keyguard is visible
|
|
|
|
// - policy is performing key chording
|
|
|
|
//return ! isScreenOn || keyguardVisible || chording;
|
|
|
|
return true; // XXX stubbed out for now
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-17 20:52:56 -07:00
|
|
|
bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
|
2010-06-15 01:31:58 -07:00
|
|
|
if (env->ExceptionCheck()) {
|
|
|
|
LOGE("An exception was thrown by callback '%s'.", methodName);
|
|
|
|
LOGE_EX(env);
|
|
|
|
env->ExceptionClear();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height) {
|
|
|
|
if (displayId == 0) {
|
|
|
|
AutoMutex _l(mDisplayLock);
|
|
|
|
|
|
|
|
mDisplayWidth = width;
|
|
|
|
mDisplayHeight = height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeInputManager::setDisplayOrientation(int32_t displayId, int32_t orientation) {
|
|
|
|
if (displayId == 0) {
|
|
|
|
AutoMutex _l(mDisplayLock);
|
|
|
|
|
|
|
|
mDisplayOrientation = orientation;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-17 20:52:56 -07:00
|
|
|
status_t NativeInputManager::registerInputChannel(JNIEnv* env,
|
2010-08-11 14:46:32 -07:00
|
|
|
const sp<InputChannel>& inputChannel, jobject inputChannelObj, bool monitor) {
|
2010-06-17 20:52:56 -07:00
|
|
|
jweak inputChannelObjWeak = env->NewWeakGlobalRef(inputChannelObj);
|
|
|
|
if (! inputChannelObjWeak) {
|
|
|
|
LOGE("Could not create weak reference for input channel.");
|
|
|
|
LOGE_EX(env);
|
|
|
|
return NO_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t status;
|
|
|
|
{
|
|
|
|
AutoMutex _l(mInputChannelRegistryLock);
|
|
|
|
|
2010-08-17 15:59:26 -07:00
|
|
|
ssize_t index = mInputChannelObjWeakTable.indexOfKey(inputChannel.get());
|
2010-06-17 20:52:56 -07:00
|
|
|
if (index >= 0) {
|
|
|
|
LOGE("Input channel object '%s' has already been registered",
|
|
|
|
inputChannel->getName().string());
|
|
|
|
status = INVALID_OPERATION;
|
|
|
|
goto DeleteWeakRef;
|
|
|
|
}
|
|
|
|
|
2010-08-17 15:59:26 -07:00
|
|
|
mInputChannelObjWeakTable.add(inputChannel.get(), inputChannelObjWeak);
|
2010-06-17 20:52:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
status = mInputManager->registerInputChannel(inputChannel);
|
|
|
|
if (! status) {
|
2010-08-11 14:46:32 -07:00
|
|
|
// Success.
|
|
|
|
if (monitor) {
|
|
|
|
registerMonitoringChannel(inputChannel);
|
|
|
|
}
|
2010-06-17 20:52:56 -07:00
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
2010-08-11 14:46:32 -07:00
|
|
|
// Failed!
|
2010-06-17 20:52:56 -07:00
|
|
|
{
|
|
|
|
AutoMutex _l(mInputChannelRegistryLock);
|
2010-08-17 15:59:26 -07:00
|
|
|
mInputChannelObjWeakTable.removeItem(inputChannel.get());
|
2010-06-17 20:52:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
DeleteWeakRef:
|
|
|
|
env->DeleteWeakGlobalRef(inputChannelObjWeak);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t NativeInputManager::unregisterInputChannel(JNIEnv* env,
|
|
|
|
const sp<InputChannel>& inputChannel) {
|
|
|
|
jweak inputChannelObjWeak;
|
|
|
|
{
|
|
|
|
AutoMutex _l(mInputChannelRegistryLock);
|
|
|
|
|
2010-08-17 15:59:26 -07:00
|
|
|
ssize_t index = mInputChannelObjWeakTable.indexOfKey(inputChannel.get());
|
2010-06-17 20:52:56 -07:00
|
|
|
if (index < 0) {
|
|
|
|
LOGE("Input channel object '%s' is not currently registered",
|
|
|
|
inputChannel->getName().string());
|
|
|
|
return INVALID_OPERATION;
|
|
|
|
}
|
|
|
|
|
2010-08-17 15:59:26 -07:00
|
|
|
inputChannelObjWeak = mInputChannelObjWeakTable.valueAt(index);
|
|
|
|
mInputChannelObjWeakTable.removeItemsAt(index);
|
2010-06-17 20:52:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
env->DeleteWeakGlobalRef(inputChannelObjWeak);
|
|
|
|
|
2010-08-11 14:46:32 -07:00
|
|
|
unregisterMonitoringChannel(inputChannel);
|
|
|
|
|
2010-06-17 20:52:56 -07:00
|
|
|
return mInputManager->unregisterInputChannel(inputChannel);
|
|
|
|
}
|
|
|
|
|
|
|
|
jobject NativeInputManager::getInputChannelObjLocal(JNIEnv* env,
|
|
|
|
const sp<InputChannel>& inputChannel) {
|
|
|
|
{
|
|
|
|
AutoMutex _l(mInputChannelRegistryLock);
|
|
|
|
|
2010-08-17 15:59:26 -07:00
|
|
|
ssize_t index = mInputChannelObjWeakTable.indexOfKey(inputChannel.get());
|
2010-06-17 20:52:56 -07:00
|
|
|
if (index < 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-08-17 15:59:26 -07:00
|
|
|
jweak inputChannelObjWeak = mInputChannelObjWeakTable.valueAt(index);
|
2010-06-17 20:52:56 -07:00
|
|
|
return env->NewLocalRef(inputChannelObjWeak);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
bool NativeInputManager::getDisplayInfo(int32_t displayId,
|
|
|
|
int32_t* width, int32_t* height, int32_t* orientation) {
|
|
|
|
bool result = false;
|
|
|
|
if (displayId == 0) {
|
|
|
|
AutoMutex _l(mDisplayLock);
|
|
|
|
|
|
|
|
if (mDisplayWidth > 0) {
|
2010-07-23 21:28:06 -07:00
|
|
|
if (width) {
|
|
|
|
*width = mDisplayWidth;
|
|
|
|
}
|
|
|
|
if (height) {
|
|
|
|
*height = mDisplayHeight;
|
|
|
|
}
|
|
|
|
if (orientation) {
|
|
|
|
*orientation = mDisplayOrientation;
|
|
|
|
}
|
2010-06-15 01:31:58 -07:00
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeInputManager::isScreenOn() {
|
2010-07-02 15:37:36 -07:00
|
|
|
return android_server_PowerManagerService_isScreenOn();
|
2010-06-15 01:31:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeInputManager::isScreenBright() {
|
2010-07-02 15:37:36 -07:00
|
|
|
return android_server_PowerManagerService_isScreenBright();
|
2010-06-15 01:31:58 -07:00
|
|
|
}
|
|
|
|
|
2010-07-02 15:37:36 -07:00
|
|
|
void NativeInputManager::virtualKeyDownFeedback() {
|
2010-06-15 01:31:58 -07:00
|
|
|
#if DEBUG_INPUT_READER_POLICY
|
2010-07-02 15:37:36 -07:00
|
|
|
LOGD("virtualKeyDownFeedback");
|
2010-06-15 01:31:58 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
JNIEnv* env = jniEnv();
|
|
|
|
|
2010-07-02 15:37:36 -07:00
|
|
|
env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.virtualKeyDownFeedback);
|
|
|
|
checkAndClearExceptionFromCallback(env, "virtualKeyDownFeedback");
|
2010-06-15 01:31:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int32_t NativeInputManager::interceptKey(nsecs_t when,
|
2010-07-23 21:28:06 -07:00
|
|
|
int32_t deviceId, bool down, int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) {
|
2010-06-15 01:31:58 -07:00
|
|
|
#if DEBUG_INPUT_READER_POLICY
|
|
|
|
LOGD("interceptKey - when=%lld, deviceId=%d, down=%d, keyCode=%d, scanCode=%d, "
|
2010-06-22 01:27:15 -07:00
|
|
|
"policyFlags=0x%x",
|
2010-06-15 01:31:58 -07:00
|
|
|
when, deviceId, down, keyCode, scanCode, policyFlags);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
const int32_t WM_ACTION_PASS_TO_USER = 1;
|
|
|
|
const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2;
|
|
|
|
const int32_t WM_ACTION_GO_TO_SLEEP = 4;
|
|
|
|
|
|
|
|
bool isScreenOn = this->isScreenOn();
|
|
|
|
bool isScreenBright = this->isScreenBright();
|
|
|
|
|
2010-07-02 15:37:36 -07:00
|
|
|
jint wmActions = 0;
|
|
|
|
if (isPolicyKey(keyCode, isScreenOn)) {
|
|
|
|
JNIEnv* env = jniEnv();
|
|
|
|
|
|
|
|
wmActions = env->CallIntMethod(mCallbacksObj,
|
|
|
|
gCallbacksClassInfo.interceptKeyBeforeQueueing,
|
|
|
|
when, keyCode, down, policyFlags, isScreenOn);
|
|
|
|
if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
|
|
|
|
wmActions = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
wmActions = WM_ACTION_PASS_TO_USER;
|
2010-06-15 01:31:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
|
|
|
|
if (! isScreenOn) {
|
|
|
|
// Key presses and releases wake the device.
|
2010-07-23 21:28:06 -07:00
|
|
|
policyFlags |= POLICY_FLAG_WOKE_HERE;
|
2010-06-15 01:31:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (! isScreenBright) {
|
|
|
|
// Key presses and releases brighten the screen if dimmed.
|
2010-07-23 21:28:06 -07:00
|
|
|
policyFlags |= POLICY_FLAG_BRIGHT_HERE;
|
2010-06-15 01:31:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (wmActions & WM_ACTION_GO_TO_SLEEP) {
|
2010-07-02 15:37:36 -07:00
|
|
|
android_server_PowerManagerService_goToSleep(when);
|
2010-06-15 01:31:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
|
2010-06-22 01:27:15 -07:00
|
|
|
pokeUserActivity(when, POWER_MANAGER_BUTTON_EVENT);
|
2010-06-15 01:31:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (wmActions & WM_ACTION_PASS_TO_USER) {
|
|
|
|
actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
|
|
|
|
|
|
|
|
if (down && isAppSwitchKey(keyCode)) {
|
2010-07-02 15:37:36 -07:00
|
|
|
JNIEnv* env = jniEnv();
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyAppSwitchComing);
|
2010-06-17 20:52:56 -07:00
|
|
|
checkAndClearExceptionFromCallback(env, "notifyAppSwitchComing");
|
2010-06-15 01:31:58 -07:00
|
|
|
|
|
|
|
actions |= InputReaderPolicyInterface::ACTION_APP_SWITCH_COMING;
|
|
|
|
}
|
|
|
|
}
|
2010-06-22 01:27:15 -07:00
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
return actions;
|
|
|
|
}
|
|
|
|
|
2010-07-23 21:28:06 -07:00
|
|
|
int32_t NativeInputManager::interceptGeneric(nsecs_t when, uint32_t& policyFlags) {
|
2010-06-15 01:31:58 -07:00
|
|
|
#if DEBUG_INPUT_READER_POLICY
|
2010-07-23 21:28:06 -07:00
|
|
|
LOGD("interceptGeneric - when=%lld, policyFlags=0x%x", when, policyFlags);
|
2010-06-15 01:31:58 -07:00
|
|
|
#endif
|
|
|
|
|
2010-06-16 01:53:36 -07:00
|
|
|
int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
|
|
|
|
if (isScreenOn()) {
|
2010-07-23 21:28:06 -07:00
|
|
|
// Only dispatch events when the device is awake.
|
2010-06-22 01:27:15 -07:00
|
|
|
// Do not wake the device.
|
2010-06-16 01:53:36 -07:00
|
|
|
actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
|
2010-06-15 01:31:58 -07:00
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
if (! isScreenBright()) {
|
|
|
|
// Brighten the screen if dimmed.
|
2010-07-23 21:28:06 -07:00
|
|
|
policyFlags |= POLICY_FLAG_BRIGHT_HERE;
|
2010-06-22 01:27:15 -07:00
|
|
|
}
|
2010-06-15 01:31:58 -07:00
|
|
|
}
|
|
|
|
|
2010-06-16 01:53:36 -07:00
|
|
|
return actions;
|
2010-06-15 01:31:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int32_t NativeInputManager::interceptSwitch(nsecs_t when, int32_t switchCode,
|
2010-07-23 21:28:06 -07:00
|
|
|
int32_t switchValue, uint32_t& policyFlags) {
|
2010-06-15 01:31:58 -07:00
|
|
|
#if DEBUG_INPUT_READER_POLICY
|
2010-07-23 21:28:06 -07:00
|
|
|
LOGD("interceptSwitch - when=%lld, switchCode=%d, switchValue=%d, policyFlags=0x%x",
|
|
|
|
when, switchCode, switchValue, policyFlags);
|
2010-06-15 01:31:58 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
JNIEnv* env = jniEnv();
|
|
|
|
|
|
|
|
switch (switchCode) {
|
|
|
|
case SW_LID:
|
|
|
|
env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyLidSwitchChanged,
|
|
|
|
when, switchValue == 0);
|
2010-06-17 20:52:56 -07:00
|
|
|
checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
|
2010-06-15 01:31:58 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return InputReaderPolicyInterface::ACTION_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeInputManager::filterTouchEvents() {
|
|
|
|
if (mFilterTouchEvents < 0) {
|
|
|
|
JNIEnv* env = jniEnv();
|
|
|
|
|
|
|
|
jboolean result = env->CallBooleanMethod(mCallbacksObj,
|
|
|
|
gCallbacksClassInfo.filterTouchEvents);
|
2010-06-17 20:52:56 -07:00
|
|
|
if (checkAndClearExceptionFromCallback(env, "filterTouchEvents")) {
|
2010-06-15 01:31:58 -07:00
|
|
|
result = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
mFilterTouchEvents = result ? 1 : 0;
|
|
|
|
}
|
|
|
|
return mFilterTouchEvents;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeInputManager::filterJumpyTouchEvents() {
|
|
|
|
if (mFilterJumpyTouchEvents < 0) {
|
|
|
|
JNIEnv* env = jniEnv();
|
|
|
|
|
|
|
|
jboolean result = env->CallBooleanMethod(mCallbacksObj,
|
|
|
|
gCallbacksClassInfo.filterJumpyTouchEvents);
|
2010-06-17 20:52:56 -07:00
|
|
|
if (checkAndClearExceptionFromCallback(env, "filterJumpyTouchEvents")) {
|
2010-06-15 01:31:58 -07:00
|
|
|
result = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
mFilterJumpyTouchEvents = result ? 1 : 0;
|
|
|
|
}
|
|
|
|
return mFilterJumpyTouchEvents;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeInputManager::getVirtualKeyDefinitions(const String8& deviceName,
|
2010-08-30 03:02:23 -07:00
|
|
|
Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) {
|
|
|
|
outVirtualKeyDefinitions.clear();
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
JNIEnv* env = jniEnv();
|
|
|
|
|
|
|
|
jstring deviceNameStr = env->NewStringUTF(deviceName.string());
|
2010-06-17 20:52:56 -07:00
|
|
|
if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions")) {
|
2010-06-15 01:31:58 -07:00
|
|
|
jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
|
|
|
|
gCallbacksClassInfo.getVirtualKeyDefinitions, deviceNameStr));
|
2010-06-17 20:52:56 -07:00
|
|
|
if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions") && result) {
|
2010-06-15 01:31:58 -07:00
|
|
|
jsize length = env->GetArrayLength(result);
|
|
|
|
for (jsize i = 0; i < length; i++) {
|
|
|
|
jobject item = env->GetObjectArrayElement(result, i);
|
|
|
|
|
|
|
|
outVirtualKeyDefinitions.add();
|
|
|
|
outVirtualKeyDefinitions.editTop().scanCode =
|
|
|
|
int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.scanCode));
|
|
|
|
outVirtualKeyDefinitions.editTop().centerX =
|
|
|
|
int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerX));
|
|
|
|
outVirtualKeyDefinitions.editTop().centerY =
|
|
|
|
int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerY));
|
|
|
|
outVirtualKeyDefinitions.editTop().width =
|
|
|
|
int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.width));
|
|
|
|
outVirtualKeyDefinitions.editTop().height =
|
|
|
|
int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.height));
|
|
|
|
|
|
|
|
env->DeleteLocalRef(item);
|
|
|
|
}
|
|
|
|
env->DeleteLocalRef(result);
|
|
|
|
}
|
|
|
|
env->DeleteLocalRef(deviceNameStr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-30 03:02:23 -07:00
|
|
|
void NativeInputManager::getInputDeviceCalibration(const String8& deviceName,
|
|
|
|
InputDeviceCalibration& outCalibration) {
|
|
|
|
outCalibration.clear();
|
|
|
|
|
|
|
|
JNIEnv* env = jniEnv();
|
|
|
|
|
|
|
|
jstring deviceNameStr = env->NewStringUTF(deviceName.string());
|
|
|
|
if (! checkAndClearExceptionFromCallback(env, "getInputDeviceCalibration")) {
|
|
|
|
jobject result = env->CallObjectMethod(mCallbacksObj,
|
|
|
|
gCallbacksClassInfo.getInputDeviceCalibration, deviceNameStr);
|
|
|
|
if (! checkAndClearExceptionFromCallback(env, "getInputDeviceCalibration") && result) {
|
|
|
|
jobjectArray keys = jobjectArray(env->GetObjectField(result,
|
|
|
|
gInputDeviceCalibrationClassInfo.keys));
|
|
|
|
jobjectArray values = jobjectArray(env->GetObjectField(result,
|
|
|
|
gInputDeviceCalibrationClassInfo.values));
|
|
|
|
|
|
|
|
jsize length = env->GetArrayLength(keys);
|
|
|
|
for (jsize i = 0; i < length; i++) {
|
|
|
|
jstring keyStr = jstring(env->GetObjectArrayElement(keys, i));
|
|
|
|
jstring valueStr = jstring(env->GetObjectArrayElement(values, i));
|
|
|
|
|
|
|
|
const char* keyChars = env->GetStringUTFChars(keyStr, NULL);
|
|
|
|
String8 key(keyChars);
|
|
|
|
env->ReleaseStringUTFChars(keyStr, keyChars);
|
|
|
|
|
|
|
|
const char* valueChars = env->GetStringUTFChars(valueStr, NULL);
|
|
|
|
String8 value(valueChars);
|
|
|
|
env->ReleaseStringUTFChars(valueStr, valueChars);
|
|
|
|
|
|
|
|
outCalibration.addProperty(key, value);
|
|
|
|
|
|
|
|
env->DeleteLocalRef(keyStr);
|
|
|
|
env->DeleteLocalRef(valueStr);
|
|
|
|
}
|
|
|
|
env->DeleteLocalRef(keys);
|
|
|
|
env->DeleteLocalRef(values);
|
|
|
|
env->DeleteLocalRef(result);
|
|
|
|
}
|
|
|
|
env->DeleteLocalRef(deviceNameStr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
void NativeInputManager::getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
|
2010-08-30 03:02:23 -07:00
|
|
|
outExcludedDeviceNames.clear();
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
JNIEnv* env = jniEnv();
|
|
|
|
|
|
|
|
jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
|
|
|
|
gCallbacksClassInfo.getExcludedDeviceNames));
|
2010-06-17 20:52:56 -07:00
|
|
|
if (! checkAndClearExceptionFromCallback(env, "getExcludedDeviceNames") && result) {
|
2010-06-15 01:31:58 -07:00
|
|
|
jsize length = env->GetArrayLength(result);
|
|
|
|
for (jsize i = 0; i < length; i++) {
|
|
|
|
jstring item = jstring(env->GetObjectArrayElement(result, i));
|
|
|
|
|
|
|
|
const char* deviceNameChars = env->GetStringUTFChars(item, NULL);
|
|
|
|
outExcludedDeviceNames.add(String8(deviceNameChars));
|
|
|
|
env->ReleaseStringUTFChars(item, deviceNameChars);
|
|
|
|
|
|
|
|
env->DeleteLocalRef(item);
|
|
|
|
}
|
|
|
|
env->DeleteLocalRef(result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
|
|
|
|
#if DEBUG_INPUT_DISPATCHER_POLICY
|
|
|
|
LOGD("notifyConfigurationChanged - when=%lld", when);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
JNIEnv* env = jniEnv();
|
|
|
|
|
|
|
|
InputConfiguration config;
|
|
|
|
mInputManager->getInputConfiguration(& config);
|
|
|
|
|
|
|
|
env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyConfigurationChanged,
|
|
|
|
when, config.touchScreen, config.keyboard, config.navigation);
|
2010-06-17 20:52:56 -07:00
|
|
|
checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged");
|
2010-06-15 01:31:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void NativeInputManager::notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
|
|
|
|
#if DEBUG_INPUT_DISPATCHER_POLICY
|
|
|
|
LOGD("notifyInputChannelBroken - inputChannel='%s'", inputChannel->getName().string());
|
|
|
|
#endif
|
|
|
|
|
2010-06-17 20:52:56 -07:00
|
|
|
JNIEnv* env = jniEnv();
|
|
|
|
|
|
|
|
jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
|
|
|
|
if (inputChannelObjLocal) {
|
|
|
|
env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelBroken,
|
|
|
|
inputChannelObjLocal);
|
|
|
|
checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken");
|
|
|
|
|
|
|
|
env->DeleteLocalRef(inputChannelObjLocal);
|
|
|
|
}
|
2010-08-11 14:46:32 -07:00
|
|
|
|
|
|
|
unregisterMonitoringChannel(inputChannel);
|
2010-06-15 01:31:58 -07:00
|
|
|
}
|
|
|
|
|
2010-06-17 20:52:56 -07:00
|
|
|
bool NativeInputManager::notifyInputChannelANR(const sp<InputChannel>& inputChannel,
|
|
|
|
nsecs_t& outNewTimeout) {
|
2010-06-15 01:31:58 -07:00
|
|
|
#if DEBUG_INPUT_DISPATCHER_POLICY
|
|
|
|
LOGD("notifyInputChannelANR - inputChannel='%s'",
|
|
|
|
inputChannel->getName().string());
|
|
|
|
#endif
|
|
|
|
|
2010-06-17 20:52:56 -07:00
|
|
|
JNIEnv* env = jniEnv();
|
|
|
|
|
|
|
|
jlong newTimeout;
|
|
|
|
jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
|
|
|
|
if (inputChannelObjLocal) {
|
|
|
|
newTimeout = env->CallLongMethod(mCallbacksObj,
|
|
|
|
gCallbacksClassInfo.notifyInputChannelANR, inputChannelObjLocal);
|
|
|
|
if (checkAndClearExceptionFromCallback(env, "notifyInputChannelANR")) {
|
|
|
|
newTimeout = -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
env->DeleteLocalRef(inputChannelObjLocal);
|
|
|
|
} else {
|
|
|
|
newTimeout = -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newTimeout == -2) {
|
|
|
|
return false; // abort
|
|
|
|
}
|
|
|
|
|
|
|
|
outNewTimeout = newTimeout;
|
|
|
|
return true; // resume
|
2010-06-15 01:31:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void NativeInputManager::notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel) {
|
|
|
|
#if DEBUG_INPUT_DISPATCHER_POLICY
|
|
|
|
LOGD("notifyInputChannelRecoveredFromANR - inputChannel='%s'",
|
|
|
|
inputChannel->getName().string());
|
|
|
|
#endif
|
|
|
|
|
2010-06-17 20:52:56 -07:00
|
|
|
JNIEnv* env = jniEnv();
|
|
|
|
|
|
|
|
jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
|
|
|
|
if (inputChannelObjLocal) {
|
|
|
|
env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelRecoveredFromANR,
|
|
|
|
inputChannelObjLocal);
|
|
|
|
checkAndClearExceptionFromCallback(env, "notifyInputChannelRecoveredFromANR");
|
|
|
|
|
|
|
|
env->DeleteLocalRef(inputChannelObjLocal);
|
|
|
|
}
|
2010-06-15 01:31:58 -07:00
|
|
|
}
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
bool NativeInputManager::notifyANR(jobject tokenObj, nsecs_t& outNewTimeout) {
|
|
|
|
#if DEBUG_INPUT_DISPATCHER_POLICY
|
|
|
|
LOGD("notifyANR");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
JNIEnv* env = jniEnv();
|
|
|
|
|
|
|
|
jlong newTimeout = env->CallLongMethod(mCallbacksObj,
|
|
|
|
gCallbacksClassInfo.notifyANR, tokenObj);
|
|
|
|
if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
|
|
|
|
newTimeout = -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newTimeout == -2) {
|
|
|
|
return false; // abort
|
|
|
|
}
|
|
|
|
|
|
|
|
outNewTimeout = newTimeout;
|
|
|
|
return true; // resume
|
|
|
|
}
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
nsecs_t NativeInputManager::getKeyRepeatTimeout() {
|
|
|
|
if (! isScreenOn()) {
|
|
|
|
// Disable key repeat when the screen is off.
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
// TODO use ViewConfiguration.getLongPressTimeout()
|
|
|
|
return milliseconds_to_nanoseconds(500);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-18 15:51:08 -07:00
|
|
|
int32_t NativeInputManager::getMaxEventsPerSecond() {
|
|
|
|
if (mMaxEventsPerSecond < 0) {
|
|
|
|
JNIEnv* env = jniEnv();
|
|
|
|
|
|
|
|
jint result = env->CallIntMethod(mCallbacksObj,
|
|
|
|
gCallbacksClassInfo.getMaxEventsPerSecond);
|
|
|
|
if (checkAndClearExceptionFromCallback(env, "getMaxEventsPerSecond")) {
|
2010-08-18 17:48:53 -07:00
|
|
|
result = 60;
|
2010-08-18 15:51:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
mMaxEventsPerSecond = result;
|
|
|
|
}
|
|
|
|
return mMaxEventsPerSecond;
|
|
|
|
}
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArray) {
|
|
|
|
#if DEBUG_FOCUS
|
|
|
|
LOGD("setInputWindows");
|
2010-06-15 01:31:58 -07:00
|
|
|
#endif
|
2010-06-22 01:27:15 -07:00
|
|
|
{ // acquire lock
|
|
|
|
AutoMutex _l(mDispatchLock);
|
2010-06-15 01:31:58 -07:00
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
sp<InputChannel> touchedWindowChannel;
|
|
|
|
if (mTouchedWindow) {
|
|
|
|
touchedWindowChannel = mTouchedWindow->inputChannel;
|
|
|
|
mTouchedWindow = NULL;
|
|
|
|
}
|
|
|
|
size_t numTouchedWallpapers = mTouchedWallpaperWindows.size();
|
|
|
|
if (numTouchedWallpapers != 0) {
|
|
|
|
for (size_t i = 0; i < numTouchedWallpapers; i++) {
|
|
|
|
mTempTouchedWallpaperChannels.push(mTouchedWallpaperWindows[i]->inputChannel);
|
|
|
|
}
|
|
|
|
mTouchedWallpaperWindows.clear();
|
|
|
|
}
|
|
|
|
|
2010-07-15 23:54:05 -07:00
|
|
|
bool hadFocusedWindow = mFocusedWindow != NULL;
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
mWindows.clear();
|
|
|
|
mFocusedWindow = NULL;
|
|
|
|
mWallpaperWindows.clear();
|
|
|
|
|
|
|
|
if (windowObjArray) {
|
|
|
|
mWindowsReady = true;
|
|
|
|
|
|
|
|
jsize length = env->GetArrayLength(windowObjArray);
|
|
|
|
for (jsize i = 0; i < length; i++) {
|
|
|
|
jobject inputTargetObj = env->GetObjectArrayElement(windowObjArray, i);
|
|
|
|
if (! inputTargetObj) {
|
|
|
|
break; // found null element indicating end of used portion of the array
|
|
|
|
}
|
|
|
|
|
|
|
|
mWindows.push();
|
|
|
|
InputWindow& window = mWindows.editTop();
|
|
|
|
bool valid = populateWindow(env, inputTargetObj, window);
|
|
|
|
if (! valid) {
|
|
|
|
mWindows.pop();
|
|
|
|
}
|
|
|
|
|
|
|
|
env->DeleteLocalRef(inputTargetObj);
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t numWindows = mWindows.size();
|
|
|
|
for (size_t i = 0; i < numWindows; i++) {
|
|
|
|
InputWindow* window = & mWindows.editItemAt(i);
|
|
|
|
if (window->hasFocus) {
|
|
|
|
mFocusedWindow = window;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window->layoutParamsType == TYPE_WALLPAPER) {
|
|
|
|
mWallpaperWindows.push(window);
|
|
|
|
|
|
|
|
for (size_t j = 0; j < numTouchedWallpapers; j++) {
|
|
|
|
if (window->inputChannel == mTempTouchedWallpaperChannels[i]) {
|
|
|
|
mTouchedWallpaperWindows.push(window);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window->inputChannel == touchedWindowChannel) {
|
|
|
|
mTouchedWindow = window;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
mWindowsReady = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
mTempTouchedWallpaperChannels.clear();
|
|
|
|
|
2010-07-16 15:01:56 -07:00
|
|
|
if ((hadFocusedWindow && ! mFocusedWindow)
|
|
|
|
|| (mFocusedWindow && ! mFocusedWindow->visible)) {
|
2010-07-15 23:54:05 -07:00
|
|
|
preemptInputDispatch();
|
|
|
|
}
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
mDispatchStateChanged.broadcast();
|
|
|
|
|
|
|
|
#if DEBUG_FOCUS
|
2010-07-15 23:54:05 -07:00
|
|
|
logDispatchStateLd();
|
2010-06-22 01:27:15 -07:00
|
|
|
#endif
|
|
|
|
} // release lock
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj,
|
|
|
|
InputWindow& outWindow) {
|
|
|
|
bool valid = false;
|
|
|
|
|
|
|
|
jobject inputChannelObj = env->GetObjectField(windowObj,
|
|
|
|
gInputWindowClassInfo.inputChannel);
|
|
|
|
if (inputChannelObj) {
|
|
|
|
sp<InputChannel> inputChannel =
|
|
|
|
android_view_InputChannel_getInputChannel(env, inputChannelObj);
|
|
|
|
if (inputChannel != NULL) {
|
|
|
|
jint layoutParamsFlags = env->GetIntField(windowObj,
|
|
|
|
gInputWindowClassInfo.layoutParamsFlags);
|
|
|
|
jint layoutParamsType = env->GetIntField(windowObj,
|
|
|
|
gInputWindowClassInfo.layoutParamsType);
|
|
|
|
jlong dispatchingTimeoutNanos = env->GetLongField(windowObj,
|
|
|
|
gInputWindowClassInfo.dispatchingTimeoutNanos);
|
|
|
|
jint frameLeft = env->GetIntField(windowObj,
|
|
|
|
gInputWindowClassInfo.frameLeft);
|
|
|
|
jint frameTop = env->GetIntField(windowObj,
|
|
|
|
gInputWindowClassInfo.frameTop);
|
2010-09-01 17:01:00 -07:00
|
|
|
jint frameRight = env->GetIntField(windowObj,
|
|
|
|
gInputWindowClassInfo.frameRight);
|
|
|
|
jint frameBottom = env->GetIntField(windowObj,
|
|
|
|
gInputWindowClassInfo.frameBottom);
|
|
|
|
jint visibleFrameLeft = env->GetIntField(windowObj,
|
|
|
|
gInputWindowClassInfo.visibleFrameLeft);
|
|
|
|
jint visibleFrameTop = env->GetIntField(windowObj,
|
|
|
|
gInputWindowClassInfo.visibleFrameTop);
|
|
|
|
jint visibleFrameRight = env->GetIntField(windowObj,
|
|
|
|
gInputWindowClassInfo.visibleFrameRight);
|
|
|
|
jint visibleFrameBottom = env->GetIntField(windowObj,
|
|
|
|
gInputWindowClassInfo.visibleFrameBottom);
|
2010-06-22 01:27:15 -07:00
|
|
|
jint touchableAreaLeft = env->GetIntField(windowObj,
|
|
|
|
gInputWindowClassInfo.touchableAreaLeft);
|
|
|
|
jint touchableAreaTop = env->GetIntField(windowObj,
|
|
|
|
gInputWindowClassInfo.touchableAreaTop);
|
|
|
|
jint touchableAreaRight = env->GetIntField(windowObj,
|
|
|
|
gInputWindowClassInfo.touchableAreaRight);
|
|
|
|
jint touchableAreaBottom = env->GetIntField(windowObj,
|
|
|
|
gInputWindowClassInfo.touchableAreaBottom);
|
|
|
|
jboolean visible = env->GetBooleanField(windowObj,
|
|
|
|
gInputWindowClassInfo.visible);
|
|
|
|
jboolean hasFocus = env->GetBooleanField(windowObj,
|
|
|
|
gInputWindowClassInfo.hasFocus);
|
|
|
|
jboolean hasWallpaper = env->GetBooleanField(windowObj,
|
|
|
|
gInputWindowClassInfo.hasWallpaper);
|
|
|
|
jboolean paused = env->GetBooleanField(windowObj,
|
|
|
|
gInputWindowClassInfo.paused);
|
|
|
|
jint ownerPid = env->GetIntField(windowObj,
|
|
|
|
gInputWindowClassInfo.ownerPid);
|
|
|
|
jint ownerUid = env->GetIntField(windowObj,
|
|
|
|
gInputWindowClassInfo.ownerUid);
|
|
|
|
|
|
|
|
outWindow.inputChannel = inputChannel;
|
|
|
|
outWindow.layoutParamsFlags = layoutParamsFlags;
|
|
|
|
outWindow.layoutParamsType = layoutParamsType;
|
|
|
|
outWindow.dispatchingTimeout = dispatchingTimeoutNanos;
|
|
|
|
outWindow.frameLeft = frameLeft;
|
|
|
|
outWindow.frameTop = frameTop;
|
2010-09-01 17:01:00 -07:00
|
|
|
outWindow.frameRight = frameRight;
|
|
|
|
outWindow.frameBottom = frameBottom;
|
|
|
|
outWindow.visibleFrameLeft = visibleFrameLeft;
|
|
|
|
outWindow.visibleFrameTop = visibleFrameTop;
|
|
|
|
outWindow.visibleFrameRight = visibleFrameRight;
|
|
|
|
outWindow.visibleFrameBottom = visibleFrameBottom;
|
2010-06-22 01:27:15 -07:00
|
|
|
outWindow.touchableAreaLeft = touchableAreaLeft;
|
|
|
|
outWindow.touchableAreaTop = touchableAreaTop;
|
|
|
|
outWindow.touchableAreaRight = touchableAreaRight;
|
|
|
|
outWindow.touchableAreaBottom = touchableAreaBottom;
|
|
|
|
outWindow.visible = visible;
|
|
|
|
outWindow.hasFocus = hasFocus;
|
|
|
|
outWindow.hasWallpaper = hasWallpaper;
|
|
|
|
outWindow.paused = paused;
|
|
|
|
outWindow.ownerPid = ownerPid;
|
|
|
|
outWindow.ownerUid = ownerUid;
|
|
|
|
valid = true;
|
|
|
|
} else {
|
|
|
|
LOGW("Dropping input target because its input channel is not initialized.");
|
|
|
|
}
|
2010-06-15 01:31:58 -07:00
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
env->DeleteLocalRef(inputChannelObj);
|
2010-06-15 01:31:58 -07:00
|
|
|
} else {
|
2010-06-22 01:27:15 -07:00
|
|
|
LOGW("Dropping input target because the input channel object was null.");
|
|
|
|
}
|
|
|
|
return valid;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) {
|
|
|
|
#if DEBUG_FOCUS
|
|
|
|
LOGD("setFocusedApplication");
|
|
|
|
#endif
|
|
|
|
{ // acquire lock
|
|
|
|
AutoMutex _l(mDispatchLock);
|
|
|
|
|
|
|
|
releaseFocusedApplicationLd(env);
|
|
|
|
|
|
|
|
if (applicationObj) {
|
|
|
|
jstring nameObj = jstring(env->GetObjectField(applicationObj,
|
|
|
|
gInputApplicationClassInfo.name));
|
|
|
|
jlong dispatchingTimeoutNanos = env->GetLongField(applicationObj,
|
|
|
|
gInputApplicationClassInfo.dispatchingTimeoutNanos);
|
|
|
|
jobject tokenObj = env->GetObjectField(applicationObj,
|
|
|
|
gInputApplicationClassInfo.token);
|
|
|
|
jweak tokenObjWeak = env->NewWeakGlobalRef(tokenObj);
|
|
|
|
if (! tokenObjWeak) {
|
|
|
|
LOGE("Could not create weak reference for application token.");
|
|
|
|
LOGE_EX(env);
|
|
|
|
env->ExceptionClear();
|
|
|
|
}
|
|
|
|
env->DeleteLocalRef(tokenObj);
|
|
|
|
|
|
|
|
mFocusedApplication = & mFocusedApplicationStorage;
|
|
|
|
|
|
|
|
if (nameObj) {
|
|
|
|
const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
|
|
|
|
mFocusedApplication->name.setTo(nameStr);
|
|
|
|
env->ReleaseStringUTFChars(nameObj, nameStr);
|
|
|
|
env->DeleteLocalRef(nameObj);
|
|
|
|
} else {
|
|
|
|
LOGE("InputApplication.name should not be null.");
|
|
|
|
mFocusedApplication->name.setTo("unknown");
|
|
|
|
}
|
|
|
|
|
|
|
|
mFocusedApplication->dispatchingTimeout = dispatchingTimeoutNanos;
|
|
|
|
mFocusedApplication->tokenObjWeak = tokenObjWeak;
|
|
|
|
}
|
|
|
|
|
|
|
|
mDispatchStateChanged.broadcast();
|
|
|
|
|
|
|
|
#if DEBUG_FOCUS
|
2010-07-15 23:54:05 -07:00
|
|
|
logDispatchStateLd();
|
2010-06-22 01:27:15 -07:00
|
|
|
#endif
|
|
|
|
} // release lock
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeInputManager::releaseFocusedApplicationLd(JNIEnv* env) {
|
|
|
|
if (mFocusedApplication) {
|
|
|
|
env->DeleteWeakGlobalRef(mFocusedApplication->tokenObjWeak);
|
|
|
|
mFocusedApplication = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
|
|
|
|
#if DEBUG_FOCUS
|
|
|
|
LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
{ // acquire lock
|
|
|
|
AutoMutex _l(mDispatchLock);
|
|
|
|
|
|
|
|
if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
|
|
|
|
mDispatchEnabled = enabled;
|
|
|
|
mDispatchFrozen = frozen;
|
|
|
|
|
|
|
|
mDispatchStateChanged.broadcast();
|
|
|
|
}
|
|
|
|
|
|
|
|
#if DEBUG_FOCUS
|
2010-07-15 23:54:05 -07:00
|
|
|
logDispatchStateLd();
|
2010-06-22 01:27:15 -07:00
|
|
|
#endif
|
|
|
|
} // release lock
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeInputManager::preemptInputDispatch() {
|
|
|
|
#if DEBUG_FOCUS
|
|
|
|
LOGD("preemptInputDispatch");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
mInputManager->preemptInputDispatch();
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t NativeInputManager::waitForFocusedWindowLd(uint32_t policyFlags,
|
|
|
|
int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
|
|
|
|
InputWindow*& outFocusedWindow) {
|
|
|
|
|
|
|
|
int32_t injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
|
|
|
|
bool firstIteration = true;
|
|
|
|
ANRTimer anrTimer;
|
|
|
|
for (;;) {
|
|
|
|
if (firstIteration) {
|
|
|
|
firstIteration = false;
|
|
|
|
} else {
|
|
|
|
if (! anrTimer.waitForDispatchStateChangeLd(this)) {
|
|
|
|
LOGW("Dropping event because the dispatcher timed out waiting to identify "
|
|
|
|
"the window that should receive it.");
|
|
|
|
injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If dispatch is not enabled then fail.
|
|
|
|
if (! mDispatchEnabled) {
|
|
|
|
LOGI("Dropping event because input dispatch is disabled.");
|
2010-06-17 20:52:56 -07:00
|
|
|
injectionResult = INPUT_EVENT_INJECTION_FAILED;
|
2010-06-22 01:27:15 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If dispatch is frozen or we don't have valid window data yet then wait.
|
|
|
|
if (mDispatchFrozen || ! mWindowsReady) {
|
|
|
|
#if DEBUG_FOCUS
|
|
|
|
LOGD("Waiting because dispatch is frozen or windows are not ready.");
|
|
|
|
#endif
|
|
|
|
anrTimer.dispatchFrozenBySystem();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there is no currently focused window and no focused application
|
|
|
|
// then drop the event.
|
|
|
|
if (! mFocusedWindow) {
|
|
|
|
if (mFocusedApplication) {
|
|
|
|
#if DEBUG_FOCUS
|
|
|
|
LOGD("Waiting because there is no focused window but there is a "
|
|
|
|
"focused application that may yet introduce a new target: '%s'.",
|
|
|
|
mFocusedApplication->name.string());
|
|
|
|
#endif
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOGI("Dropping event because there is no focused window or focused application.");
|
|
|
|
injectionResult = INPUT_EVENT_INJECTION_FAILED;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check permissions.
|
|
|
|
if (! checkInjectionPermission(mFocusedWindow, injectorPid, injectorUid)) {
|
|
|
|
injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the currently focused window is paused then keep waiting.
|
|
|
|
if (mFocusedWindow->paused) {
|
|
|
|
#if DEBUG_FOCUS
|
|
|
|
LOGD("Waiting because focused window is paused.");
|
|
|
|
#endif
|
|
|
|
anrTimer.dispatchPausedByApplication(mFocusedWindow);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Success!
|
|
|
|
break; // done waiting, exit loop
|
|
|
|
}
|
|
|
|
|
|
|
|
// Output targets.
|
|
|
|
if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
|
|
|
|
addTarget(mFocusedWindow, InputTarget::FLAG_SYNC,
|
|
|
|
anrTimer.getTimeSpentWaitingForApplication(), outTargets);
|
|
|
|
|
|
|
|
outFocusedWindow = mFocusedWindow;
|
|
|
|
} else {
|
|
|
|
outFocusedWindow = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if DEBUG_FOCUS
|
|
|
|
LOGD("waitForFocusedWindow finished: injectionResult=%d",
|
|
|
|
injectionResult);
|
2010-07-15 23:54:05 -07:00
|
|
|
logDispatchStateLd();
|
2010-06-22 01:27:15 -07:00
|
|
|
#endif
|
|
|
|
return injectionResult;
|
|
|
|
}
|
|
|
|
|
2010-07-14 18:48:53 -07:00
|
|
|
enum InjectionPermission {
|
|
|
|
INJECTION_PERMISSION_UNKNOWN,
|
|
|
|
INJECTION_PERMISSION_GRANTED,
|
|
|
|
INJECTION_PERMISSION_DENIED
|
|
|
|
};
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
|
|
|
|
int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
|
|
|
|
InputWindow*& outTouchedWindow) {
|
|
|
|
nsecs_t startTime = now();
|
|
|
|
|
|
|
|
// For security reasons, we defer updating the touch state until we are sure that
|
|
|
|
// event injection will be allowed.
|
|
|
|
//
|
|
|
|
// FIXME In the original code, screenWasOff could never be set to true.
|
|
|
|
// The reason is that the POLICY_FLAG_WOKE_HERE
|
|
|
|
// and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
|
|
|
|
// EV_KEY, EV_REL and EV_ABS events. As it happens, the touch event was
|
|
|
|
// actually enqueued using the policyFlags that appeared in the final EV_SYN
|
|
|
|
// events upon which no preprocessing took place. So policyFlags was always 0.
|
|
|
|
// In the new native input dispatcher we're a bit more careful about event
|
|
|
|
// preprocessing so the touches we receive can actually have non-zero policyFlags.
|
|
|
|
// Unfortunately we obtain undesirable behavior.
|
|
|
|
//
|
|
|
|
// Here's what happens:
|
|
|
|
//
|
|
|
|
// When the device dims in anticipation of going to sleep, touches
|
|
|
|
// in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
|
|
|
|
// the device to brighten and reset the user activity timer.
|
|
|
|
// Touches on other windows (such as the launcher window)
|
|
|
|
// are dropped. Then after a moment, the device goes to sleep. Oops.
|
|
|
|
//
|
|
|
|
// Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
|
|
|
|
// instead of POLICY_FLAG_WOKE_HERE...
|
|
|
|
//
|
|
|
|
bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
|
2010-07-14 18:48:53 -07:00
|
|
|
|
|
|
|
int32_t action = motionEvent->getAction();
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
bool firstIteration = true;
|
|
|
|
ANRTimer anrTimer;
|
2010-07-14 18:48:53 -07:00
|
|
|
int32_t injectionResult;
|
|
|
|
InjectionPermission injectionPermission;
|
2010-06-22 01:27:15 -07:00
|
|
|
for (;;) {
|
|
|
|
if (firstIteration) {
|
|
|
|
firstIteration = false;
|
|
|
|
} else {
|
|
|
|
if (! anrTimer.waitForDispatchStateChangeLd(this)) {
|
|
|
|
LOGW("Dropping event because the dispatcher timed out waiting to identify "
|
|
|
|
"the window that should receive it.");
|
|
|
|
injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
|
2010-07-14 18:48:53 -07:00
|
|
|
injectionPermission = INJECTION_PERMISSION_UNKNOWN;
|
|
|
|
break; // timed out, exit wait loop
|
2010-06-22 01:27:15 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If dispatch is not enabled then fail.
|
|
|
|
if (! mDispatchEnabled) {
|
|
|
|
LOGI("Dropping event because input dispatch is disabled.");
|
|
|
|
injectionResult = INPUT_EVENT_INJECTION_FAILED;
|
2010-07-14 18:48:53 -07:00
|
|
|
injectionPermission = INJECTION_PERMISSION_UNKNOWN;
|
2010-06-22 01:27:15 -07:00
|
|
|
break; // failed, exit wait loop
|
|
|
|
}
|
|
|
|
|
|
|
|
// If dispatch is frozen or we don't have valid window data yet then wait.
|
|
|
|
if (mDispatchFrozen || ! mWindowsReady) {
|
|
|
|
#if DEBUG_INPUT_DISPATCHER_POLICY
|
|
|
|
LOGD("Waiting because dispatch is frozen or windows are not ready.");
|
|
|
|
#endif
|
|
|
|
anrTimer.dispatchFrozenBySystem();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the touch state as needed based on the properties of the touch event.
|
2010-07-14 18:48:53 -07:00
|
|
|
if (action == AMOTION_EVENT_ACTION_DOWN) {
|
|
|
|
/* Case 1: ACTION_DOWN */
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
InputWindow* newTouchedWindow = NULL;
|
2010-09-01 17:01:00 -07:00
|
|
|
mTempTouchedOutsideTargets.clear();
|
2010-06-22 01:27:15 -07:00
|
|
|
|
|
|
|
int32_t x = int32_t(motionEvent->getX(0));
|
|
|
|
int32_t y = int32_t(motionEvent->getY(0));
|
|
|
|
InputWindow* topErrorWindow = NULL;
|
2010-09-01 17:01:00 -07:00
|
|
|
bool obscured = false;
|
2010-06-22 01:27:15 -07:00
|
|
|
|
|
|
|
// Traverse windows from front to back to find touched window and outside targets.
|
|
|
|
size_t numWindows = mWindows.size();
|
|
|
|
for (size_t i = 0; i < numWindows; i++) {
|
|
|
|
InputWindow* window = & mWindows.editItemAt(i);
|
|
|
|
int32_t flags = window->layoutParamsFlags;
|
|
|
|
|
|
|
|
if (flags & FLAG_SYSTEM_ERROR) {
|
|
|
|
if (! topErrorWindow) {
|
|
|
|
topErrorWindow = window;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window->visible) {
|
|
|
|
if (! (flags & FLAG_NOT_TOUCHABLE)) {
|
|
|
|
bool isTouchModal = (flags &
|
|
|
|
(FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL)) == 0;
|
|
|
|
if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
|
|
|
|
if (! screenWasOff || flags & FLAG_TOUCHABLE_WHEN_WAKING) {
|
|
|
|
newTouchedWindow = window;
|
2010-09-01 17:01:00 -07:00
|
|
|
obscured = isWindowObscuredLocked(window);
|
2010-06-22 01:27:15 -07:00
|
|
|
}
|
|
|
|
break; // found touched window, exit window loop
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & FLAG_WATCH_OUTSIDE_TOUCH) {
|
2010-09-01 17:01:00 -07:00
|
|
|
OutsideTarget outsideTarget;
|
|
|
|
outsideTarget.window = window;
|
|
|
|
outsideTarget.obscured = isWindowObscuredLocked(window);
|
|
|
|
mTempTouchedOutsideTargets.push(outsideTarget);
|
2010-06-22 01:27:15 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there is an error window but it is not taking focus (typically because
|
|
|
|
// it is invisible) then wait for it. Any other focused window may in
|
|
|
|
// fact be in ANR state.
|
|
|
|
if (topErrorWindow && newTouchedWindow != topErrorWindow) {
|
|
|
|
#if DEBUG_INPUT_DISPATCHER_POLICY
|
|
|
|
LOGD("Waiting because system error window is pending.");
|
|
|
|
#endif
|
|
|
|
anrTimer.dispatchFrozenBySystem();
|
|
|
|
continue; // wait some more
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we did not find a touched window then fail.
|
|
|
|
if (! newTouchedWindow) {
|
|
|
|
if (mFocusedApplication) {
|
|
|
|
#if DEBUG_FOCUS
|
|
|
|
LOGD("Waiting because there is no focused window but there is a "
|
|
|
|
"focused application that may yet introduce a new target: '%s'.",
|
|
|
|
mFocusedApplication->name.string());
|
|
|
|
#endif
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOGI("Dropping event because there is no touched window or focused application.");
|
|
|
|
injectionResult = INPUT_EVENT_INJECTION_FAILED;
|
2010-07-14 18:48:53 -07:00
|
|
|
injectionPermission = INJECTION_PERMISSION_UNKNOWN;
|
2010-06-22 01:27:15 -07:00
|
|
|
break; // failed, exit wait loop
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check permissions.
|
|
|
|
if (! checkInjectionPermission(newTouchedWindow, injectorPid, injectorUid)) {
|
|
|
|
injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
|
2010-07-14 18:48:53 -07:00
|
|
|
injectionPermission = INJECTION_PERMISSION_DENIED;
|
2010-06-22 01:27:15 -07:00
|
|
|
break; // failed, exit wait loop
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the touched window is paused then keep waiting.
|
|
|
|
if (newTouchedWindow->paused) {
|
|
|
|
#if DEBUG_INPUT_DISPATCHER_POLICY
|
|
|
|
LOGD("Waiting because touched window is paused.");
|
|
|
|
#endif
|
|
|
|
anrTimer.dispatchPausedByApplication(newTouchedWindow);
|
|
|
|
continue; // wait some more
|
|
|
|
}
|
|
|
|
|
|
|
|
// Success! Update the touch dispatch state for real.
|
|
|
|
releaseTouchedWindowLd();
|
|
|
|
|
|
|
|
mTouchedWindow = newTouchedWindow;
|
2010-09-01 17:01:00 -07:00
|
|
|
mTouchedWindowIsObscured = obscured;
|
2010-06-22 01:27:15 -07:00
|
|
|
|
|
|
|
if (newTouchedWindow->hasWallpaper) {
|
|
|
|
mTouchedWallpaperWindows.appendVector(mWallpaperWindows);
|
|
|
|
}
|
2010-07-14 18:48:53 -07:00
|
|
|
|
|
|
|
injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
|
|
|
|
injectionPermission = INJECTION_PERMISSION_GRANTED;
|
2010-06-22 01:27:15 -07:00
|
|
|
break; // done
|
2010-06-17 20:52:56 -07:00
|
|
|
} else {
|
2010-07-14 18:48:53 -07:00
|
|
|
/* Case 2: Everything but ACTION_DOWN */
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
// Check permissions.
|
|
|
|
if (! checkInjectionPermission(mTouchedWindow, injectorPid, injectorUid)) {
|
|
|
|
injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
|
2010-07-14 18:48:53 -07:00
|
|
|
injectionPermission = INJECTION_PERMISSION_DENIED;
|
|
|
|
break; // failed, exit wait loop
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the pointer is not currently down, then ignore the event.
|
|
|
|
if (! mTouchDown) {
|
|
|
|
LOGI("Dropping event because the pointer is not down.");
|
|
|
|
injectionResult = INPUT_EVENT_INJECTION_FAILED;
|
|
|
|
injectionPermission = INJECTION_PERMISSION_GRANTED;
|
2010-06-22 01:27:15 -07:00
|
|
|
break; // failed, exit wait loop
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there is no currently touched window then fail.
|
2010-07-14 18:48:53 -07:00
|
|
|
if (! mTouchedWindow) {
|
2010-08-11 14:46:32 -07:00
|
|
|
#if DEBUG_INPUT_DISPATCHER_POLICY
|
|
|
|
LOGD("Dropping event because there is no touched window to receive it.");
|
|
|
|
#endif
|
2010-06-22 01:27:15 -07:00
|
|
|
injectionResult = INPUT_EVENT_INJECTION_FAILED;
|
2010-07-14 18:48:53 -07:00
|
|
|
injectionPermission = INJECTION_PERMISSION_GRANTED;
|
2010-06-22 01:27:15 -07:00
|
|
|
break; // failed, exit wait loop
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the touched window is paused then keep waiting.
|
|
|
|
if (mTouchedWindow->paused) {
|
|
|
|
#if DEBUG_INPUT_DISPATCHER_POLICY
|
|
|
|
LOGD("Waiting because touched window is paused.");
|
|
|
|
#endif
|
|
|
|
anrTimer.dispatchPausedByApplication(mTouchedWindow);
|
|
|
|
continue; // wait some more
|
|
|
|
}
|
|
|
|
|
|
|
|
// Success!
|
2010-07-14 18:48:53 -07:00
|
|
|
injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
|
|
|
|
injectionPermission = INJECTION_PERMISSION_GRANTED;
|
2010-06-22 01:27:15 -07:00
|
|
|
break; // done
|
2010-06-15 01:31:58 -07:00
|
|
|
}
|
|
|
|
}
|
2010-06-22 01:27:15 -07:00
|
|
|
|
|
|
|
// Output targets.
|
|
|
|
if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
|
|
|
|
size_t numWallpaperWindows = mTouchedWallpaperWindows.size();
|
|
|
|
for (size_t i = 0; i < numWallpaperWindows; i++) {
|
2010-09-01 17:01:00 -07:00
|
|
|
addTarget(mTouchedWallpaperWindows[i],
|
|
|
|
InputTarget::FLAG_WINDOW_IS_OBSCURED, 0, outTargets);
|
2010-06-22 01:27:15 -07:00
|
|
|
}
|
|
|
|
|
2010-09-01 17:01:00 -07:00
|
|
|
size_t numOutsideTargets = mTempTouchedOutsideTargets.size();
|
|
|
|
for (size_t i = 0; i < numOutsideTargets; i++) {
|
|
|
|
const OutsideTarget& outsideTarget = mTempTouchedOutsideTargets[i];
|
|
|
|
int32_t outsideTargetFlags = InputTarget::FLAG_OUTSIDE;
|
|
|
|
if (outsideTarget.obscured) {
|
|
|
|
outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
|
|
|
|
}
|
|
|
|
addTarget(outsideTarget.window, outsideTargetFlags, 0, outTargets);
|
2010-06-22 01:27:15 -07:00
|
|
|
}
|
|
|
|
|
2010-09-01 17:01:00 -07:00
|
|
|
int32_t targetFlags = InputTarget::FLAG_SYNC;
|
|
|
|
if (mTouchedWindowIsObscured) {
|
|
|
|
targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
|
|
|
|
}
|
|
|
|
addTarget(mTouchedWindow, targetFlags,
|
2010-06-22 01:27:15 -07:00
|
|
|
anrTimer.getTimeSpentWaitingForApplication(), outTargets);
|
|
|
|
outTouchedWindow = mTouchedWindow;
|
|
|
|
} else {
|
|
|
|
outTouchedWindow = NULL;
|
|
|
|
}
|
2010-09-01 17:01:00 -07:00
|
|
|
mTempTouchedOutsideTargets.clear();
|
2010-06-22 01:27:15 -07:00
|
|
|
|
2010-07-14 18:48:53 -07:00
|
|
|
// Check injection permission once and for all.
|
|
|
|
if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
|
|
|
|
if (checkInjectionPermission(action == AMOTION_EVENT_ACTION_DOWN ? NULL : mTouchedWindow,
|
|
|
|
injectorPid, injectorUid)) {
|
|
|
|
injectionPermission = INJECTION_PERMISSION_GRANTED;
|
|
|
|
} else {
|
|
|
|
injectionPermission = INJECTION_PERMISSION_DENIED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update final pieces of touch state if the injector had permission.
|
|
|
|
if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
|
|
|
|
if (action == AMOTION_EVENT_ACTION_DOWN) {
|
2010-06-22 01:27:15 -07:00
|
|
|
if (mTouchDown) {
|
|
|
|
// This is weird. We got a down but we thought it was already down!
|
|
|
|
LOGW("Pointer down received while already down.");
|
|
|
|
} else {
|
|
|
|
mTouchDown = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
|
|
|
|
// Since we failed to identify a target for this touch down, we may still
|
|
|
|
// be holding on to an earlier target from a previous touch down. Release it.
|
|
|
|
releaseTouchedWindowLd();
|
|
|
|
}
|
2010-07-14 18:48:53 -07:00
|
|
|
} else if (action == AMOTION_EVENT_ACTION_UP) {
|
2010-06-22 01:27:15 -07:00
|
|
|
mTouchDown = false;
|
|
|
|
releaseTouchedWindowLd();
|
|
|
|
}
|
2010-07-14 18:48:53 -07:00
|
|
|
} else {
|
|
|
|
LOGW("Not updating touch focus because injection was denied.");
|
2010-06-22 01:27:15 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#if DEBUG_FOCUS
|
|
|
|
LOGD("waitForTouchedWindow finished: injectionResult=%d",
|
|
|
|
injectionResult);
|
2010-07-15 23:54:05 -07:00
|
|
|
logDispatchStateLd();
|
2010-06-22 01:27:15 -07:00
|
|
|
#endif
|
2010-06-17 20:52:56 -07:00
|
|
|
return injectionResult;
|
2010-06-15 01:31:58 -07:00
|
|
|
}
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
void NativeInputManager::releaseTouchedWindowLd() {
|
|
|
|
mTouchedWindow = NULL;
|
2010-09-01 17:01:00 -07:00
|
|
|
mTouchedWindowIsObscured = false;
|
2010-06-22 01:27:15 -07:00
|
|
|
mTouchedWallpaperWindows.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeInputManager::addTarget(const InputWindow* window, int32_t targetFlags,
|
|
|
|
nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets) {
|
|
|
|
nsecs_t timeout = window->dispatchingTimeout - timeSpentWaitingForApplication;
|
|
|
|
if (timeout < MIN_INPUT_DISPATCHING_TIMEOUT) {
|
|
|
|
timeout = MIN_INPUT_DISPATCHING_TIMEOUT;
|
|
|
|
}
|
|
|
|
|
|
|
|
outTargets.push();
|
|
|
|
|
|
|
|
InputTarget& target = outTargets.editTop();
|
|
|
|
target.inputChannel = window->inputChannel;
|
|
|
|
target.flags = targetFlags;
|
|
|
|
target.timeout = timeout;
|
|
|
|
target.xOffset = - window->frameLeft;
|
|
|
|
target.yOffset = - window->frameTop;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeInputManager::checkInjectionPermission(const InputWindow* window,
|
|
|
|
int32_t injectorPid, int32_t injectorUid) {
|
|
|
|
if (injectorUid > 0 && (window == NULL || window->ownerUid != injectorUid)) {
|
|
|
|
JNIEnv* env = jniEnv();
|
|
|
|
jboolean result = env->CallBooleanMethod(mCallbacksObj,
|
|
|
|
gCallbacksClassInfo.checkInjectEventsPermission, injectorPid, injectorUid);
|
|
|
|
checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission");
|
|
|
|
|
|
|
|
if (! result) {
|
|
|
|
if (window) {
|
|
|
|
LOGW("Permission denied: injecting event from pid %d uid %d to window "
|
|
|
|
"with input channel %s owned by uid %d",
|
|
|
|
injectorPid, injectorUid, window->inputChannel->getName().string(),
|
|
|
|
window->ownerUid);
|
|
|
|
} else {
|
|
|
|
LOGW("Permission denied: injecting event from pid %d uid %d",
|
|
|
|
injectorPid, injectorUid);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-09-01 17:01:00 -07:00
|
|
|
bool NativeInputManager::isWindowObscuredLocked(const InputWindow* window) {
|
|
|
|
size_t numWindows = mWindows.size();
|
|
|
|
for (size_t i = 0; i < numWindows; i++) {
|
|
|
|
const InputWindow* other = & mWindows.itemAt(i);
|
|
|
|
if (other == window) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (other->visible && window->visibleFrameIntersects(other)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
int32_t NativeInputManager::waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
|
2010-06-17 20:52:56 -07:00
|
|
|
int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets) {
|
2010-06-15 01:31:58 -07:00
|
|
|
#if DEBUG_INPUT_DISPATCHER_POLICY
|
2010-06-22 01:27:15 -07:00
|
|
|
LOGD("waitForKeyEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
|
2010-06-17 20:52:56 -07:00
|
|
|
policyFlags, injectorPid, injectorUid);
|
2010-06-15 01:31:58 -07:00
|
|
|
#endif
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
int32_t windowType;
|
|
|
|
{ // acquire lock
|
|
|
|
AutoMutex _l(mDispatchLock);
|
2010-06-15 01:31:58 -07:00
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
InputWindow* focusedWindow;
|
|
|
|
int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
|
|
|
|
injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
|
|
|
|
if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
|
|
|
|
return injectionResult;
|
|
|
|
}
|
|
|
|
|
|
|
|
windowType = focusedWindow->layoutParamsType;
|
|
|
|
} // release lock
|
|
|
|
|
2010-07-02 15:37:36 -07:00
|
|
|
if (isPolicyKey(keyEvent->getKeyCode(), isScreenOn())) {
|
|
|
|
const InputTarget& target = outTargets.top();
|
|
|
|
bool consumed = interceptKeyBeforeDispatching(target, keyEvent, policyFlags);
|
|
|
|
if (consumed) {
|
|
|
|
outTargets.clear();
|
|
|
|
return INPUT_EVENT_INJECTION_SUCCEEDED;
|
|
|
|
}
|
2010-08-11 14:46:32 -07:00
|
|
|
|
|
|
|
addMonitoringTargetsLd(outTargets);
|
2010-06-15 01:31:58 -07:00
|
|
|
}
|
2010-06-22 01:27:15 -07:00
|
|
|
|
|
|
|
pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
|
|
|
|
return INPUT_EVENT_INJECTION_SUCCEEDED;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t NativeInputManager::waitForMotionEventTargets(MotionEvent* motionEvent,
|
|
|
|
uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
|
|
|
|
Vector<InputTarget>& outTargets) {
|
|
|
|
#if DEBUG_INPUT_DISPATCHER_POLICY
|
|
|
|
LOGD("waitForMotionEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
|
|
|
|
policyFlags, injectorPid, injectorUid);
|
|
|
|
#endif
|
|
|
|
|
2010-07-14 18:48:53 -07:00
|
|
|
int32_t source = motionEvent->getSource();
|
|
|
|
if (source & AINPUT_SOURCE_CLASS_POINTER) {
|
2010-07-02 15:37:36 -07:00
|
|
|
return waitForTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
|
2010-06-22 01:27:15 -07:00
|
|
|
outTargets);
|
2010-07-14 18:48:53 -07:00
|
|
|
} else {
|
|
|
|
return waitForNonTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
|
|
|
|
outTargets);
|
2010-06-22 01:27:15 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-14 18:48:53 -07:00
|
|
|
int32_t NativeInputManager::waitForNonTouchEventTargets(MotionEvent* motionEvent,
|
2010-06-22 01:27:15 -07:00
|
|
|
uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
|
|
|
|
Vector<InputTarget>& outTargets) {
|
|
|
|
#if DEBUG_INPUT_DISPATCHER_POLICY
|
2010-07-14 18:48:53 -07:00
|
|
|
LOGD("waitForNonTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
|
2010-06-22 01:27:15 -07:00
|
|
|
policyFlags, injectorPid, injectorUid);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int32_t windowType;
|
|
|
|
{ // acquire lock
|
|
|
|
AutoMutex _l(mDispatchLock);
|
|
|
|
|
|
|
|
InputWindow* focusedWindow;
|
|
|
|
int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
|
|
|
|
injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
|
|
|
|
if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
|
|
|
|
return injectionResult;
|
|
|
|
}
|
|
|
|
|
|
|
|
windowType = focusedWindow->layoutParamsType;
|
2010-08-11 14:46:32 -07:00
|
|
|
|
|
|
|
addMonitoringTargetsLd(outTargets);
|
2010-06-22 01:27:15 -07:00
|
|
|
} // release lock
|
|
|
|
|
|
|
|
pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
|
|
|
|
return INPUT_EVENT_INJECTION_SUCCEEDED;
|
2010-06-17 20:52:56 -07:00
|
|
|
}
|
|
|
|
|
2010-07-02 15:37:36 -07:00
|
|
|
int32_t NativeInputManager::waitForTouchEventTargets(MotionEvent* motionEvent,
|
2010-06-22 01:27:15 -07:00
|
|
|
uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
|
2010-06-17 20:52:56 -07:00
|
|
|
Vector<InputTarget>& outTargets) {
|
2010-06-22 01:27:15 -07:00
|
|
|
#if DEBUG_INPUT_DISPATCHER_POLICY
|
2010-07-02 15:37:36 -07:00
|
|
|
LOGD("waitForTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
|
2010-06-22 01:27:15 -07:00
|
|
|
policyFlags, injectorPid, injectorUid);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int32_t windowType;
|
|
|
|
{ // acquire lock
|
|
|
|
AutoMutex _l(mDispatchLock);
|
|
|
|
|
|
|
|
InputWindow* touchedWindow;
|
|
|
|
int32_t injectionResult = waitForTouchedWindowLd(motionEvent, policyFlags,
|
|
|
|
injectorPid, injectorUid, outTargets, /*out*/ touchedWindow);
|
|
|
|
if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
|
|
|
|
return injectionResult;
|
|
|
|
}
|
|
|
|
|
|
|
|
windowType = touchedWindow->layoutParamsType;
|
2010-08-11 14:46:32 -07:00
|
|
|
|
|
|
|
addMonitoringTargetsLd(outTargets);
|
2010-06-22 01:27:15 -07:00
|
|
|
} // release lock
|
|
|
|
|
|
|
|
int32_t eventType;
|
|
|
|
switch (motionEvent->getAction()) {
|
2010-07-14 18:48:53 -07:00
|
|
|
case AMOTION_EVENT_ACTION_DOWN:
|
2010-06-22 01:27:15 -07:00
|
|
|
eventType = POWER_MANAGER_TOUCH_EVENT;
|
|
|
|
break;
|
2010-07-14 18:48:53 -07:00
|
|
|
case AMOTION_EVENT_ACTION_UP:
|
2010-06-22 01:27:15 -07:00
|
|
|
eventType = POWER_MANAGER_TOUCH_UP_EVENT;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (motionEvent->getEventTime() - motionEvent->getDownTime()
|
|
|
|
>= EVENT_IGNORE_DURATION) {
|
|
|
|
eventType = POWER_MANAGER_TOUCH_EVENT;
|
|
|
|
} else {
|
|
|
|
eventType = POWER_MANAGER_LONG_TOUCH_EVENT;
|
2010-06-17 20:52:56 -07:00
|
|
|
}
|
2010-06-22 01:27:15 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
pokeUserActivityIfNeeded(windowType, eventType);
|
|
|
|
return INPUT_EVENT_INJECTION_SUCCEEDED;
|
|
|
|
}
|
|
|
|
|
2010-06-30 14:41:59 -07:00
|
|
|
bool NativeInputManager::interceptKeyBeforeDispatching(const InputTarget& target,
|
|
|
|
const KeyEvent* keyEvent, uint32_t policyFlags) {
|
|
|
|
JNIEnv* env = jniEnv();
|
|
|
|
|
|
|
|
jobject inputChannelObj = getInputChannelObjLocal(env, target.inputChannel);
|
|
|
|
if (inputChannelObj) {
|
|
|
|
jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
|
|
|
|
gCallbacksClassInfo.interceptKeyBeforeDispatching,
|
2010-07-02 15:37:36 -07:00
|
|
|
inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(),
|
|
|
|
keyEvent->getKeyCode(), keyEvent->getMetaState(),
|
2010-06-30 14:41:59 -07:00
|
|
|
keyEvent->getRepeatCount(), policyFlags);
|
|
|
|
bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
|
|
|
|
|
|
|
|
env->DeleteLocalRef(inputChannelObj);
|
|
|
|
|
|
|
|
return consumed && ! error;
|
|
|
|
} else {
|
|
|
|
LOGW("Could not apply key dispatch policy because input channel '%s' is "
|
|
|
|
"no longer valid.", target.inputChannel->getName().string());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
void NativeInputManager::pokeUserActivityIfNeeded(int32_t windowType, int32_t eventType) {
|
|
|
|
if (windowType != TYPE_KEYGUARD) {
|
|
|
|
nsecs_t eventTime = now();
|
|
|
|
pokeUserActivity(eventTime, eventType);
|
|
|
|
}
|
|
|
|
}
|
2010-06-17 20:52:56 -07:00
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
|
2010-07-02 15:37:36 -07:00
|
|
|
android_server_PowerManagerService_userActivity(eventTime, eventType);
|
2010-06-22 01:27:15 -07:00
|
|
|
}
|
2010-06-17 20:52:56 -07:00
|
|
|
|
2010-08-11 14:46:32 -07:00
|
|
|
void NativeInputManager::registerMonitoringChannel(const sp<InputChannel>& inputChannel) {
|
|
|
|
{ // acquire lock
|
|
|
|
AutoMutex _l(mDispatchLock);
|
|
|
|
mMonitoringChannels.push(inputChannel);
|
|
|
|
} // release lock
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeInputManager::unregisterMonitoringChannel(const sp<InputChannel>& inputChannel) {
|
|
|
|
{ // acquire lock
|
|
|
|
AutoMutex _l(mDispatchLock);
|
|
|
|
|
|
|
|
for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
|
|
|
|
if (mMonitoringChannels[i] == inputChannel) {
|
|
|
|
mMonitoringChannels.removeAt(i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // release lock
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeInputManager::addMonitoringTargetsLd(Vector<InputTarget>& outTargets) {
|
|
|
|
for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
|
|
|
|
outTargets.push();
|
|
|
|
|
|
|
|
InputTarget& target = outTargets.editTop();
|
|
|
|
target.inputChannel = mMonitoringChannels[i];
|
|
|
|
target.flags = 0;
|
|
|
|
target.timeout = -1;
|
|
|
|
target.xOffset = 0;
|
|
|
|
target.yOffset = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-23 21:28:06 -07:00
|
|
|
static void dumpMotionRange(String8& dump,
|
|
|
|
const char* name, const InputDeviceInfo::MotionRange* range) {
|
|
|
|
if (range) {
|
|
|
|
dump.appendFormat(" %s = { min: %0.3f, max: %0.3f, flat: %0.3f, fuzz: %0.3f }\n",
|
|
|
|
name, range->min, range->max, range->flat, range->fuzz);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define DUMP_MOTION_RANGE(range) \
|
|
|
|
dumpMotionRange(dump, #range, deviceInfo.getMotionRange(AINPUT_MOTION_RANGE_##range));
|
|
|
|
|
|
|
|
void NativeInputManager::dumpDeviceInfo(String8& dump) {
|
|
|
|
Vector<int32_t> deviceIds;
|
|
|
|
mInputManager->getInputDeviceIds(deviceIds);
|
|
|
|
|
|
|
|
InputDeviceInfo deviceInfo;
|
|
|
|
for (size_t i = 0; i < deviceIds.size(); i++) {
|
|
|
|
int32_t deviceId = deviceIds[i];
|
|
|
|
|
|
|
|
status_t result = mInputManager->getInputDeviceInfo(deviceId, & deviceInfo);
|
|
|
|
if (result == NAME_NOT_FOUND) {
|
|
|
|
continue;
|
|
|
|
} else if (result != OK) {
|
|
|
|
dump.appendFormat(" ** Unexpected error %d getting information about input devices.\n",
|
|
|
|
result);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
dump.appendFormat(" Device %d: '%s'\n",
|
|
|
|
deviceInfo.getId(), deviceInfo.getName().string());
|
|
|
|
dump.appendFormat(" sources = 0x%08x\n",
|
|
|
|
deviceInfo.getSources());
|
|
|
|
dump.appendFormat(" keyboardType = %d\n",
|
|
|
|
deviceInfo.getKeyboardType());
|
|
|
|
|
|
|
|
dump.append(" motion ranges:\n");
|
|
|
|
DUMP_MOTION_RANGE(X);
|
|
|
|
DUMP_MOTION_RANGE(Y);
|
|
|
|
DUMP_MOTION_RANGE(PRESSURE);
|
|
|
|
DUMP_MOTION_RANGE(SIZE);
|
|
|
|
DUMP_MOTION_RANGE(TOUCH_MAJOR);
|
|
|
|
DUMP_MOTION_RANGE(TOUCH_MINOR);
|
|
|
|
DUMP_MOTION_RANGE(TOOL_MAJOR);
|
|
|
|
DUMP_MOTION_RANGE(TOOL_MINOR);
|
|
|
|
DUMP_MOTION_RANGE(ORIENTATION);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef DUMP_MOTION_RANGE
|
|
|
|
|
2010-07-15 23:54:05 -07:00
|
|
|
void NativeInputManager::logDispatchStateLd() {
|
|
|
|
String8 dump;
|
|
|
|
dumpDispatchStateLd(dump);
|
|
|
|
LOGD("%s", dump.string());
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeInputManager::dumpDispatchStateLd(String8& dump) {
|
|
|
|
dump.appendFormat(" dispatchEnabled: %d\n", mDispatchEnabled);
|
|
|
|
dump.appendFormat(" dispatchFrozen: %d\n", mDispatchFrozen);
|
|
|
|
dump.appendFormat(" windowsReady: %d\n", mWindowsReady);
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
if (mFocusedApplication) {
|
2010-07-15 23:54:05 -07:00
|
|
|
dump.appendFormat(" focusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
|
2010-06-22 01:27:15 -07:00
|
|
|
mFocusedApplication->name.string(),
|
|
|
|
mFocusedApplication->dispatchingTimeout / 1000000.0);
|
|
|
|
} else {
|
2010-07-15 23:54:05 -07:00
|
|
|
dump.append(" focusedApplication: <null>\n");
|
2010-06-22 01:27:15 -07:00
|
|
|
}
|
2010-07-15 23:54:05 -07:00
|
|
|
dump.appendFormat(" focusedWindow: '%s'\n",
|
2010-06-22 01:27:15 -07:00
|
|
|
mFocusedWindow != NULL ? mFocusedWindow->inputChannel->getName().string() : "<null>");
|
2010-07-15 23:54:05 -07:00
|
|
|
dump.appendFormat(" touchedWindow: '%s', touchDown=%d\n",
|
2010-06-22 01:27:15 -07:00
|
|
|
mTouchedWindow != NULL ? mTouchedWindow->inputChannel->getName().string() : "<null>",
|
|
|
|
mTouchDown);
|
|
|
|
for (size_t i = 0; i < mTouchedWallpaperWindows.size(); i++) {
|
2010-07-15 23:54:05 -07:00
|
|
|
dump.appendFormat(" touchedWallpaperWindows[%d]: '%s'\n",
|
2010-06-22 01:27:15 -07:00
|
|
|
i, mTouchedWallpaperWindows[i]->inputChannel->getName().string());
|
2010-06-17 20:52:56 -07:00
|
|
|
}
|
2010-06-22 01:27:15 -07:00
|
|
|
for (size_t i = 0; i < mWindows.size(); i++) {
|
2010-07-15 23:54:05 -07:00
|
|
|
dump.appendFormat(" windows[%d]: '%s', paused=%d, hasFocus=%d, hasWallpaper=%d, "
|
|
|
|
"visible=%d, flags=0x%08x, type=0x%08x, "
|
2010-09-01 17:01:00 -07:00
|
|
|
"frame=[%d,%d][%d,%d], "
|
|
|
|
"visibleFrame=[%d,%d][%d,%d], "
|
|
|
|
"touchableArea=[%d,%d][%d,%d], "
|
2010-07-15 23:54:05 -07:00
|
|
|
"ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
|
2010-06-22 01:27:15 -07:00
|
|
|
i, mWindows[i].inputChannel->getName().string(),
|
|
|
|
mWindows[i].paused, mWindows[i].hasFocus, mWindows[i].hasWallpaper,
|
|
|
|
mWindows[i].visible, mWindows[i].layoutParamsFlags, mWindows[i].layoutParamsType,
|
|
|
|
mWindows[i].frameLeft, mWindows[i].frameTop,
|
2010-09-01 17:01:00 -07:00
|
|
|
mWindows[i].frameRight, mWindows[i].frameBottom,
|
|
|
|
mWindows[i].visibleFrameLeft, mWindows[i].visibleFrameTop,
|
|
|
|
mWindows[i].visibleFrameRight, mWindows[i].visibleFrameBottom,
|
2010-06-22 01:27:15 -07:00
|
|
|
mWindows[i].touchableAreaLeft, mWindows[i].touchableAreaTop,
|
|
|
|
mWindows[i].touchableAreaRight, mWindows[i].touchableAreaBottom,
|
|
|
|
mWindows[i].ownerPid, mWindows[i].ownerUid,
|
|
|
|
mWindows[i].dispatchingTimeout / 1000000.0);
|
|
|
|
}
|
2010-08-11 14:46:32 -07:00
|
|
|
|
|
|
|
for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
|
|
|
|
dump.appendFormat(" monitoringChannel[%d]: '%s'\n",
|
|
|
|
i, mMonitoringChannels[i]->getName().string());
|
|
|
|
}
|
2010-06-15 01:31:58 -07:00
|
|
|
}
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
2010-09-01 17:01:00 -07:00
|
|
|
bool NativeInputManager::InputWindow::visibleFrameIntersects(const InputWindow* other) const {
|
|
|
|
return visibleFrameRight > other->visibleFrameLeft
|
|
|
|
&& visibleFrameLeft < other->visibleFrameRight
|
|
|
|
&& visibleFrameBottom > other->visibleFrameTop
|
|
|
|
&& visibleFrameTop < other->visibleFrameBottom;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeInputManager::InputWindow::touchableAreaContainsPoint(int32_t x, int32_t y) const {
|
|
|
|
return x >= touchableAreaLeft && x <= touchableAreaRight
|
|
|
|
&& y >= touchableAreaTop && y <= touchableAreaBottom;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
NativeInputManager::ANRTimer::ANRTimer() :
|
|
|
|
mBudget(APPLICATION), mStartTime(now()), mFrozen(false), mPausedWindow(NULL) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeInputManager::ANRTimer::dispatchFrozenBySystem() {
|
|
|
|
mFrozen = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeInputManager::ANRTimer::dispatchPausedByApplication(InputWindow* pausedWindow) {
|
|
|
|
mPausedWindow = pausedWindow;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeInputManager::ANRTimer::waitForDispatchStateChangeLd(NativeInputManager* inputManager) {
|
|
|
|
nsecs_t currentTime = now();
|
|
|
|
|
|
|
|
Budget newBudget;
|
|
|
|
nsecs_t dispatchingTimeout;
|
|
|
|
sp<InputChannel> pausedChannel = NULL;
|
|
|
|
jobject tokenObj = NULL;
|
|
|
|
if (mFrozen) {
|
|
|
|
newBudget = SYSTEM;
|
|
|
|
dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
|
|
|
|
mFrozen = false;
|
|
|
|
} else if (mPausedWindow) {
|
|
|
|
newBudget = APPLICATION;
|
|
|
|
dispatchingTimeout = mPausedWindow->dispatchingTimeout;
|
|
|
|
pausedChannel = mPausedWindow->inputChannel;
|
|
|
|
mPausedWindow = NULL;
|
|
|
|
} else if (inputManager->mFocusedApplication) {
|
|
|
|
newBudget = APPLICATION;
|
|
|
|
dispatchingTimeout = inputManager->mFocusedApplication->dispatchingTimeout;
|
|
|
|
tokenObj = jniEnv()->NewLocalRef(inputManager->mFocusedApplication->tokenObjWeak);
|
|
|
|
} else {
|
|
|
|
newBudget = APPLICATION;
|
|
|
|
dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mBudget != newBudget) {
|
|
|
|
mBudget = newBudget;
|
|
|
|
mStartTime = currentTime;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool result = false;
|
|
|
|
nsecs_t timeoutRemaining = mStartTime + dispatchingTimeout - currentTime;
|
|
|
|
if (timeoutRemaining > 0
|
|
|
|
&& inputManager->mDispatchStateChanged.waitRelative(inputManager->mDispatchLock,
|
|
|
|
timeoutRemaining) == OK) {
|
|
|
|
result = true;
|
|
|
|
} else {
|
|
|
|
if (pausedChannel != NULL || tokenObj != NULL) {
|
|
|
|
bool resumed;
|
|
|
|
nsecs_t newTimeout = 0;
|
|
|
|
|
|
|
|
inputManager->mDispatchLock.unlock(); // release lock
|
|
|
|
if (pausedChannel != NULL) {
|
|
|
|
resumed = inputManager->notifyInputChannelANR(pausedChannel, /*out*/ newTimeout);
|
|
|
|
} else {
|
|
|
|
resumed = inputManager->notifyANR(tokenObj, /*out*/ newTimeout);
|
|
|
|
}
|
|
|
|
inputManager->mDispatchLock.lock(); // re-acquire lock
|
|
|
|
|
|
|
|
if (resumed) {
|
|
|
|
mStartTime = now() - dispatchingTimeout + newTimeout;
|
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tokenObj) {
|
|
|
|
jniEnv()->DeleteLocalRef(tokenObj);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsecs_t NativeInputManager::ANRTimer::getTimeSpentWaitingForApplication() const {
|
|
|
|
return mBudget == APPLICATION ? now() - mStartTime : 0;
|
|
|
|
}
|
2010-06-15 01:31:58 -07:00
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
static sp<NativeInputManager> gNativeInputManager;
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
|
|
|
|
static bool checkInputManagerUnitialized(JNIEnv* env) {
|
2010-06-15 01:31:58 -07:00
|
|
|
if (gNativeInputManager == NULL) {
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
LOGE("Input manager not initialized.");
|
|
|
|
jniThrowRuntimeException(env, "Input manager not initialized.");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void android_server_InputManager_nativeInit(JNIEnv* env, jclass clazz,
|
|
|
|
jobject callbacks) {
|
2010-06-15 01:31:58 -07:00
|
|
|
if (gNativeInputManager == NULL) {
|
|
|
|
gNativeInputManager = new NativeInputManager(callbacks);
|
|
|
|
} else {
|
|
|
|
LOGE("Input manager already initialized.");
|
|
|
|
jniThrowRuntimeException(env, "Input manager already initialized.");
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void android_server_InputManager_nativeStart(JNIEnv* env, jclass clazz) {
|
|
|
|
if (checkInputManagerUnitialized(env)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
status_t result = gNativeInputManager->getInputManager()->start();
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
if (result) {
|
|
|
|
jniThrowRuntimeException(env, "Input manager could not be started.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void android_server_InputManager_nativeSetDisplaySize(JNIEnv* env, jclass clazz,
|
|
|
|
jint displayId, jint width, jint height) {
|
|
|
|
if (checkInputManagerUnitialized(env)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXX we could get this from the SurfaceFlinger directly instead of requiring it
|
|
|
|
// to be passed in like this, not sure which is better but leaving it like this
|
|
|
|
// keeps the window manager in direct control of when display transitions propagate down
|
|
|
|
// to the input dispatcher
|
2010-06-15 01:31:58 -07:00
|
|
|
gNativeInputManager->setDisplaySize(displayId, width, height);
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void android_server_InputManager_nativeSetDisplayOrientation(JNIEnv* env, jclass clazz,
|
|
|
|
jint displayId, jint orientation) {
|
|
|
|
if (checkInputManagerUnitialized(env)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
gNativeInputManager->setDisplayOrientation(displayId, orientation);
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static jint android_server_InputManager_nativeGetScanCodeState(JNIEnv* env, jclass clazz,
|
2010-07-23 21:28:06 -07:00
|
|
|
jint deviceId, jint sourceMask, jint scanCode) {
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
if (checkInputManagerUnitialized(env)) {
|
2010-07-14 18:48:53 -07:00
|
|
|
return AKEY_STATE_UNKNOWN;
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
}
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
return gNativeInputManager->getInputManager()->getScanCodeState(
|
2010-07-23 21:28:06 -07:00
|
|
|
deviceId, uint32_t(sourceMask), scanCode);
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static jint android_server_InputManager_nativeGetKeyCodeState(JNIEnv* env, jclass clazz,
|
2010-07-23 21:28:06 -07:00
|
|
|
jint deviceId, jint sourceMask, jint keyCode) {
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
if (checkInputManagerUnitialized(env)) {
|
2010-07-14 18:48:53 -07:00
|
|
|
return AKEY_STATE_UNKNOWN;
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
}
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
return gNativeInputManager->getInputManager()->getKeyCodeState(
|
2010-07-23 21:28:06 -07:00
|
|
|
deviceId, uint32_t(sourceMask), keyCode);
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static jint android_server_InputManager_nativeGetSwitchState(JNIEnv* env, jclass clazz,
|
2010-07-23 21:28:06 -07:00
|
|
|
jint deviceId, jint sourceMask, jint sw) {
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
if (checkInputManagerUnitialized(env)) {
|
2010-07-14 18:48:53 -07:00
|
|
|
return AKEY_STATE_UNKNOWN;
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
}
|
|
|
|
|
2010-07-23 21:28:06 -07:00
|
|
|
return gNativeInputManager->getInputManager()->getSwitchState(
|
|
|
|
deviceId, uint32_t(sourceMask), sw);
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static jboolean android_server_InputManager_nativeHasKeys(JNIEnv* env, jclass clazz,
|
2010-07-23 21:28:06 -07:00
|
|
|
jint deviceId, jint sourceMask, jintArray keyCodes, jbooleanArray outFlags) {
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
if (checkInputManagerUnitialized(env)) {
|
|
|
|
return JNI_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t* codes = env->GetIntArrayElements(keyCodes, NULL);
|
|
|
|
uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL);
|
|
|
|
jsize numCodes = env->GetArrayLength(keyCodes);
|
|
|
|
jboolean result;
|
2010-07-23 21:28:06 -07:00
|
|
|
if (numCodes == env->GetArrayLength(keyCodes)) {
|
|
|
|
result = gNativeInputManager->getInputManager()->hasKeys(
|
|
|
|
deviceId, uint32_t(sourceMask), numCodes, codes, flags);
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
} else {
|
|
|
|
result = JNI_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
env->ReleaseBooleanArrayElements(outFlags, flags, 0);
|
|
|
|
env->ReleaseIntArrayElements(keyCodes, codes, 0);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void throwInputChannelNotInitialized(JNIEnv* env) {
|
|
|
|
jniThrowException(env, "java/lang/IllegalStateException",
|
|
|
|
"inputChannel is not initialized");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void android_server_InputManager_handleInputChannelDisposed(JNIEnv* env,
|
|
|
|
jobject inputChannelObj, const sp<InputChannel>& inputChannel, void* data) {
|
|
|
|
LOGW("Input channel object '%s' was disposed without first being unregistered with "
|
|
|
|
"the input manager!", inputChannel->getName().string());
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
if (gNativeInputManager != NULL) {
|
2010-06-17 20:52:56 -07:00
|
|
|
gNativeInputManager->unregisterInputChannel(env, inputChannel);
|
2010-06-15 01:31:58 -07:00
|
|
|
}
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
|
2010-08-11 14:46:32 -07:00
|
|
|
jobject inputChannelObj, jboolean monitor) {
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
if (checkInputManagerUnitialized(env)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
|
|
|
|
inputChannelObj);
|
|
|
|
if (inputChannel == NULL) {
|
|
|
|
throwInputChannelNotInitialized(env);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-06-17 20:52:56 -07:00
|
|
|
|
|
|
|
status_t status = gNativeInputManager->registerInputChannel(
|
2010-08-11 14:46:32 -07:00
|
|
|
env, inputChannel, inputChannelObj, monitor);
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
if (status) {
|
|
|
|
jniThrowRuntimeException(env, "Failed to register input channel. "
|
|
|
|
"Check logs for details.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-08-11 14:46:32 -07:00
|
|
|
if (! monitor) {
|
|
|
|
android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
|
|
|
|
android_server_InputManager_handleInputChannelDisposed, NULL);
|
|
|
|
}
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void android_server_InputManager_nativeUnregisterInputChannel(JNIEnv* env, jclass clazz,
|
|
|
|
jobject inputChannelObj) {
|
|
|
|
if (checkInputManagerUnitialized(env)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
|
|
|
|
inputChannelObj);
|
|
|
|
if (inputChannel == NULL) {
|
|
|
|
throwInputChannelNotInitialized(env);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL);
|
|
|
|
|
2010-06-17 20:52:56 -07:00
|
|
|
status_t status = gNativeInputManager->unregisterInputChannel(env, inputChannel);
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
if (status) {
|
|
|
|
jniThrowRuntimeException(env, "Failed to unregister input channel. "
|
|
|
|
"Check logs for details.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-28 15:48:59 -07:00
|
|
|
static jint android_server_InputManager_nativeInjectInputEvent(JNIEnv* env, jclass clazz,
|
|
|
|
jobject inputEventObj, jint injectorPid, jint injectorUid,
|
|
|
|
jint syncMode, jint timeoutMillis) {
|
2010-06-17 20:52:56 -07:00
|
|
|
if (checkInputManagerUnitialized(env)) {
|
|
|
|
return INPUT_EVENT_INJECTION_FAILED;
|
|
|
|
}
|
|
|
|
|
2010-07-28 15:48:59 -07:00
|
|
|
if (env->IsInstanceOf(inputEventObj, gKeyEventClassInfo.clazz)) {
|
|
|
|
KeyEvent keyEvent;
|
|
|
|
android_view_KeyEvent_toNative(env, inputEventObj, & keyEvent);
|
2010-06-17 20:52:56 -07:00
|
|
|
|
2010-07-28 15:48:59 -07:00
|
|
|
return gNativeInputManager->getInputManager()->injectInputEvent(& keyEvent,
|
|
|
|
injectorPid, injectorUid, syncMode, timeoutMillis);
|
|
|
|
} else if (env->IsInstanceOf(inputEventObj, gMotionEventClassInfo.clazz)) {
|
|
|
|
MotionEvent motionEvent;
|
|
|
|
android_view_MotionEvent_toNative(env, inputEventObj, & motionEvent);
|
2010-06-17 20:52:56 -07:00
|
|
|
|
2010-07-28 15:48:59 -07:00
|
|
|
return gNativeInputManager->getInputManager()->injectInputEvent(& motionEvent,
|
|
|
|
injectorPid, injectorUid, syncMode, timeoutMillis);
|
|
|
|
} else {
|
|
|
|
jniThrowRuntimeException(env, "Invalid input event type.");
|
2010-06-17 20:52:56 -07:00
|
|
|
return INPUT_EVENT_INJECTION_FAILED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
static void android_server_InputManager_nativeSetInputWindows(JNIEnv* env, jclass clazz,
|
|
|
|
jobjectArray windowObjArray) {
|
|
|
|
if (checkInputManagerUnitialized(env)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
gNativeInputManager->setInputWindows(env, windowObjArray);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void android_server_InputManager_nativeSetFocusedApplication(JNIEnv* env, jclass clazz,
|
|
|
|
jobject applicationObj) {
|
|
|
|
if (checkInputManagerUnitialized(env)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
gNativeInputManager->setFocusedApplication(env, applicationObj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void android_server_InputManager_nativeSetInputDispatchMode(JNIEnv* env,
|
|
|
|
jclass clazz, jboolean enabled, jboolean frozen) {
|
|
|
|
if (checkInputManagerUnitialized(env)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
gNativeInputManager->setInputDispatchMode(enabled, frozen);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void android_server_InputManager_nativePreemptInputDispatch(JNIEnv* env,
|
|
|
|
jclass clazz) {
|
|
|
|
if (checkInputManagerUnitialized(env)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
gNativeInputManager->preemptInputDispatch();
|
|
|
|
}
|
|
|
|
|
2010-08-30 03:02:23 -07:00
|
|
|
static jobject android_server_InputManager_nativeGetInputDevice(JNIEnv* env,
|
|
|
|
jclass clazz, jint deviceId) {
|
|
|
|
if (checkInputManagerUnitialized(env)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
InputDeviceInfo deviceInfo;
|
|
|
|
status_t status = gNativeInputManager->getInputManager()->getInputDeviceInfo(
|
|
|
|
deviceId, & deviceInfo);
|
|
|
|
if (status) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
jobject deviceObj = env->NewObject(gInputDeviceClassInfo.clazz, gInputDeviceClassInfo.ctor);
|
|
|
|
if (! deviceObj) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
jstring deviceNameObj = env->NewStringUTF(deviceInfo.getName().string());
|
|
|
|
if (! deviceNameObj) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
env->SetIntField(deviceObj, gInputDeviceClassInfo.mId, deviceInfo.getId());
|
|
|
|
env->SetObjectField(deviceObj, gInputDeviceClassInfo.mName, deviceNameObj);
|
|
|
|
env->SetIntField(deviceObj, gInputDeviceClassInfo.mSources, deviceInfo.getSources());
|
|
|
|
env->SetIntField(deviceObj, gInputDeviceClassInfo.mKeyboardType, deviceInfo.getKeyboardType());
|
|
|
|
|
|
|
|
const KeyedVector<int, InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
|
|
|
|
for (size_t i = 0; i < ranges.size(); i++) {
|
|
|
|
int rangeType = ranges.keyAt(i);
|
|
|
|
const InputDeviceInfo::MotionRange& range = ranges.valueAt(i);
|
|
|
|
env->CallVoidMethod(deviceObj, gInputDeviceClassInfo.addMotionRange,
|
|
|
|
rangeType, range.min, range.max, range.flat, range.fuzz);
|
|
|
|
if (env->ExceptionCheck()) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return deviceObj;
|
|
|
|
}
|
|
|
|
|
|
|
|
static jintArray android_server_InputManager_nativeGetInputDeviceIds(JNIEnv* env,
|
|
|
|
jclass clazz) {
|
|
|
|
if (checkInputManagerUnitialized(env)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector<int> deviceIds;
|
|
|
|
gNativeInputManager->getInputManager()->getInputDeviceIds(deviceIds);
|
|
|
|
|
|
|
|
jintArray deviceIdsObj = env->NewIntArray(deviceIds.size());
|
|
|
|
if (! deviceIdsObj) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
env->SetIntArrayRegion(deviceIdsObj, 0, deviceIds.size(), deviceIds.array());
|
|
|
|
return deviceIdsObj;
|
|
|
|
}
|
|
|
|
|
2010-07-15 23:54:05 -07:00
|
|
|
static jstring android_server_InputManager_nativeDump(JNIEnv* env, jclass clazz) {
|
|
|
|
if (checkInputManagerUnitialized(env)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
String8 dump(gNativeInputManager->dump());
|
|
|
|
return env->NewStringUTF(dump.string());
|
|
|
|
}
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
static JNINativeMethod gInputManagerMethods[] = {
|
|
|
|
/* name, signature, funcPtr */
|
|
|
|
{ "nativeInit", "(Lcom/android/server/InputManager$Callbacks;)V",
|
|
|
|
(void*) android_server_InputManager_nativeInit },
|
|
|
|
{ "nativeStart", "()V",
|
|
|
|
(void*) android_server_InputManager_nativeStart },
|
|
|
|
{ "nativeSetDisplaySize", "(III)V",
|
|
|
|
(void*) android_server_InputManager_nativeSetDisplaySize },
|
|
|
|
{ "nativeSetDisplayOrientation", "(II)V",
|
|
|
|
(void*) android_server_InputManager_nativeSetDisplayOrientation },
|
|
|
|
{ "nativeGetScanCodeState", "(III)I",
|
|
|
|
(void*) android_server_InputManager_nativeGetScanCodeState },
|
|
|
|
{ "nativeGetKeyCodeState", "(III)I",
|
|
|
|
(void*) android_server_InputManager_nativeGetKeyCodeState },
|
|
|
|
{ "nativeGetSwitchState", "(III)I",
|
|
|
|
(void*) android_server_InputManager_nativeGetSwitchState },
|
2010-07-23 21:28:06 -07:00
|
|
|
{ "nativeHasKeys", "(II[I[Z)Z",
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
(void*) android_server_InputManager_nativeHasKeys },
|
2010-08-11 14:46:32 -07:00
|
|
|
{ "nativeRegisterInputChannel", "(Landroid/view/InputChannel;Z)V",
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
(void*) android_server_InputManager_nativeRegisterInputChannel },
|
|
|
|
{ "nativeUnregisterInputChannel", "(Landroid/view/InputChannel;)V",
|
2010-06-17 20:52:56 -07:00
|
|
|
(void*) android_server_InputManager_nativeUnregisterInputChannel },
|
2010-07-28 15:48:59 -07:00
|
|
|
{ "nativeInjectInputEvent", "(Landroid/view/InputEvent;IIII)I",
|
|
|
|
(void*) android_server_InputManager_nativeInjectInputEvent },
|
2010-06-22 01:27:15 -07:00
|
|
|
{ "nativeSetInputWindows", "([Lcom/android/server/InputWindow;)V",
|
|
|
|
(void*) android_server_InputManager_nativeSetInputWindows },
|
|
|
|
{ "nativeSetFocusedApplication", "(Lcom/android/server/InputApplication;)V",
|
|
|
|
(void*) android_server_InputManager_nativeSetFocusedApplication },
|
|
|
|
{ "nativeSetInputDispatchMode", "(ZZ)V",
|
|
|
|
(void*) android_server_InputManager_nativeSetInputDispatchMode },
|
|
|
|
{ "nativePreemptInputDispatch", "()V",
|
2010-07-15 23:54:05 -07:00
|
|
|
(void*) android_server_InputManager_nativePreemptInputDispatch },
|
2010-08-30 03:02:23 -07:00
|
|
|
{ "nativeGetInputDevice", "(I)Landroid/view/InputDevice;",
|
|
|
|
(void*) android_server_InputManager_nativeGetInputDevice },
|
|
|
|
{ "nativeGetInputDeviceIds", "()[I",
|
|
|
|
(void*) android_server_InputManager_nativeGetInputDeviceIds },
|
2010-07-15 23:54:05 -07:00
|
|
|
{ "nativeDump", "()Ljava/lang/String;",
|
|
|
|
(void*) android_server_InputManager_nativeDump },
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
#define FIND_CLASS(var, className) \
|
|
|
|
var = env->FindClass(className); \
|
|
|
|
LOG_FATAL_IF(! var, "Unable to find class " className); \
|
|
|
|
var = jclass(env->NewGlobalRef(var));
|
|
|
|
|
|
|
|
#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
|
|
|
|
var = env->GetMethodID(clazz, methodName, methodDescriptor); \
|
|
|
|
LOG_FATAL_IF(! var, "Unable to find method " methodName);
|
|
|
|
|
|
|
|
#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
|
|
|
|
var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
|
|
|
|
LOG_FATAL_IF(! var, "Unable to find field " fieldName);
|
|
|
|
|
|
|
|
int register_android_server_InputManager(JNIEnv* env) {
|
|
|
|
int res = jniRegisterNativeMethods(env, "com/android/server/InputManager",
|
|
|
|
gInputManagerMethods, NELEM(gInputManagerMethods));
|
|
|
|
LOG_FATAL_IF(res < 0, "Unable to register native methods.");
|
|
|
|
|
2010-06-15 01:31:58 -07:00
|
|
|
// Callbacks
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
|
|
|
|
FIND_CLASS(gCallbacksClassInfo.clazz, "com/android/server/InputManager$Callbacks");
|
|
|
|
|
|
|
|
GET_METHOD_ID(gCallbacksClassInfo.notifyConfigurationChanged, gCallbacksClassInfo.clazz,
|
|
|
|
"notifyConfigurationChanged", "(JIII)V");
|
|
|
|
|
|
|
|
GET_METHOD_ID(gCallbacksClassInfo.notifyLidSwitchChanged, gCallbacksClassInfo.clazz,
|
|
|
|
"notifyLidSwitchChanged", "(JZ)V");
|
|
|
|
|
2010-06-17 20:52:56 -07:00
|
|
|
GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelBroken, gCallbacksClassInfo.clazz,
|
|
|
|
"notifyInputChannelBroken", "(Landroid/view/InputChannel;)V");
|
|
|
|
|
|
|
|
GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelANR, gCallbacksClassInfo.clazz,
|
|
|
|
"notifyInputChannelANR", "(Landroid/view/InputChannel;)J");
|
|
|
|
|
|
|
|
GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelRecoveredFromANR, gCallbacksClassInfo.clazz,
|
|
|
|
"notifyInputChannelRecoveredFromANR", "(Landroid/view/InputChannel;)V");
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
|
|
|
|
"notifyANR", "(Ljava/lang/Object;)J");
|
|
|
|
|
2010-07-02 15:37:36 -07:00
|
|
|
GET_METHOD_ID(gCallbacksClassInfo.virtualKeyDownFeedback, gCallbacksClassInfo.clazz,
|
|
|
|
"virtualKeyDownFeedback", "()V");
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
|
2010-07-02 15:37:36 -07:00
|
|
|
"interceptKeyBeforeQueueing", "(JIZIZ)I");
|
2010-06-22 01:27:15 -07:00
|
|
|
|
|
|
|
GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
|
2010-07-02 15:37:36 -07:00
|
|
|
"interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIIIII)Z");
|
2010-06-22 01:27:15 -07:00
|
|
|
|
|
|
|
GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,
|
|
|
|
"checkInjectEventsPermission", "(II)Z");
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
|
|
|
|
GET_METHOD_ID(gCallbacksClassInfo.notifyAppSwitchComing, gCallbacksClassInfo.clazz,
|
|
|
|
"notifyAppSwitchComing", "()V");
|
|
|
|
|
|
|
|
GET_METHOD_ID(gCallbacksClassInfo.filterTouchEvents, gCallbacksClassInfo.clazz,
|
|
|
|
"filterTouchEvents", "()Z");
|
|
|
|
|
|
|
|
GET_METHOD_ID(gCallbacksClassInfo.filterJumpyTouchEvents, gCallbacksClassInfo.clazz,
|
|
|
|
"filterJumpyTouchEvents", "()Z");
|
|
|
|
|
|
|
|
GET_METHOD_ID(gCallbacksClassInfo.getVirtualKeyDefinitions, gCallbacksClassInfo.clazz,
|
|
|
|
"getVirtualKeyDefinitions",
|
|
|
|
"(Ljava/lang/String;)[Lcom/android/server/InputManager$VirtualKeyDefinition;");
|
|
|
|
|
2010-08-30 03:02:23 -07:00
|
|
|
GET_METHOD_ID(gCallbacksClassInfo.getInputDeviceCalibration, gCallbacksClassInfo.clazz,
|
|
|
|
"getInputDeviceCalibration",
|
|
|
|
"(Ljava/lang/String;)Lcom/android/server/InputManager$InputDeviceCalibration;");
|
|
|
|
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
GET_METHOD_ID(gCallbacksClassInfo.getExcludedDeviceNames, gCallbacksClassInfo.clazz,
|
|
|
|
"getExcludedDeviceNames", "()[Ljava/lang/String;");
|
|
|
|
|
2010-08-18 15:51:08 -07:00
|
|
|
GET_METHOD_ID(gCallbacksClassInfo.getMaxEventsPerSecond, gCallbacksClassInfo.clazz,
|
|
|
|
"getMaxEventsPerSecond", "()I");
|
|
|
|
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
// VirtualKeyDefinition
|
|
|
|
|
|
|
|
FIND_CLASS(gVirtualKeyDefinitionClassInfo.clazz,
|
|
|
|
"com/android/server/InputManager$VirtualKeyDefinition");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.scanCode, gVirtualKeyDefinitionClassInfo.clazz,
|
|
|
|
"scanCode", "I");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerX, gVirtualKeyDefinitionClassInfo.clazz,
|
|
|
|
"centerX", "I");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerY, gVirtualKeyDefinitionClassInfo.clazz,
|
|
|
|
"centerY", "I");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.width, gVirtualKeyDefinitionClassInfo.clazz,
|
|
|
|
"width", "I");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.height, gVirtualKeyDefinitionClassInfo.clazz,
|
|
|
|
"height", "I");
|
|
|
|
|
2010-08-30 03:02:23 -07:00
|
|
|
// InputDeviceCalibration
|
|
|
|
|
|
|
|
FIND_CLASS(gInputDeviceCalibrationClassInfo.clazz,
|
|
|
|
"com/android/server/InputManager$InputDeviceCalibration");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputDeviceCalibrationClassInfo.keys, gInputDeviceCalibrationClassInfo.clazz,
|
|
|
|
"keys", "[Ljava/lang/String;");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputDeviceCalibrationClassInfo.values, gInputDeviceCalibrationClassInfo.clazz,
|
|
|
|
"values", "[Ljava/lang/String;");
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
// InputWindow
|
|
|
|
|
|
|
|
FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
|
|
|
|
"inputChannel", "Landroid/view/InputChannel;");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
|
|
|
|
"layoutParamsFlags", "I");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
|
|
|
|
"layoutParamsType", "I");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
|
|
|
|
"dispatchingTimeoutNanos", "J");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
|
|
|
|
"frameLeft", "I");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
|
|
|
|
"frameTop", "I");
|
|
|
|
|
2010-09-01 17:01:00 -07:00
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.frameRight, gInputWindowClassInfo.clazz,
|
|
|
|
"frameRight", "I");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.frameBottom, gInputWindowClassInfo.clazz,
|
|
|
|
"frameBottom", "I");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.visibleFrameLeft, gInputWindowClassInfo.clazz,
|
|
|
|
"visibleFrameLeft", "I");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.visibleFrameTop, gInputWindowClassInfo.clazz,
|
|
|
|
"visibleFrameTop", "I");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.visibleFrameRight, gInputWindowClassInfo.clazz,
|
|
|
|
"visibleFrameRight", "I");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.visibleFrameBottom, gInputWindowClassInfo.clazz,
|
|
|
|
"visibleFrameBottom", "I");
|
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
|
|
|
|
"touchableAreaLeft", "I");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
|
|
|
|
"touchableAreaTop", "I");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
|
|
|
|
"touchableAreaRight", "I");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
|
|
|
|
"touchableAreaBottom", "I");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
|
|
|
|
"visible", "Z");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
|
|
|
|
"hasFocus", "Z");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
|
|
|
|
"hasWallpaper", "Z");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
|
|
|
|
"paused", "Z");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
|
|
|
|
"ownerPid", "I");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
|
|
|
|
"ownerUid", "I");
|
|
|
|
|
|
|
|
// InputApplication
|
|
|
|
|
|
|
|
FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication");
|
2010-06-17 20:52:56 -07:00
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
|
|
|
|
"name", "Ljava/lang/String;");
|
2010-06-17 20:52:56 -07:00
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
|
|
|
|
gInputApplicationClassInfo.clazz,
|
|
|
|
"dispatchingTimeoutNanos", "J");
|
2010-06-17 20:52:56 -07:00
|
|
|
|
2010-06-22 01:27:15 -07:00
|
|
|
GET_FIELD_ID(gInputApplicationClassInfo.token, gInputApplicationClassInfo.clazz,
|
|
|
|
"token", "Ljava/lang/Object;");
|
2010-06-17 20:52:56 -07:00
|
|
|
|
2010-07-28 15:48:59 -07:00
|
|
|
// KeyEvent
|
|
|
|
|
|
|
|
FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
|
|
|
|
|
2010-08-30 03:02:23 -07:00
|
|
|
// MotionEvent
|
2010-07-28 15:48:59 -07:00
|
|
|
|
|
|
|
FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent");
|
|
|
|
|
2010-08-30 03:02:23 -07:00
|
|
|
// InputDevice
|
|
|
|
|
|
|
|
FIND_CLASS(gInputDeviceClassInfo.clazz, "android/view/InputDevice");
|
|
|
|
|
|
|
|
GET_METHOD_ID(gInputDeviceClassInfo.ctor, gInputDeviceClassInfo.clazz,
|
|
|
|
"<init>", "()V");
|
|
|
|
|
|
|
|
GET_METHOD_ID(gInputDeviceClassInfo.addMotionRange, gInputDeviceClassInfo.clazz,
|
|
|
|
"addMotionRange", "(IFFFF)V");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputDeviceClassInfo.mId, gInputDeviceClassInfo.clazz,
|
|
|
|
"mId", "I");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputDeviceClassInfo.mName, gInputDeviceClassInfo.clazz,
|
|
|
|
"mName", "Ljava/lang/String;");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputDeviceClassInfo.mSources, gInputDeviceClassInfo.clazz,
|
|
|
|
"mSources", "I");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputDeviceClassInfo.mKeyboardType, gInputDeviceClassInfo.clazz,
|
|
|
|
"mKeyboardType", "I");
|
|
|
|
|
|
|
|
GET_FIELD_ID(gInputDeviceClassInfo.mMotionRanges, gInputDeviceClassInfo.clazz,
|
|
|
|
"mMotionRanges", "[Landroid/view/InputDevice$MotionRange;");
|
|
|
|
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-22 18:58:52 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
} /* namespace android */
|