summaryrefslogtreecommitdiffstats
path: root/include/ui
diff options
context:
space:
mode:
Diffstat (limited to 'include/ui')
-rw-r--r--include/ui/EventHub.h157
-rw-r--r--include/ui/GraphicBuffer.h13
-rw-r--r--include/ui/GraphicBufferAllocator.h2
-rw-r--r--include/ui/Input.h370
-rw-r--r--include/ui/InputDispatcher.h549
-rw-r--r--include/ui/InputManager.h142
-rw-r--r--include/ui/InputReader.h621
-rw-r--r--include/ui/InputTransport.h333
-rwxr-xr-x[-rw-r--r--]include/ui/KeycodeLabels.h10
-rw-r--r--include/ui/android_native_buffer.h9
-rw-r--r--include/ui/egl/android_natives.h103
11 files changed, 2246 insertions, 63 deletions
diff --git a/include/ui/EventHub.h b/include/ui/EventHub.h
index 3b18c77..d322a34 100644
--- a/include/ui/EventHub.h
+++ b/include/ui/EventHub.h
@@ -18,6 +18,7 @@
#ifndef _RUNTIME_EVENT_HUB_H
#define _RUNTIME_EVENT_HUB_H
+#include <android/input.h>
#include <utils/String8.h>
#include <utils/threads.h>
#include <utils/Log.h>
@@ -27,6 +28,31 @@
#include <linux/input.h>
+/* These constants are not defined in linux/input.h but they are part of the multitouch
+ * input protocol. */
+
+#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
+#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
+#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */
+#define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */
+#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */
+#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
+#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
+#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device (finger, pen, ...) */
+#define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */
+#define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */
+#define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */
+
+#define MT_TOOL_FINGER 0 /* Identifies a finger */
+#define MT_TOOL_PEN 1 /* Identifies a pen */
+
+#define SYN_MT_REPORT 2
+
+/* Convenience constants. */
+
+#define BTN_FIRST 0x100 // first button scancode
+#define BTN_LAST 0x15f // last button scancode
+
struct pollfd;
namespace android {
@@ -34,62 +60,101 @@ namespace android {
class KeyLayoutMap;
/*
- * Grand Central Station for events. With a single call to waitEvent()
- * you can wait for:
- * - input events from the keypad of a real device
- * - input events and meta-events (e.g. "quit") from the simulator
- * - synthetic events from the runtime (e.g. "URL fetch completed")
- * - real or forged "vsync" events
+ * Grand Central Station for events.
*
- * Do not instantiate this class. Instead, call startUp().
+ * The event hub aggregates input events received across all known input
+ * devices on the system, including devices that may be emulated by the simulator
+ * environment. In addition, the event hub generates fake input events to indicate
+ * when devices are added or removed.
+ *
+ * The event hub provies a stream of input events (via the getEvent function).
+ * It also supports querying the current actual state of input devices such as identifying
+ * which keys are currently down. Finally, the event hub keeps track of the capabilities of
+ * individual input devices, such as their class and the set of key codes that they support.
*/
-class EventHub : public RefBase
+class EventHubInterface : public virtual RefBase {
+protected:
+ EventHubInterface() { }
+ virtual ~EventHubInterface() { }
+
+public:
+ // Synthetic raw event type codes produced when devices are added or removed.
+ enum {
+ DEVICE_ADDED = 0x10000000,
+ DEVICE_REMOVED = 0x20000000
+ };
+
+ virtual uint32_t getDeviceClasses(int32_t deviceId) const = 0;
+
+ virtual String8 getDeviceName(int32_t deviceId) const = 0;
+
+ virtual int getAbsoluteInfo(int32_t deviceId, int axis, int *outMinValue,
+ int* outMaxValue, int* outFlat, int* outFuzz) const = 0;
+
+ virtual status_t scancodeToKeycode(int32_t deviceId, int scancode,
+ int32_t* outKeycode, uint32_t* outFlags) const = 0;
+
+ // exclude a particular device from opening
+ // this can be used to ignore input devices for sensors
+ virtual void addExcludedDevice(const char* deviceName) = 0;
+
+ /*
+ * Wait for the next event to become available and return it.
+ * After returning, the EventHub holds onto a wake lock until the next call to getEvent.
+ * This ensures that the device will not go to sleep while the event is being processed.
+ * If the device needs to remain awake longer than that, then the caller is responsible
+ * for taking care of it (say, by poking the power manager user activity timer).
+ */
+ virtual bool getEvent(int32_t* outDeviceId, int32_t* outType,
+ int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags,
+ int32_t* outValue, nsecs_t* outWhen) = 0;
+
+ /*
+ * Query current input state.
+ * deviceId may be -1 to search for the device automatically, filtered by class.
+ * deviceClasses may be -1 to ignore device class while searching.
+ */
+ virtual int32_t getScanCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t scanCode) const = 0;
+ virtual int32_t getKeyCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t keyCode) const = 0;
+ virtual int32_t getSwitchState(int32_t deviceId, int32_t deviceClasses,
+ int32_t sw) const = 0;
+
+ /*
+ * Examine key input devices for specific framework keycode support
+ */
+ virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes,
+ uint8_t* outFlags) const = 0;
+};
+
+class EventHub : public EventHubInterface
{
public:
EventHub();
-
+
status_t errorCheck() const;
+
+ virtual uint32_t getDeviceClasses(int32_t deviceId) const;
- // bit fields for classes of devices.
- enum {
- CLASS_KEYBOARD = 0x00000001,
- CLASS_ALPHAKEY = 0x00000002,
- CLASS_TOUCHSCREEN = 0x00000004,
- CLASS_TRACKBALL = 0x00000008,
- CLASS_TOUCHSCREEN_MT= 0x00000010,
- CLASS_DPAD = 0x00000020
- };
- uint32_t getDeviceClasses(int32_t deviceId) const;
-
- String8 getDeviceName(int32_t deviceId) const;
+ virtual String8 getDeviceName(int32_t deviceId) const;
- int getAbsoluteInfo(int32_t deviceId, int axis, int *outMinValue,
+ virtual int getAbsoluteInfo(int32_t deviceId, int axis, int *outMinValue,
int* outMaxValue, int* outFlat, int* outFuzz) const;
- int getSwitchState(int sw) const;
- int getSwitchState(int32_t deviceId, int sw) const;
-
- int getScancodeState(int key) const;
- int getScancodeState(int32_t deviceId, int key) const;
-
- int getKeycodeState(int key) const;
- int getKeycodeState(int32_t deviceId, int key) const;
-
- status_t scancodeToKeycode(int32_t deviceId, int scancode,
+ virtual status_t scancodeToKeycode(int32_t deviceId, int scancode,
int32_t* outKeycode, uint32_t* outFlags) const;
- // exclude a particular device from opening
- // this can be used to ignore input devices for sensors
- void addExcludedDevice(const char* deviceName);
+ virtual void addExcludedDevice(const char* deviceName);
- // special type codes when devices are added/removed.
- enum {
- DEVICE_ADDED = 0x10000000,
- DEVICE_REMOVED = 0x20000000
- };
-
- // examine key input devices for specific framework keycode support
- bool hasKeys(size_t numCodes, int32_t* keyCodes, uint8_t* outFlags);
+ virtual int32_t getScanCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t scanCode) const;
+ virtual int32_t getKeyCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t keyCode) const;
+ virtual int32_t getSwitchState(int32_t deviceId, int32_t deviceClasses,
+ int32_t sw) const;
+
+ virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const;
virtual bool getEvent(int32_t* outDeviceId, int32_t* outType,
int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags,
@@ -126,6 +191,10 @@ private:
device_t* getDevice(int32_t deviceId) const;
bool hasKeycode(device_t* device, int keycode) const;
+ int32_t getScanCodeStateLocked(device_t* device, int32_t scanCode) const;
+ int32_t getKeyCodeStateLocked(device_t* device, int32_t keyCode) const;
+ int32_t getSwitchStateLocked(device_t* device, int32_t sw) const;
+
// Protect all internal state.
mutable Mutex mLock;
@@ -151,7 +220,7 @@ private:
// device ids that report particular switches.
#ifdef EV_SW
- int32_t mSwitches[SW_MAX+1];
+ int32_t mSwitches[SW_MAX + 1];
#endif
};
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index e72b6b3..a3e85a9 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -93,10 +93,8 @@ public:
void setIndex(int index);
int getIndex() const;
- void setVerticalStride(uint32_t vstride);
- uint32_t getVerticalStride() const;
-protected:
+private:
virtual ~GraphicBuffer();
enum {
@@ -105,8 +103,12 @@ protected:
ownData = 2,
};
- inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
- inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; }
+ inline const GraphicBufferMapper& getBufferMapper() const {
+ return mBufferMapper;
+ }
+ inline GraphicBufferMapper& getBufferMapper() {
+ return mBufferMapper;
+ }
uint8_t mOwner;
private:
@@ -134,7 +136,6 @@ private:
GraphicBufferMapper& mBufferMapper;
ssize_t mInitCheck;
- uint32_t mVStride;
int mIndex;
};
diff --git a/include/ui/GraphicBufferAllocator.h b/include/ui/GraphicBufferAllocator.h
index 741d763..54b8236 100644
--- a/include/ui/GraphicBufferAllocator.h
+++ b/include/ui/GraphicBufferAllocator.h
@@ -73,9 +73,9 @@ private:
struct alloc_rec_t {
uint32_t w;
uint32_t h;
+ uint32_t s;
PixelFormat format;
uint32_t usage;
- void* vaddr;
size_t size;
};
diff --git a/include/ui/Input.h b/include/ui/Input.h
new file mode 100644
index 0000000..92ff872
--- /dev/null
+++ b/include/ui/Input.h
@@ -0,0 +1,370 @@
+/*
+ * 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.
+ */
+
+#ifndef _UI_INPUT_H
+#define _UI_INPUT_H
+
+/**
+ * Native input event structures.
+ */
+
+#include <android/input.h>
+#include <utils/Vector.h>
+#include <utils/Timers.h>
+
+/*
+ * Additional private constants not defined in ndk/ui/input.h.
+ */
+enum {
+ /*
+ * Private control to determine when an app is tracking a key sequence.
+ */
+ KEY_EVENT_FLAG_START_TRACKING = 0x40000000
+};
+
+/*
+ * Maximum number of pointers supported per motion event.
+ */
+#define MAX_POINTERS 10
+
+namespace android {
+
+/*
+ * A raw event as retrieved from the EventHub.
+ */
+struct RawEvent {
+ nsecs_t when;
+ int32_t deviceId;
+ int32_t type;
+ int32_t scanCode;
+ int32_t keyCode;
+ int32_t value;
+ uint32_t flags;
+};
+
+/*
+ * Flags that flow alongside events in the input dispatch system to help with certain
+ * policy decisions such as waking from device sleep.
+ *
+ * TODO This enumeration should probably be split up or relabeled for clarity.
+ */
+enum {
+ /* These flags originate in RawEvents and are generally set in the key map. */
+
+ POLICY_FLAG_WAKE = 0x00000001,
+ POLICY_FLAG_WAKE_DROPPED = 0x00000002,
+ POLICY_FLAG_SHIFT = 0x00000004,
+ POLICY_FLAG_CAPS_LOCK = 0x00000008,
+ POLICY_FLAG_ALT = 0x00000010,
+ POLICY_FLAG_ALT_GR = 0x00000020,
+ POLICY_FLAG_MENU = 0x00000040,
+ POLICY_FLAG_LAUNCHER = 0x00000080,
+
+ /* These flags are set by the input reader policy as it intercepts each event. */
+
+ // Indicates that the screen was off when the event was received and the event
+ // should wake the device.
+ POLICY_FLAG_WOKE_HERE = 0x10000000,
+
+ // Indicates that the screen was dim when the event was received and the event
+ // should brighten the device.
+ POLICY_FLAG_BRIGHT_HERE = 0x20000000,
+};
+
+/*
+ * Describes the basic configuration of input devices that are present.
+ */
+struct InputConfiguration {
+ enum {
+ TOUCHSCREEN_UNDEFINED = 0,
+ TOUCHSCREEN_NOTOUCH = 1,
+ TOUCHSCREEN_STYLUS = 2,
+ TOUCHSCREEN_FINGER = 3
+ };
+
+ enum {
+ KEYBOARD_UNDEFINED = 0,
+ KEYBOARD_NOKEYS = 1,
+ KEYBOARD_QWERTY = 2,
+ KEYBOARD_12KEY = 3
+ };
+
+ enum {
+ NAVIGATION_UNDEFINED = 0,
+ NAVIGATION_NONAV = 1,
+ NAVIGATION_DPAD = 2,
+ NAVIGATION_TRACKBALL = 3,
+ NAVIGATION_WHEEL = 4
+ };
+
+ int32_t touchScreen;
+ int32_t keyboard;
+ int32_t navigation;
+};
+
+/*
+ * Pointer coordinate data.
+ */
+struct PointerCoords {
+ float x;
+ float y;
+ float pressure;
+ float size;
+};
+
+/*
+ * Input events.
+ */
+struct input_event_t { };
+
+class InputEvent : public input_event_t {
+public:
+ virtual ~InputEvent() { }
+
+ virtual int32_t getType() const = 0;
+
+ inline int32_t getDeviceId() const { return mDeviceId; }
+
+ inline int32_t getNature() const { return mNature; }
+
+protected:
+ void initialize(int32_t deviceId, int32_t nature);
+
+private:
+ int32_t mDeviceId;
+ int32_t mNature;
+};
+
+/*
+ * Key events.
+ */
+class KeyEvent : public InputEvent {
+public:
+ virtual ~KeyEvent() { }
+
+ virtual int32_t getType() const { return INPUT_EVENT_TYPE_KEY; }
+
+ inline int32_t getAction() const { return mAction; }
+
+ inline int32_t getFlags() const { return mFlags; }
+
+ inline int32_t getKeyCode() const { return mKeyCode; }
+
+ inline int32_t getScanCode() const { return mScanCode; }
+
+ inline int32_t getMetaState() const { return mMetaState; }
+
+ inline int32_t getRepeatCount() const { return mRepeatCount; }
+
+ inline nsecs_t getDownTime() const { return mDownTime; }
+
+ inline nsecs_t getEventTime() const { return mEventTime; }
+
+ void initialize(
+ int32_t deviceId,
+ int32_t nature,
+ int32_t action,
+ int32_t flags,
+ int32_t keyCode,
+ int32_t scanCode,
+ int32_t metaState,
+ int32_t repeatCount,
+ nsecs_t downTime,
+ nsecs_t eventTime);
+
+private:
+ int32_t mAction;
+ int32_t mFlags;
+ int32_t mKeyCode;
+ int32_t mScanCode;
+ int32_t mMetaState;
+ int32_t mRepeatCount;
+ nsecs_t mDownTime;
+ nsecs_t mEventTime;
+};
+
+/*
+ * Motion events.
+ */
+class MotionEvent : public InputEvent {
+public:
+ virtual ~MotionEvent() { }
+
+ virtual int32_t getType() const { return INPUT_EVENT_TYPE_MOTION; }
+
+ inline int32_t getAction() const { return mAction; }
+
+ inline int32_t getEdgeFlags() const { return mEdgeFlags; }
+
+ inline int32_t getMetaState() const { return mMetaState; }
+
+ inline float getXOffset() const { return mXOffset; }
+
+ inline float getYOffset() const { return mYOffset; }
+
+ inline float getXPrecision() const { return mXPrecision; }
+
+ inline float getYPrecision() const { return mYPrecision; }
+
+ inline nsecs_t getDownTime() const { return mDownTime; }
+
+ inline size_t getPointerCount() const { return mPointerIds.size(); }
+
+ inline int32_t getPointerId(size_t pointerIndex) const { return mPointerIds[pointerIndex]; }
+
+ inline nsecs_t getEventTime() const { return mSampleEventTimes[getHistorySize()]; }
+
+ inline float getRawX(size_t pointerIndex) const {
+ return getCurrentPointerCoords(pointerIndex).x;
+ }
+
+ inline float getRawY(size_t pointerIndex) const {
+ return getCurrentPointerCoords(pointerIndex).y;
+ }
+
+ inline float getX(size_t pointerIndex) const {
+ return getRawX(pointerIndex) + mXOffset;
+ }
+
+ inline float getY(size_t pointerIndex) const {
+ return getRawY(pointerIndex) + mYOffset;
+ }
+
+ inline float getPressure(size_t pointerIndex) const {
+ return getCurrentPointerCoords(pointerIndex).pressure;
+ }
+
+ inline float getSize(size_t pointerIndex) const {
+ return getCurrentPointerCoords(pointerIndex).size;
+ }
+
+ inline size_t getHistorySize() const { return mSampleEventTimes.size() - 1; }
+
+ inline nsecs_t getHistoricalEventTime(size_t historicalIndex) const {
+ return mSampleEventTimes[historicalIndex];
+ }
+
+ inline float getHistoricalRawX(size_t pointerIndex, size_t historicalIndex) const {
+ return getHistoricalPointerCoords(pointerIndex, historicalIndex).x;
+ }
+
+ inline float getHistoricalRawY(size_t pointerIndex, size_t historicalIndex) const {
+ return getHistoricalPointerCoords(pointerIndex, historicalIndex).y;
+ }
+
+ inline float getHistoricalX(size_t pointerIndex, size_t historicalIndex) const {
+ return getHistoricalRawX(pointerIndex, historicalIndex) + mXOffset;
+ }
+
+ inline float getHistoricalY(size_t pointerIndex, size_t historicalIndex) const {
+ return getHistoricalRawY(pointerIndex, historicalIndex) + mYOffset;
+ }
+
+ inline float getHistoricalPressure(size_t pointerIndex, size_t historicalIndex) const {
+ return getHistoricalPointerCoords(pointerIndex, historicalIndex).pressure;
+ }
+
+ inline float getHistoricalSize(size_t pointerIndex, size_t historicalIndex) const {
+ return getHistoricalPointerCoords(pointerIndex, historicalIndex).size;
+ }
+
+ void initialize(
+ int32_t deviceId,
+ int32_t nature,
+ int32_t action,
+ int32_t edgeFlags,
+ int32_t metaState,
+ float xOffset,
+ float yOffset,
+ float xPrecision,
+ float yPrecision,
+ nsecs_t downTime,
+ nsecs_t eventTime,
+ size_t pointerCount,
+ const int32_t* pointerIds,
+ const PointerCoords* pointerCoords);
+
+ void addSample(
+ nsecs_t eventTime,
+ const PointerCoords* pointerCoords);
+
+ void offsetLocation(float xOffset, float yOffset);
+
+ // Low-level accessors.
+ inline const int32_t* getPointerIds() const { return mPointerIds.array(); }
+ inline const nsecs_t* getSampleEventTimes() const { return mSampleEventTimes.array(); }
+ inline const PointerCoords* getSamplePointerCoords() const {
+ return mSamplePointerCoords.array();
+ }
+
+private:
+ int32_t mAction;
+ int32_t mEdgeFlags;
+ int32_t mMetaState;
+ float mXOffset;
+ float mYOffset;
+ float mXPrecision;
+ float mYPrecision;
+ nsecs_t mDownTime;
+ Vector<int32_t> mPointerIds;
+ Vector<nsecs_t> mSampleEventTimes;
+ Vector<PointerCoords> mSamplePointerCoords;
+
+ inline const PointerCoords& getCurrentPointerCoords(size_t pointerIndex) const {
+ return mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
+ }
+
+ inline const PointerCoords& getHistoricalPointerCoords(
+ size_t pointerIndex, size_t historicalIndex) const {
+ return mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex];
+ }
+};
+
+/*
+ * Input event factory.
+ */
+class InputEventFactoryInterface {
+protected:
+ virtual ~InputEventFactoryInterface() { }
+
+public:
+ InputEventFactoryInterface() { }
+
+ virtual KeyEvent* createKeyEvent() = 0;
+ virtual MotionEvent* createMotionEvent() = 0;
+};
+
+/*
+ * A simple input event factory implementation that uses a single preallocated instance
+ * of each type of input event that are reused for each request.
+ */
+class PreallocatedInputEventFactory : public InputEventFactoryInterface {
+public:
+ PreallocatedInputEventFactory() { }
+ virtual ~PreallocatedInputEventFactory() { }
+
+ virtual KeyEvent* createKeyEvent() { return & mKeyEvent; }
+ virtual MotionEvent* createMotionEvent() { return & mMotionEvent; }
+
+private:
+ KeyEvent mKeyEvent;
+ MotionEvent mMotionEvent;
+};
+
+
+} // namespace android
+
+#endif // _UI_INPUT_H
diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h
new file mode 100644
index 0000000..80a20c9
--- /dev/null
+++ b/include/ui/InputDispatcher.h
@@ -0,0 +1,549 @@
+/*
+ * 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.
+ */
+
+#ifndef _UI_INPUT_DISPATCHER_H
+#define _UI_INPUT_DISPATCHER_H
+
+#include <ui/Input.h>
+#include <ui/InputTransport.h>
+#include <utils/KeyedVector.h>
+#include <utils/Vector.h>
+#include <utils/threads.h>
+#include <utils/Timers.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/PollLoop.h>
+#include <utils/Pool.h>
+
+#include <stddef.h>
+#include <unistd.h>
+
+
+namespace android {
+
+/*
+ * An input target specifies how an input event is to be dispatched to a particular window
+ * including the window's input channel, control flags, a timeout, and an X / Y offset to
+ * be added to input event coordinates to compensate for the absolute position of the
+ * window area.
+ */
+struct InputTarget {
+ enum {
+ /* This flag indicates that subsequent event delivery should be held until the
+ * current event is delivered to this target or a timeout occurs. */
+ FLAG_SYNC = 0x01,
+
+ /* This flag indicates that a MotionEvent with ACTION_DOWN falls outside of the area of
+ * this target and so should instead be delivered as an ACTION_OUTSIDE to this target. */
+ FLAG_OUTSIDE = 0x02,
+
+ /* This flag indicates that a KeyEvent or MotionEvent is being canceled.
+ * In the case of a key event, it should be delivered with KeyEvent.FLAG_CANCELED set.
+ * In the case of a motion event, it should be delivered as MotionEvent.ACTION_CANCEL. */
+ FLAG_CANCEL = 0x04
+ };
+
+ // The input channel to be targeted.
+ sp<InputChannel> inputChannel;
+
+ // Flags for the input target.
+ int32_t flags;
+
+ // The timeout for event delivery to this target in nanoseconds. Or -1 if none.
+ nsecs_t timeout;
+
+ // The x and y offset to add to a MotionEvent as it is delivered.
+ // (ignored for KeyEvents)
+ float xOffset, yOffset;
+};
+
+/*
+ * Input dispatcher policy interface.
+ *
+ * The input reader policy is used by the input reader to interact with the Window Manager
+ * and other system components.
+ *
+ * The actual implementation is partially supported by callbacks into the DVM
+ * via JNI. This interface is also mocked in the unit tests.
+ */
+class InputDispatcherPolicyInterface : public virtual RefBase {
+protected:
+ InputDispatcherPolicyInterface() { }
+ virtual ~InputDispatcherPolicyInterface() { }
+
+public:
+ /* Notifies the system that a configuration change has occurred. */
+ virtual void notifyConfigurationChanged(nsecs_t when) = 0;
+
+ /* Notifies the system that an input channel is unrecoverably broken. */
+ virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) = 0;
+
+ /* Notifies the system that an input channel is not responding. */
+ virtual void notifyInputChannelANR(const sp<InputChannel>& inputChannel) = 0;
+
+ /* Notifies the system that an input channel recovered from ANR. */
+ virtual void notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel) = 0;
+
+ /* Gets the key repeat timeout or -1 if automatic key repeating is disabled. */
+ virtual nsecs_t getKeyRepeatTimeout() = 0;
+
+ /* Gets the input targets for a key event. */
+ virtual void getKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
+ Vector<InputTarget>& outTargets) = 0;
+
+ /* Gets the input targets for a motion event. */
+ virtual void getMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
+ Vector<InputTarget>& outTargets) = 0;
+};
+
+
+/* Notifies the system about input events generated by the input reader.
+ * The dispatcher is expected to be mostly asynchronous. */
+class InputDispatcherInterface : public virtual RefBase {
+protected:
+ InputDispatcherInterface() { }
+ virtual ~InputDispatcherInterface() { }
+
+public:
+ /* Runs a single iteration of the dispatch loop.
+ * Nominally processes one queued event, a timeout, or a response from an input consumer.
+ *
+ * This method should only be called on the input dispatcher thread.
+ */
+ virtual void dispatchOnce() = 0;
+
+ /* Notifies the dispatcher about new events.
+ *
+ * These methods should only be called on the input reader thread.
+ */
+ virtual void notifyConfigurationChanged(nsecs_t eventTime) = 0;
+ virtual void notifyAppSwitchComing(nsecs_t eventTime) = 0;
+ virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t nature,
+ uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
+ int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0;
+ virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t nature,
+ uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
+ uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
+ float xPrecision, float yPrecision, nsecs_t downTime) = 0;
+
+ /* Registers or unregister input channels that may be used as targets for input events.
+ *
+ * These methods may be called on any thread (usually by the input manager).
+ */
+ virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel) = 0;
+ virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
+};
+
+/* Dispatches events to input targets. Some functions of the input dispatcher, such as
+ * identifying input targets, are controlled by a separate policy object.
+ *
+ * IMPORTANT INVARIANT:
+ * Because the policy can potentially block or cause re-entrance into the input dispatcher,
+ * the input dispatcher never calls into the policy while holding its internal locks.
+ * The implementation is also carefully designed to recover from scenarios such as an
+ * input channel becoming unregistered while identifying input targets or processing timeouts.
+ *
+ * Methods marked 'Locked' must be called with the lock acquired.
+ *
+ * Methods marked 'LockedInterruptible' must be called with the lock acquired but
+ * may during the course of their execution release the lock, call into the policy, and
+ * then reacquire the lock. The caller is responsible for recovering gracefully.
+ *
+ * A 'LockedInterruptible' method may called a 'Locked' method, but NOT vice-versa.
+ */
+class InputDispatcher : public InputDispatcherInterface {
+protected:
+ virtual ~InputDispatcher();
+
+public:
+ explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy);
+
+ virtual void dispatchOnce();
+
+ virtual void notifyConfigurationChanged(nsecs_t eventTime);
+ virtual void notifyAppSwitchComing(nsecs_t eventTime);
+ virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t nature,
+ uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
+ int32_t scanCode, int32_t metaState, nsecs_t downTime);
+ virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t nature,
+ uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
+ uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
+ float xPrecision, float yPrecision, nsecs_t downTime);
+
+ virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel);
+ virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
+
+private:
+ template <typename T>
+ struct Link {
+ T* next;
+ T* prev;
+ };
+
+ struct EventEntry : Link<EventEntry> {
+ enum {
+ TYPE_SENTINEL,
+ TYPE_CONFIGURATION_CHANGED,
+ TYPE_KEY,
+ TYPE_MOTION
+ };
+
+ int32_t refCount;
+ int32_t type;
+ nsecs_t eventTime;
+
+ bool dispatchInProgress; // initially false, set to true while dispatching
+ };
+
+ struct ConfigurationChangedEntry : EventEntry {
+ };
+
+ struct KeyEntry : EventEntry {
+ int32_t deviceId;
+ int32_t nature;
+ uint32_t policyFlags;
+ int32_t action;
+ int32_t flags;
+ int32_t keyCode;
+ int32_t scanCode;
+ int32_t metaState;
+ int32_t repeatCount;
+ nsecs_t downTime;
+ };
+
+ struct MotionSample {
+ MotionSample* next;
+
+ nsecs_t eventTime;
+ PointerCoords pointerCoords[MAX_POINTERS];
+ };
+
+ struct MotionEntry : EventEntry {
+ int32_t deviceId;
+ int32_t nature;
+ uint32_t policyFlags;
+ int32_t action;
+ int32_t metaState;
+ int32_t edgeFlags;
+ float xPrecision;
+ float yPrecision;
+ nsecs_t downTime;
+ uint32_t pointerCount;
+ int32_t pointerIds[MAX_POINTERS];
+
+ // Linked list of motion samples associated with this motion event.
+ MotionSample firstSample;
+ MotionSample* lastSample;
+ };
+
+ // Tracks the progress of dispatching a particular event to a particular connection.
+ struct DispatchEntry : Link<DispatchEntry> {
+ EventEntry* eventEntry; // the event to dispatch
+ int32_t targetFlags;
+ float xOffset;
+ float yOffset;
+ nsecs_t timeout;
+
+ // True if dispatch has started.
+ bool inProgress;
+
+ // For motion events:
+ // Pointer to the first motion sample to dispatch in this cycle.
+ // Usually NULL to indicate that the list of motion samples begins at
+ // MotionEntry::firstSample. Otherwise, some samples were dispatched in a previous
+ // cycle and this pointer indicates the location of the first remainining sample
+ // to dispatch during the current cycle.
+ MotionSample* headMotionSample;
+ // Pointer to a motion sample to dispatch in the next cycle if the dispatcher was
+ // unable to send all motion samples during this cycle. On the next cycle,
+ // headMotionSample will be initialized to tailMotionSample and tailMotionSample
+ // will be set to NULL.
+ MotionSample* tailMotionSample;
+ };
+
+ // A command entry captures state and behavior for an action to be performed in the
+ // dispatch loop after the initial processing has taken place. It is essentially
+ // a kind of continuation used to postpone sensitive policy interactions to a point
+ // in the dispatch loop where it is safe to release the lock (generally after finishing
+ // the critical parts of the dispatch cycle).
+ //
+ // The special thing about commands is that they can voluntarily release and reacquire
+ // the dispatcher lock at will. Initially when the command starts running, the
+ // dispatcher lock is held. However, if the command needs to call into the policy to
+ // do some work, it can release the lock, do the work, then reacquire the lock again
+ // before returning.
+ //
+ // This mechanism is a bit clunky but it helps to preserve the invariant that the dispatch
+ // never calls into the policy while holding its lock.
+ //
+ // Commands are implicitly 'LockedInterruptible'.
+ struct CommandEntry;
+ typedef void (InputDispatcher::*Command)(CommandEntry* commandEntry);
+
+ struct CommandEntry : Link<CommandEntry> {
+ CommandEntry();
+ ~CommandEntry();
+
+ Command command;
+
+ // parameters for the command (usage varies by command)
+ sp<InputChannel> inputChannel;
+ };
+
+ // Generic queue implementation.
+ template <typename T>
+ struct Queue {
+ T head;
+ T tail;
+
+ inline Queue() {
+ head.prev = NULL;
+ head.next = & tail;
+ tail.prev = & head;
+ tail.next = NULL;
+ }
+
+ inline bool isEmpty() {
+ return head.next == & tail;
+ }
+
+ inline void enqueueAtTail(T* entry) {
+ T* last = tail.prev;
+ last->next = entry;
+ entry->prev = last;
+ entry->next = & tail;
+ tail.prev = entry;
+ }
+
+ inline void enqueueAtHead(T* entry) {
+ T* first = head.next;
+ head.next = entry;
+ entry->prev = & head;
+ entry->next = first;
+ first->prev = entry;
+ }
+
+ inline void dequeue(T* entry) {
+ entry->prev->next = entry->next;
+ entry->next->prev = entry->prev;
+ }
+
+ inline T* dequeueAtHead() {
+ T* first = head.next;
+ dequeue(first);
+ return first;
+ }
+ };
+
+ /* Allocates queue entries and performs reference counting as needed. */
+ class Allocator {
+ public:
+ Allocator();
+
+ ConfigurationChangedEntry* obtainConfigurationChangedEntry();
+ KeyEntry* obtainKeyEntry();
+ MotionEntry* obtainMotionEntry();
+ DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry);
+ CommandEntry* obtainCommandEntry(Command command);
+
+ void releaseEventEntry(EventEntry* entry);
+ void releaseConfigurationChangedEntry(ConfigurationChangedEntry* entry);
+ void releaseKeyEntry(KeyEntry* entry);
+ void releaseMotionEntry(MotionEntry* entry);
+ void releaseDispatchEntry(DispatchEntry* entry);
+ void releaseCommandEntry(CommandEntry* entry);
+
+ void appendMotionSample(MotionEntry* motionEntry,
+ nsecs_t eventTime, int32_t pointerCount, const PointerCoords* pointerCoords);
+
+ private:
+ Pool<ConfigurationChangedEntry> mConfigurationChangeEntryPool;
+ Pool<KeyEntry> mKeyEntryPool;
+ Pool<MotionEntry> mMotionEntryPool;
+ Pool<MotionSample> mMotionSamplePool;
+ Pool<DispatchEntry> mDispatchEntryPool;
+ Pool<CommandEntry> mCommandEntryPool;
+ };
+
+ /* Manages the dispatch state associated with a single input channel. */
+ class Connection : public RefBase {
+ protected:
+ virtual ~Connection();
+
+ public:
+ enum Status {
+ // Everything is peachy.
+ STATUS_NORMAL,
+ // An unrecoverable communication error has occurred.
+ STATUS_BROKEN,
+ // The client is not responding.
+ STATUS_NOT_RESPONDING,
+ // The input channel has been unregistered.
+ STATUS_ZOMBIE
+ };
+
+ Status status;
+ sp<InputChannel> inputChannel;
+ InputPublisher inputPublisher;
+ Queue<DispatchEntry> outboundQueue;
+ nsecs_t nextTimeoutTime; // next timeout time (LONG_LONG_MAX if none)
+
+ nsecs_t lastEventTime; // the time when the event was originally captured
+ nsecs_t lastDispatchTime; // the time when the last event was dispatched
+ nsecs_t lastANRTime; // the time when the last ANR was recorded
+
+ explicit Connection(const sp<InputChannel>& inputChannel);
+
+ inline const char* getInputChannelName() const { return inputChannel->getName().string(); }
+
+ const char* getStatusLabel() const;
+
+ // Finds a DispatchEntry in the outbound queue associated with the specified event.
+ // Returns NULL if not found.
+ DispatchEntry* findQueuedDispatchEntryForEvent(const EventEntry* eventEntry) const;
+
+ // Determine whether this connection has a pending synchronous dispatch target.
+ // Since there can only ever be at most one such target at a time, if there is one,
+ // it must be at the tail because nothing else can be enqueued after it.
+ inline bool hasPendingSyncTarget() {
+ return ! outboundQueue.isEmpty()
+ && (outboundQueue.tail.prev->targetFlags & InputTarget::FLAG_SYNC);
+ }
+
+ // Gets the time since the current event was originally obtained from the input driver.
+ inline double getEventLatencyMillis(nsecs_t currentTime) {
+ return (currentTime - lastEventTime) / 1000000.0;
+ }
+
+ // Gets the time since the current event entered the outbound dispatch queue.
+ inline double getDispatchLatencyMillis(nsecs_t currentTime) {
+ return (currentTime - lastDispatchTime) / 1000000.0;
+ }
+
+ // Gets the time since the current event ANR was declared, if applicable.
+ inline double getANRLatencyMillis(nsecs_t currentTime) {
+ return (currentTime - lastANRTime) / 1000000.0;
+ }
+
+ status_t initialize();
+ };
+
+ sp<InputDispatcherPolicyInterface> mPolicy;
+
+ Mutex mLock;
+
+ Allocator mAllocator;
+ sp<PollLoop> mPollLoop;
+
+ Queue<EventEntry> mInboundQueue;
+ Queue<CommandEntry> mCommandQueue;
+
+ // All registered connections mapped by receive pipe file descriptor.
+ KeyedVector<int, sp<Connection> > mConnectionsByReceiveFd;
+
+ // Active connections are connections that have a non-empty outbound queue.
+ Vector<Connection*> mActiveConnections;
+
+ // Preallocated key and motion event objects used only to ask the input dispatcher policy
+ // for the targets of an event that is to be dispatched.
+ KeyEvent mReusableKeyEvent;
+ MotionEvent mReusableMotionEvent;
+
+ // The input targets that were most recently identified for dispatch.
+ // If there is a synchronous event dispatch in progress, the current input targets will
+ // remain unchanged until the dispatch has completed or been aborted.
+ Vector<InputTarget> mCurrentInputTargets;
+ bool mCurrentInputTargetsValid; // false while targets are being recomputed
+
+ // Key repeat tracking.
+ // XXX Move this up to the input reader instead.
+ struct KeyRepeatState {
+ KeyEntry* lastKeyEntry; // or null if no repeat
+ nsecs_t nextRepeatTime;
+ } mKeyRepeatState;
+
+ void resetKeyRepeatLocked();
+
+ // Deferred command processing.
+ bool runCommandsLockedInterruptible();
+ CommandEntry* postCommandLocked(Command command);
+
+ // Process events that have just been dequeued from the head of the input queue.
+ void processConfigurationChangedLockedInterruptible(
+ nsecs_t currentTime, ConfigurationChangedEntry* entry);
+ void processKeyLockedInterruptible(
+ nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout);
+ void processKeyRepeatLockedInterruptible(
+ nsecs_t currentTime, nsecs_t keyRepeatTimeout);
+ void processMotionLockedInterruptible(
+ nsecs_t currentTime, MotionEntry* entry);
+
+ // Identify input targets for an event and dispatch to them.
+ void identifyInputTargetsAndDispatchKeyLockedInterruptible(
+ nsecs_t currentTime, KeyEntry* entry);
+ void identifyInputTargetsAndDispatchMotionLockedInterruptible(
+ nsecs_t currentTime, MotionEntry* entry);
+ void dispatchEventToCurrentInputTargetsLocked(
+ nsecs_t currentTime, EventEntry* entry, bool resumeWithAppendedMotionSample);
+
+ // Manage the dispatch cycle for a single connection.
+ void prepareDispatchCycleLocked(nsecs_t currentTime, Connection* connection,
+ EventEntry* eventEntry, const InputTarget* inputTarget,
+ bool resumeWithAppendedMotionSample);
+ void startDispatchCycleLocked(nsecs_t currentTime, Connection* connection);
+ void finishDispatchCycleLocked(nsecs_t currentTime, Connection* connection);
+ bool timeoutDispatchCycleLocked(nsecs_t currentTime, Connection* connection);
+ bool abortDispatchCycleLocked(nsecs_t currentTime, Connection* connection,
+ bool broken);
+ static bool handleReceiveCallback(int receiveFd, int events, void* data);
+
+ // Add or remove a connection to the mActiveConnections vector.
+ void activateConnectionLocked(Connection* connection);
+ void deactivateConnectionLocked(Connection* connection);
+
+ // Outbound policy interactions.
+ void doNotifyConfigurationChangedLockedInterruptible(CommandEntry* commandEntry);
+
+ // Interesting events that we might like to log or tell the framework about.
+ void onDispatchCycleStartedLocked(
+ nsecs_t currentTime, Connection* connection);
+ void onDispatchCycleFinishedLocked(
+ nsecs_t currentTime, Connection* connection, bool recoveredFromANR);
+ void onDispatchCycleANRLocked(
+ nsecs_t currentTime, Connection* connection);
+ void onDispatchCycleBrokenLocked(
+ nsecs_t currentTime, Connection* connection);
+
+ void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry);
+ void doNotifyInputChannelANRLockedInterruptible(CommandEntry* commandEntry);
+ void doNotifyInputChannelRecoveredFromANRLockedInterruptible(CommandEntry* commandEntry);
+};
+
+/* Enqueues and dispatches input events, endlessly. */
+class InputDispatcherThread : public Thread {
+public:
+ explicit InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher);
+ ~InputDispatcherThread();
+
+private:
+ virtual bool threadLoop();
+
+ sp<InputDispatcherInterface> mDispatcher;
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_DISPATCHER_PRIV_H
diff --git a/include/ui/InputManager.h b/include/ui/InputManager.h
new file mode 100644
index 0000000..3872c26
--- /dev/null
+++ b/include/ui/InputManager.h
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+
+#ifndef _UI_INPUT_MANAGER_H
+#define _UI_INPUT_MANAGER_H
+
+/**
+ * Native input manager.
+ */
+
+#include <ui/EventHub.h>
+#include <ui/Input.h>
+#include <utils/Errors.h>
+#include <utils/Vector.h>
+#include <utils/Timers.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+
+namespace android {
+
+class InputChannel;
+
+class InputReaderInterface;
+class InputReaderPolicyInterface;
+class InputReaderThread;
+
+class InputDispatcherInterface;
+class InputDispatcherPolicyInterface;
+class InputDispatcherThread;
+
+/*
+ * The input manager is the core of the system event processing.
+ *
+ * The input manager uses two threads.
+ *
+ * 1. The InputReaderThread (called "InputReader") reads and preprocesses raw input events,
+ * applies policy, and posts messages to a queue managed by the DispatcherThread.
+ * 2. The InputDispatcherThread (called "InputDispatcher") thread waits for new events on the
+ * queue and asynchronously dispatches them to applications.
+ *
+ * By design, the InputReaderThread class and InputDispatcherThread class do not share any
+ * internal state. Moreover, all communication is done one way from the InputReaderThread
+ * into the InputDispatcherThread and never the reverse. Both classes may interact with the
+ * InputDispatchPolicy, however.
+ *
+ * The InputManager class never makes any calls into Java itself. Instead, the
+ * InputDispatchPolicy is responsible for performing all external interactions with the
+ * system, including calling DVM services.
+ */
+class InputManagerInterface : public virtual RefBase {
+protected:
+ InputManagerInterface() { }
+ virtual ~InputManagerInterface() { }
+
+public:
+ /* Starts the input manager threads. */
+ virtual status_t start() = 0;
+
+ /* Stops the input manager threads and waits for them to exit. */
+ virtual status_t stop() = 0;
+
+ /* Registers an input channel prior to using it as the target of an event. */
+ virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel) = 0;
+
+ /* Unregisters an input channel. */
+ virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
+
+ /* Gets input device configuration. */
+ virtual void getInputConfiguration(InputConfiguration* outConfiguration) const = 0;
+
+ /*
+ * Queries current input state.
+ * deviceId may be -1 to search for the device automatically, filtered by class.
+ * deviceClasses may be -1 to ignore device class while searching.
+ */
+ virtual int32_t getScanCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t scanCode) const = 0;
+ virtual int32_t getKeyCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t keyCode) const = 0;
+ virtual int32_t getSwitchState(int32_t deviceId, int32_t deviceClasses,
+ int32_t sw) const = 0;
+
+ /* Determines whether physical keys exist for the given framework-domain key codes. */
+ virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const = 0;
+};
+
+class InputManager : public InputManagerInterface {
+protected:
+ virtual ~InputManager();
+
+public:
+ InputManager(
+ const sp<EventHubInterface>& eventHub,
+ const sp<InputReaderPolicyInterface>& readerPolicy,
+ const sp<InputDispatcherPolicyInterface>& dispatcherPolicy);
+
+ // (used for testing purposes)
+ InputManager(
+ const sp<InputReaderInterface>& reader,
+ const sp<InputDispatcherInterface>& dispatcher);
+
+ virtual status_t start();
+ virtual status_t stop();
+
+ virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel);
+ virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
+
+ virtual void getInputConfiguration(InputConfiguration* outConfiguration) const;
+ virtual int32_t getScanCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t scanCode) const;
+ virtual int32_t getKeyCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t keyCode) const;
+ virtual int32_t getSwitchState(int32_t deviceId, int32_t deviceClasses,
+ int32_t sw) const;
+ virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const;
+
+private:
+ sp<InputReaderInterface> mReader;
+ sp<InputReaderThread> mReaderThread;
+
+ sp<InputDispatcherInterface> mDispatcher;
+ sp<InputDispatcherThread> mDispatcherThread;
+
+ void initialize();
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_MANAGER_H
diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h
new file mode 100644
index 0000000..d76b8fe
--- /dev/null
+++ b/include/ui/InputReader.h
@@ -0,0 +1,621 @@
+/*
+ * 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.
+ */
+
+#ifndef _UI_INPUT_READER_H
+#define _UI_INPUT_READER_H
+
+#include <ui/EventHub.h>
+#include <ui/Input.h>
+#include <ui/InputDispatcher.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+#include <utils/Timers.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/BitSet.h>
+
+#include <stddef.h>
+#include <unistd.h>
+
+/* Maximum pointer id value supported.
+ * (This is limited by our use of BitSet32 to track pointer assignments.) */
+#define MAX_POINTER_ID 32
+
+/* Maximum number of historical samples to average. */
+#define AVERAGING_HISTORY_SIZE 5
+
+
+namespace android {
+
+extern int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState);
+extern int32_t rotateKeyCode(int32_t keyCode, int32_t orientation);
+
+/*
+ * An input device structure tracks the state of a single input device.
+ *
+ * This structure is only used by ReaderThread and is not intended to be shared with
+ * DispatcherThread (because that would require locking). This works out fine because
+ * DispatcherThread is only interested in cooked event data anyways and does not need
+ * any of the low-level data from InputDevice.
+ */
+struct InputDevice {
+ struct AbsoluteAxisInfo {
+ int32_t minValue; // minimum value
+ int32_t maxValue; // maximum value
+ int32_t range; // range of values, equal to maxValue - minValue
+ int32_t flat; // center flat position, eg. flat == 8 means center is between -8 and 8
+ int32_t fuzz; // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise
+ };
+
+ struct VirtualKey {
+ int32_t keyCode;
+ int32_t scanCode;
+ uint32_t flags;
+
+ // computed hit box, specified in touch screen coords based on known display size
+ int32_t hitLeft;
+ int32_t hitTop;
+ int32_t hitRight;
+ int32_t hitBottom;
+
+ inline bool isHit(int32_t x, int32_t y) const {
+ return x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom;
+ }
+ };
+
+ struct KeyboardState {
+ struct Current {
+ int32_t metaState;
+ nsecs_t downTime; // time of most recent key down
+ } current;
+
+ void reset();
+ };
+
+ struct TrackballState {
+ struct Accumulator {
+ enum {
+ FIELD_BTN_MOUSE = 1,
+ FIELD_REL_X = 2,
+ FIELD_REL_Y = 4
+ };
+
+ uint32_t fields;
+
+ bool btnMouse;
+ int32_t relX;
+ int32_t relY;
+
+ inline void clear() {
+ fields = 0;
+ }
+
+ inline bool isDirty() {
+ return fields != 0;
+ }
+ } accumulator;
+
+ struct Current {
+ bool down;
+ nsecs_t downTime;
+ } current;
+
+ struct Precalculated {
+ float xScale;
+ float yScale;
+ float xPrecision;
+ float yPrecision;
+ } precalculated;
+
+ void reset();
+ };
+
+ struct SingleTouchScreenState {
+ struct Accumulator {
+ enum {
+ FIELD_BTN_TOUCH = 1,
+ FIELD_ABS_X = 2,
+ FIELD_ABS_Y = 4,
+ FIELD_ABS_PRESSURE = 8,
+ FIELD_ABS_TOOL_WIDTH = 16
+ };
+
+ uint32_t fields;
+
+ bool btnTouch;
+ int32_t absX;
+ int32_t absY;
+ int32_t absPressure;
+ int32_t absToolWidth;
+
+ inline void clear() {
+ fields = 0;
+ }
+
+ inline bool isDirty() {
+ return fields != 0;
+ }
+ } accumulator;
+
+ struct Current {
+ bool down;
+ int32_t x;
+ int32_t y;
+ int32_t pressure;
+ int32_t size;
+ } current;
+
+ void reset();
+ };
+
+ struct MultiTouchScreenState {
+ struct Accumulator {
+ enum {
+ FIELD_ABS_MT_POSITION_X = 1,
+ FIELD_ABS_MT_POSITION_Y = 2,
+ FIELD_ABS_MT_TOUCH_MAJOR = 4,
+ FIELD_ABS_MT_WIDTH_MAJOR = 8,
+ FIELD_ABS_MT_TRACKING_ID = 16
+ };
+
+ uint32_t pointerCount;
+ struct Pointer {
+ uint32_t fields;
+
+ int32_t absMTPositionX;
+ int32_t absMTPositionY;
+ int32_t absMTTouchMajor;
+ int32_t absMTWidthMajor;
+ int32_t absMTTrackingId;
+
+ inline void clear() {
+ fields = 0;
+ }
+ } pointers[MAX_POINTERS + 1]; // + 1 to remove the need for extra range checks
+
+ inline void clear() {
+ pointerCount = 0;
+ pointers[0].clear();
+ }
+
+ inline bool isDirty() {
+ return pointerCount != 0;
+ }
+ } accumulator;
+
+ void reset();
+ };
+
+ struct PointerData {
+ uint32_t id;
+ int32_t x;
+ int32_t y;
+ int32_t pressure;
+ int32_t size;
+ };
+
+ struct TouchData {
+ uint32_t pointerCount;
+ PointerData pointers[MAX_POINTERS];
+ BitSet32 idBits;
+ uint32_t idToIndex[MAX_POINTER_ID];
+
+ void copyFrom(const TouchData& other);
+
+ inline void clear() {
+ pointerCount = 0;
+ idBits.clear();
+ }
+ };
+
+ // common state used for both single-touch and multi-touch screens after the initial
+ // touch decoding has been performed
+ struct TouchScreenState {
+ Vector<VirtualKey> virtualKeys;
+
+ struct Parameters {
+ bool useBadTouchFilter;
+ bool useJumpyTouchFilter;
+ bool useAveragingTouchFilter;
+
+ AbsoluteAxisInfo xAxis;
+ AbsoluteAxisInfo yAxis;
+ AbsoluteAxisInfo pressureAxis;
+ AbsoluteAxisInfo sizeAxis;
+ } parameters;
+
+ // The touch data of the current sample being processed.
+ TouchData currentTouch;
+
+ // The touch data of the previous sample that was processed. This is updated
+ // incrementally while the current sample is being processed.
+ TouchData lastTouch;
+
+ // The time the primary pointer last went down.
+ nsecs_t downTime;
+
+ struct CurrentVirtualKeyState {
+ bool down;
+ nsecs_t downTime;
+ int32_t keyCode;
+ int32_t scanCode;
+ } currentVirtualKey;
+
+ struct AveragingTouchFilterState {
+ // Individual history tracks are stored by pointer id
+ uint32_t historyStart[MAX_POINTERS];
+ uint32_t historyEnd[MAX_POINTERS];
+ struct {
+ struct {
+ int32_t x;
+ int32_t y;
+ int32_t pressure;
+ } pointers[MAX_POINTERS];
+ } historyData[AVERAGING_HISTORY_SIZE];
+ } averagingTouchFilter;
+
+ struct JumpTouchFilterState {
+ int32_t jumpyPointsDropped;
+ } jumpyTouchFilter;
+
+ struct Precalculated {
+ float xScale;
+ float yScale;
+ float pressureScale;
+ float sizeScale;
+ } precalculated;
+
+ void reset();
+
+ bool applyBadTouchFilter();
+ bool applyJumpyTouchFilter();
+ void applyAveragingTouchFilter();
+ void calculatePointerIds();
+
+ bool isPointInsideDisplay(int32_t x, int32_t y) const;
+ };
+
+ InputDevice(int32_t id, uint32_t classes, String8 name);
+
+ int32_t id;
+ uint32_t classes;
+ String8 name;
+ bool ignored;
+
+ KeyboardState keyboard;
+ TrackballState trackball;
+ TouchScreenState touchScreen;
+ union {
+ SingleTouchScreenState singleTouchScreen;
+ MultiTouchScreenState multiTouchScreen;
+ };
+
+ void reset();
+
+ inline bool isKeyboard() const { return classes & INPUT_DEVICE_CLASS_KEYBOARD; }
+ inline bool isAlphaKey() const { return classes & INPUT_DEVICE_CLASS_ALPHAKEY; }
+ inline bool isTrackball() const { return classes & INPUT_DEVICE_CLASS_TRACKBALL; }
+ inline bool isDPad() const { return classes & INPUT_DEVICE_CLASS_DPAD; }
+ inline bool isSingleTouchScreen() const { return (classes
+ & (INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT))
+ == INPUT_DEVICE_CLASS_TOUCHSCREEN; }
+ inline bool isMultiTouchScreen() const { return classes
+ & INPUT_DEVICE_CLASS_TOUCHSCREEN_MT; }
+ inline bool isTouchScreen() const { return classes
+ & (INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT); }
+};
+
+
+/*
+ * Input reader policy interface.
+ *
+ * The input reader policy is used by the input reader to interact with the Window Manager
+ * and other system components.
+ *
+ * The actual implementation is partially supported by callbacks into the DVM
+ * via JNI. This interface is also mocked in the unit tests.
+ */
+class InputReaderPolicyInterface : public virtual RefBase {
+protected:
+ InputReaderPolicyInterface() { }
+ virtual ~InputReaderPolicyInterface() { }
+
+public:
+ /* Display orientations. */
+ enum {
+ ROTATION_0 = 0,
+ ROTATION_90 = 1,
+ ROTATION_180 = 2,
+ ROTATION_270 = 3
+ };
+
+ /* Actions returned by interceptXXX methods. */
+ enum {
+ // The input dispatcher should do nothing and discard the input unless other
+ // flags are set.
+ ACTION_NONE = 0,
+
+ // The input dispatcher should dispatch the input to the application.
+ ACTION_DISPATCH = 0x00000001,
+
+ // The input dispatcher should perform special filtering in preparation for
+ // a pending app switch.
+ ACTION_APP_SWITCH_COMING = 0x00000002,
+
+ // The input dispatcher should add POLICY_FLAG_WOKE_HERE to the policy flags it
+ // passes through the dispatch pipeline.
+ ACTION_WOKE_HERE = 0x00000004,
+
+ // The input dispatcher should add POLICY_FLAG_BRIGHT_HERE to the policy flags it
+ // passes through the dispatch pipeline.
+ ACTION_BRIGHT_HERE = 0x00000008
+ };
+
+ /* Describes a virtual key. */
+ struct VirtualKeyDefinition {
+ int32_t scanCode;
+
+ // configured position data, specified in display coords
+ int32_t centerX;
+ int32_t centerY;
+ int32_t width;
+ int32_t height;
+ };
+
+ /* Gets information about the display with the specified id.
+ * Returns true if the display info is available, false otherwise.
+ */
+ virtual bool getDisplayInfo(int32_t displayId,
+ int32_t* width, int32_t* height, int32_t* orientation) = 0;
+
+ /* Provides feedback for a virtual key.
+ */
+ virtual void virtualKeyFeedback(nsecs_t when, int32_t deviceId,
+ int32_t action, int32_t flags, int32_t keyCode,
+ int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0;
+
+ /* Intercepts a key event.
+ * The policy can use this method as an opportunity to perform power management functions
+ * and early event preprocessing.
+ *
+ * Returns a policy action constant such as ACTION_DISPATCH.
+ */
+ virtual int32_t interceptKey(nsecs_t when, int32_t deviceId,
+ bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) = 0;
+
+ /* Intercepts a trackball event.
+ * The policy can use this method as an opportunity to perform power management functions
+ * and early event preprocessing.
+ *
+ * Returns a policy action constant such as ACTION_DISPATCH.
+ */
+ virtual int32_t interceptTrackball(nsecs_t when, bool buttonChanged, bool buttonDown,
+ bool rolled) = 0;
+
+ /* Intercepts a touch event.
+ * The policy can use this method as an opportunity to perform power management functions
+ * and early event preprocessing.
+ *
+ * Returns a policy action constant such as ACTION_DISPATCH.
+ */
+ virtual int32_t interceptTouch(nsecs_t when) = 0;
+
+ /* Intercepts a switch event.
+ * The policy can use this method as an opportunity to perform power management functions
+ * and early event preprocessing.
+ *
+ * Switches are not dispatched to applications so this method should
+ * usually return ACTION_NONE.
+ */
+ virtual int32_t interceptSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) = 0;
+
+ /* Determines whether to turn on some hacks we have to improve the touch interaction with a
+ * certain device whose screen currently is not all that good.
+ */
+ virtual bool filterTouchEvents() = 0;
+
+ /* Determines whether to turn on some hacks to improve touch interaction with another device
+ * where touch coordinate data can get corrupted.
+ */
+ virtual bool filterJumpyTouchEvents() = 0;
+
+ /* Gets the configured virtual key definitions for an input device. */
+ virtual void getVirtualKeyDefinitions(const String8& deviceName,
+ Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) = 0;
+
+ /* Gets the excluded device names for the platform. */
+ virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) = 0;
+};
+
+
+/* Processes raw input events and sends cooked event data to an input dispatcher. */
+class InputReaderInterface : public virtual RefBase {
+protected:
+ InputReaderInterface() { }
+ virtual ~InputReaderInterface() { }
+
+public:
+ /* Runs a single iteration of the processing loop.
+ * Nominally reads and processes one incoming message from the EventHub.
+ *
+ * This method should be called on the input reader thread.
+ */
+ virtual void loopOnce() = 0;
+
+ /* Gets the current virtual key. Returns false if not down.
+ *
+ * This method may be called on any thread (usually by the input manager).
+ */
+ virtual bool getCurrentVirtualKey(int32_t* outKeyCode, int32_t* outScanCode) const = 0;
+
+ /* Gets the current input device configuration.
+ *
+ * This method may be called on any thread (usually by the input manager).
+ */
+ virtual void getCurrentInputConfiguration(InputConfiguration* outConfiguration) const = 0;
+
+ /*
+ * Query current input state.
+ * deviceId may be -1 to search for the device automatically, filtered by class.
+ * deviceClasses may be -1 to ignore device class while searching.
+ */
+ virtual int32_t getCurrentScanCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t scanCode) const = 0;
+ virtual int32_t getCurrentKeyCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t keyCode) const = 0;
+ virtual int32_t getCurrentSwitchState(int32_t deviceId, int32_t deviceClasses,
+ int32_t sw) const = 0;
+
+ /* Determine whether physical keys exist for the given framework-domain key codes. */
+ virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const = 0;
+};
+
+
+/* The input reader reads raw event data from the event hub and processes it into input events
+ * that it sends to the input dispatcher. Some functions of the input reader, such as early
+ * event filtering in low power states, are controlled by a separate policy object.
+ *
+ * IMPORTANT INVARIANT:
+ * Because the policy can potentially block or cause re-entrance into the input reader,
+ * the input reader never calls into the policy while holding its internal locks.
+ */
+class InputReader : public InputReaderInterface {
+public:
+ InputReader(const sp<EventHubInterface>& eventHub,
+ const sp<InputReaderPolicyInterface>& policy,
+ const sp<InputDispatcherInterface>& dispatcher);
+ virtual ~InputReader();
+
+ virtual void loopOnce();
+
+ virtual bool getCurrentVirtualKey(int32_t* outKeyCode, int32_t* outScanCode) const;
+
+ virtual void getCurrentInputConfiguration(InputConfiguration* outConfiguration) const;
+
+ virtual int32_t getCurrentScanCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t scanCode) const;
+ virtual int32_t getCurrentKeyCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t keyCode) const;
+ virtual int32_t getCurrentSwitchState(int32_t deviceId, int32_t deviceClasses,
+ int32_t sw) const;
+
+ virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const;
+
+private:
+ // Lock that must be acquired while manipulating state that may be concurrently accessed
+ // from other threads by input state query methods. It should be held for as short a
+ // time as possible.
+ //
+ // Exported state:
+ // - global virtual key code and scan code
+ // - device list and immutable properties of devices such as id, name, and class
+ // (but not other internal device state)
+ mutable Mutex mExportedStateLock;
+
+ // current virtual key information (lock mExportedStateLock)
+ int32_t mExportedVirtualKeyCode;
+ int32_t mExportedVirtualScanCode;
+
+ // current input configuration (lock mExportedStateLock)
+ InputConfiguration mExportedInputConfiguration;
+
+ // combined key meta state
+ int32_t mGlobalMetaState;
+
+ sp<EventHubInterface> mEventHub;
+ sp<InputReaderPolicyInterface> mPolicy;
+ sp<InputDispatcherInterface> mDispatcher;
+
+ KeyedVector<int32_t, InputDevice*> mDevices;
+
+ // display properties needed to translate touch screen coordinates into display coordinates
+ int32_t mDisplayOrientation;
+ int32_t mDisplayWidth;
+ int32_t mDisplayHeight;
+
+ // low-level input event decoding
+ void process(const RawEvent* rawEvent);
+ void handleDeviceAdded(const RawEvent* rawEvent);
+ void handleDeviceRemoved(const RawEvent* rawEvent);
+ void handleSync(const RawEvent* rawEvent);
+ void handleKey(const RawEvent* rawEvent);
+ void handleRelativeMotion(const RawEvent* rawEvent);
+ void handleAbsoluteMotion(const RawEvent* rawEvent);
+ void handleSwitch(const RawEvent* rawEvent);
+
+ // input policy processing and dispatch
+ void onKey(nsecs_t when, InputDevice* device, bool down,
+ int32_t keyCode, int32_t scanCode, uint32_t policyFlags);
+ void onSwitch(nsecs_t when, InputDevice* device, int32_t switchCode, int32_t switchValue);
+ void onSingleTouchScreenStateChanged(nsecs_t when, InputDevice* device);
+ void onMultiTouchScreenStateChanged(nsecs_t when, InputDevice* device);
+ void onTouchScreenChanged(nsecs_t when, InputDevice* device, bool havePointerIds);
+ void onTrackballStateChanged(nsecs_t when, InputDevice* device);
+ void onConfigurationChanged(nsecs_t when);
+
+ bool applyStandardInputDispatchPolicyActions(nsecs_t when,
+ int32_t policyActions, uint32_t* policyFlags);
+
+ bool consumeVirtualKeyTouches(nsecs_t when, InputDevice* device, uint32_t policyFlags);
+ void dispatchVirtualKey(nsecs_t when, InputDevice* device, uint32_t policyFlags,
+ int32_t keyEventAction, int32_t keyEventFlags);
+ void dispatchTouches(nsecs_t when, InputDevice* device, uint32_t policyFlags);
+ void dispatchTouch(nsecs_t when, InputDevice* device, uint32_t policyFlags,
+ InputDevice::TouchData* touch, BitSet32 idBits, int32_t motionEventAction);
+
+ // display
+ void resetDisplayProperties();
+ bool refreshDisplayProperties();
+
+ // device management
+ InputDevice* getDevice(int32_t deviceId);
+ InputDevice* getNonIgnoredDevice(int32_t deviceId);
+ void addDevice(nsecs_t when, int32_t deviceId);
+ void removeDevice(nsecs_t when, InputDevice* device);
+ void configureDevice(InputDevice* device);
+ void configureDeviceForCurrentDisplaySize(InputDevice* device);
+ void configureVirtualKeys(InputDevice* device);
+ void configureAbsoluteAxisInfo(InputDevice* device, int axis, const char* name,
+ InputDevice::AbsoluteAxisInfo* out);
+ void configureExcludedDevices();
+
+ // global meta state management for all devices
+ void resetGlobalMetaState();
+ int32_t globalMetaState();
+
+ // virtual key management
+ void updateExportedVirtualKeyState();
+
+ // input configuration management
+ void updateExportedInputConfiguration();
+};
+
+
+/* Reads raw events from the event hub and processes them, endlessly. */
+class InputReaderThread : public Thread {
+public:
+ InputReaderThread(const sp<InputReaderInterface>& reader);
+ virtual ~InputReaderThread();
+
+private:
+ sp<InputReaderInterface> mReader;
+
+ virtual bool threadLoop();
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_READER_H
diff --git a/include/ui/InputTransport.h b/include/ui/InputTransport.h
new file mode 100644
index 0000000..7b182f3
--- /dev/null
+++ b/include/ui/InputTransport.h
@@ -0,0 +1,333 @@
+/*
+ * 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.
+ */
+
+#ifndef _UI_INPUT_TRANSPORT_H
+#define _UI_INPUT_TRANSPORT_H
+
+/**
+ * Native input transport.
+ *
+ * Uses anonymous shared memory as a whiteboard for sending input events from an
+ * InputPublisher to an InputConsumer and ensuring appropriate synchronization.
+ * One interesting feature is that published events can be updated in place as long as they
+ * have not yet been consumed.
+ *
+ * The InputPublisher and InputConsumer only take care of transferring event data
+ * over an InputChannel and sending synchronization signals. The InputDispatcher and InputQueue
+ * build on these abstractions to add multiplexing and queueing.
+ */
+
+#include <semaphore.h>
+#include <ui/Input.h>
+#include <utils/Errors.h>
+#include <utils/Timers.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+
+namespace android {
+
+/*
+ * An input channel consists of a shared memory buffer and a pair of pipes
+ * used to send input messages from an InputPublisher to an InputConsumer
+ * across processes. Each channel has a descriptive name for debugging purposes.
+ *
+ * Each endpoint has its own InputChannel object that specifies its own file descriptors.
+ *
+ * The input channel is closed when all references to it are released.
+ */
+class InputChannel : public RefBase {
+protected:
+ virtual ~InputChannel();
+
+public:
+ InputChannel(const String8& name, int32_t ashmemFd, int32_t receivePipeFd,
+ int32_t sendPipeFd);
+
+ /* Creates a pair of input channels and their underlying shared memory buffers
+ * and pipes.
+ *
+ * Returns OK on success.
+ */
+ static status_t openInputChannelPair(const String8& name,
+ sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel);
+
+ inline String8 getName() const { return mName; }
+ inline int32_t getAshmemFd() const { return mAshmemFd; }
+ inline int32_t getReceivePipeFd() const { return mReceivePipeFd; }
+ inline int32_t getSendPipeFd() const { return mSendPipeFd; }
+
+ /* Sends a signal to the other endpoint.
+ *
+ * Returns OK on success.
+ * Returns DEAD_OBJECT if the channel's peer has been closed.
+ * Other errors probably indicate that the channel is broken.
+ */
+ status_t sendSignal(char signal);
+
+ /* Receives a signal send by the other endpoint.
+ * (Should only call this after poll() indicates that the receivePipeFd has available input.)
+ *
+ * Returns OK on success.
+ * Returns WOULD_BLOCK if there is no signal present.
+ * Returns DEAD_OBJECT if the channel's peer has been closed.
+ * Other errors probably indicate that the channel is broken.
+ */
+ status_t receiveSignal(char* outSignal);
+
+private:
+ String8 mName;
+ int32_t mAshmemFd;
+ int32_t mReceivePipeFd;
+ int32_t mSendPipeFd;
+};
+
+/*
+ * Private intermediate representation of input events as messages written into an
+ * ashmem buffer.
+ */
+struct InputMessage {
+ /* Semaphore count is set to 1 when the message is published.
+ * It becomes 0 transiently while the publisher updates the message.
+ * It becomes 0 permanently when the consumer consumes the message.
+ */
+ sem_t semaphore;
+
+ /* Initialized to false by the publisher.
+ * Set to true by the consumer when it consumes the message.
+ */
+ bool consumed;
+
+ int32_t type;
+
+ struct SampleData {
+ nsecs_t eventTime;
+ PointerCoords coords[0]; // variable length
+ };
+
+ int32_t deviceId;
+ int32_t nature;
+
+ union {
+ struct {
+ int32_t action;
+ int32_t flags;
+ int32_t keyCode;
+ int32_t scanCode;
+ int32_t metaState;
+ int32_t repeatCount;
+ nsecs_t downTime;
+ nsecs_t eventTime;
+ } key;
+
+ struct {
+ int32_t action;
+ int32_t metaState;
+ int32_t edgeFlags;
+ nsecs_t downTime;
+ float xOffset;
+ float yOffset;
+ float xPrecision;
+ float yPrecision;
+ size_t pointerCount;
+ int32_t pointerIds[MAX_POINTERS];
+ size_t sampleCount;
+ SampleData sampleData[0]; // variable length
+ } motion;
+ };
+
+ /* Gets the number of bytes to add to step to the next SampleData object in a motion
+ * event message for a given number of pointers.
+ */
+ static inline size_t sampleDataStride(size_t pointerCount) {
+ return sizeof(InputMessage::SampleData) + pointerCount * sizeof(PointerCoords);
+ }
+
+ /* Adds the SampleData stride to the given pointer. */
+ static inline SampleData* sampleDataPtrIncrement(SampleData* ptr, size_t stride) {
+ return reinterpret_cast<InputMessage::SampleData*>(reinterpret_cast<char*>(ptr) + stride);
+ }
+};
+
+/*
+ * Publishes input events to an anonymous shared memory buffer.
+ * Uses atomic operations to coordinate shared access with a single concurrent consumer.
+ */
+class InputPublisher {
+public:
+ /* Creates a publisher associated with an input channel. */
+ explicit InputPublisher(const sp<InputChannel>& channel);
+
+ /* Destroys the publisher and releases its input channel. */
+ ~InputPublisher();
+
+ /* Gets the underlying input channel. */
+ inline sp<InputChannel> getChannel() { return mChannel; }
+
+ /* Prepares the publisher for use. Must be called before it is used.
+ * Returns OK on success.
+ *
+ * This method implicitly calls reset(). */
+ status_t initialize();
+
+ /* Resets the publisher to its initial state and unpins its ashmem buffer.
+ * Returns OK on success.
+ *
+ * Should be called after an event has been consumed to release resources used by the
+ * publisher until the next event is ready to be published.
+ */
+ status_t reset();
+
+ /* Publishes a key event to the ashmem buffer.
+ *
+ * Returns OK on success.
+ * Returns INVALID_OPERATION if the publisher has not been reset.
+ */
+ status_t publishKeyEvent(
+ int32_t deviceId,
+ int32_t nature,
+ int32_t action,
+ int32_t flags,
+ int32_t keyCode,
+ int32_t scanCode,
+ int32_t metaState,
+ int32_t repeatCount,
+ nsecs_t downTime,
+ nsecs_t eventTime);
+
+ /* Publishes a motion event to the ashmem buffer.
+ *
+ * Returns OK on success.
+ * Returns INVALID_OPERATION if the publisher has not been reset.
+ * Returns BAD_VALUE if pointerCount is less than 1 or greater than MAX_POINTERS.
+ */
+ status_t publishMotionEvent(
+ int32_t deviceId,
+ int32_t nature,
+ int32_t action,
+ int32_t edgeFlags,
+ int32_t metaState,
+ float xOffset,
+ float yOffset,
+ float xPrecision,
+ float yPrecision,
+ nsecs_t downTime,
+ nsecs_t eventTime,
+ size_t pointerCount,
+ const int32_t* pointerIds,
+ const PointerCoords* pointerCoords);
+
+ /* Appends a motion sample to a motion event unless already consumed.
+ *
+ * Returns OK on success.
+ * Returns INVALID_OPERATION if the current event is not a MOTION_EVENT_ACTION_MOVE event.
+ * Returns FAILED_TRANSACTION if the current event has already been consumed.
+ * Returns NO_MEMORY if the buffer is full and no additional samples can be added.
+ */
+ status_t appendMotionSample(
+ nsecs_t eventTime,
+ const PointerCoords* pointerCoords);
+
+ /* Sends a dispatch signal to the consumer to inform it that a new message is available.
+ *
+ * Returns OK on success.
+ * Errors probably indicate that the channel is broken.
+ */
+ status_t sendDispatchSignal();
+
+ /* Receives the finished signal from the consumer in reply to the original dispatch signal.
+ *
+ * Returns OK on success.
+ * Returns WOULD_BLOCK if there is no signal present.
+ * Other errors probably indicate that the channel is broken.
+ */
+ status_t receiveFinishedSignal();
+
+private:
+ sp<InputChannel> mChannel;
+
+ size_t mAshmemSize;
+ InputMessage* mSharedMessage;
+ bool mPinned;
+ bool mSemaphoreInitialized;
+ bool mWasDispatched;
+
+ size_t mMotionEventPointerCount;
+ InputMessage::SampleData* mMotionEventSampleDataTail;
+ size_t mMotionEventSampleDataStride;
+
+ status_t publishInputEvent(
+ int32_t type,
+ int32_t deviceId,
+ int32_t nature);
+};
+
+/*
+ * Consumes input events from an anonymous shared memory buffer.
+ * Uses atomic operations to coordinate shared access with a single concurrent publisher.
+ */
+class InputConsumer {
+public:
+ /* Creates a consumer associated with an input channel. */
+ explicit InputConsumer(const sp<InputChannel>& channel);
+
+ /* Destroys the consumer and releases its input channel. */
+ ~InputConsumer();
+
+ /* Gets the underlying input channel. */
+ inline sp<InputChannel> getChannel() { return mChannel; }
+
+ /* Prepares the consumer for use. Must be called before it is used. */
+ status_t initialize();
+
+ /* Consumes the input event in the buffer and copies its contents into
+ * an InputEvent object created using the specified factory.
+ * This operation will block if the publisher is updating the event.
+ *
+ * Returns OK on success.
+ * Returns INVALID_OPERATION if there is no currently published event.
+ * Returns NO_MEMORY if the event could not be created.
+ */
+ status_t consume(InputEventFactoryInterface* factory, InputEvent** outEvent);
+
+ /* Sends a finished signal to the publisher to inform it that the current message is
+ * finished processing.
+ *
+ * Returns OK on success.
+ * Errors probably indicate that the channel is broken.
+ */
+ status_t sendFinishedSignal();
+
+ /* Receives the dispatched signal from the publisher.
+ *
+ * Returns OK on success.
+ * Returns WOULD_BLOCK if there is no signal present.
+ * Other errors probably indicate that the channel is broken.
+ */
+ status_t receiveDispatchSignal();
+
+private:
+ sp<InputChannel> mChannel;
+
+ size_t mAshmemSize;
+ InputMessage* mSharedMessage;
+
+ void populateKeyEvent(KeyEvent* keyEvent) const;
+ void populateMotionEvent(MotionEvent* motionEvent) const;
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_TRANSPORT_H
diff --git a/include/ui/KeycodeLabels.h b/include/ui/KeycodeLabels.h
index 571e47b..e81d0f9 100644..100755
--- a/include/ui/KeycodeLabels.h
+++ b/include/ui/KeycodeLabels.h
@@ -114,6 +114,10 @@ static const KeycodeLabel KEYCODES[] = {
{ "MEDIA_REWIND", 89 },
{ "MEDIA_FAST_FORWARD", 90 },
{ "MUTE", 91 },
+ { "PAGE_UP", 92 },
+ { "PAGE_DOWN", 93 },
+ { "PICTSYMBOLS", 94 },
+ { "SWITCH_CHARSET", 95 },
// NOTE: If you add a new keycode here you must also add it to:
// (enum KeyCode, in this file)
@@ -218,7 +222,11 @@ typedef enum KeyCode {
kKeyCodePreviousSong = 88,
kKeyCodeRewind = 89,
kKeyCodeForward = 90,
- kKeyCodeMute = 91
+ kKeyCodeMute = 91,
+ kKeyCodePageUp = 92,
+ kKeyCodePageDown = 93,
+ kKeyCodePictSymbols = 94,
+ kKeyCodeSwitchCharset = 95
} KeyCode;
static const KeycodeLabel FLAGS[] = {
diff --git a/include/ui/android_native_buffer.h b/include/ui/android_native_buffer.h
index 9c92af8..402843e 100644
--- a/include/ui/android_native_buffer.h
+++ b/include/ui/android_native_buffer.h
@@ -33,6 +33,15 @@ typedef struct android_native_buffer_t
common.version = sizeof(android_native_buffer_t);
memset(common.reserved, 0, sizeof(common.reserved));
}
+
+ // Implement the methods that sp<android_native_buffer_t> expects so that it
+ // can be used to automatically refcount android_native_buffer_t's.
+ void incStrong(const void* id) const {
+ common.incRef(const_cast<android_native_base_t*>(&common));
+ }
+ void decStrong(const void* id) const {
+ common.decRef(const_cast<android_native_base_t*>(&common));
+ }
#endif
struct android_native_base_t common;
diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h
index 773fd93..171f3df 100644
--- a/include/ui/egl/android_natives.h
+++ b/include/ui/egl/android_natives.h
@@ -41,6 +41,14 @@ extern "C" {
struct android_native_buffer_t;
+typedef struct android_native_rect_t
+{
+ int32_t left;
+ int32_t top;
+ int32_t right;
+ int32_t bottom;
+} android_native_rect_t;
+
// ---------------------------------------------------------------------------
typedef struct android_native_base_t
@@ -63,15 +71,18 @@ typedef struct android_native_base_t
/* attributes queriable with query() */
enum {
NATIVE_WINDOW_WIDTH = 0,
- NATIVE_WINDOW_HEIGHT = 1,
- NATIVE_WINDOW_FORMAT = 2,
+ NATIVE_WINDOW_HEIGHT,
+ NATIVE_WINDOW_FORMAT,
};
/* valid operations for the (*perform)() hook */
enum {
NATIVE_WINDOW_SET_USAGE = 0,
- NATIVE_WINDOW_CONNECT = 1,
- NATIVE_WINDOW_DISCONNECT = 2
+ NATIVE_WINDOW_CONNECT,
+ NATIVE_WINDOW_DISCONNECT,
+ NATIVE_WINDOW_SET_CROP,
+ NATIVE_WINDOW_SET_BUFFER_COUNT,
+ NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
};
/* parameter for NATIVE_WINDOW_[DIS]CONNECT */
@@ -89,6 +100,15 @@ typedef struct android_native_window_t
common.version = sizeof(android_native_window_t);
memset(common.reserved, 0, sizeof(common.reserved));
}
+
+ // Implement the methods that sp<android_native_window_t> expects so that it
+ // can be used to automatically refcount android_native_window_t's.
+ void incStrong(const void* id) const {
+ common.incRef(const_cast<android_native_base_t*>(&common));
+ }
+ void decStrong(const void* id) const {
+ common.decRef(const_cast<android_native_base_t*>(&common));
+ }
#endif
struct android_native_base_t common;
@@ -125,7 +145,7 @@ typedef struct android_native_window_t
*
* Returns 0 on success or -errno on error.
*/
- int (*dequeueBuffer)(struct android_native_window_t* window,
+ int (*dequeueBuffer)(struct android_native_window_t* window,
struct android_native_buffer_t** buffer);
/*
@@ -171,6 +191,9 @@ typedef struct android_native_window_t
* NATIVE_WINDOW_SET_USAGE
* NATIVE_WINDOW_CONNECT
* NATIVE_WINDOW_DISCONNECT
+ * NATIVE_WINDOW_SET_CROP
+ * NATIVE_WINDOW_SET_BUFFER_COUNT
+ * NATIVE_WINDOW_SET_BUFFERS_GEOMETRY
*
*/
@@ -182,8 +205,9 @@ typedef struct android_native_window_t
/*
- * native_window_set_usage() sets the intended usage flags for the next
- * buffers acquired with (*lockBuffer)() and on.
+ * native_window_set_usage(..., usage)
+ * Sets the intended usage flags for the next buffers
+ * acquired with (*lockBuffer)() and on.
* By default (if this function is never called), a usage of
* GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE
* is assumed.
@@ -198,8 +222,8 @@ static inline int native_window_set_usage(
}
/*
- * native_window_connect(..., NATIVE_WINDOW_API_EGL) must be called
- * by EGL when the window is made current.
+ * native_window_connect(..., NATIVE_WINDOW_API_EGL)
+ * Must be called by EGL when the window is made current.
* Returns -EINVAL if for some reason the window cannot be connected, which
* can happen if it's connected to some other API.
*/
@@ -210,8 +234,8 @@ static inline int native_window_connect(
}
/*
- * native_window_disconnect(..., NATIVE_WINDOW_API_EGL) must be called
- * by EGL when the window is made not current.
+ * native_window_disconnect(..., NATIVE_WINDOW_API_EGL)
+ * Must be called by EGL when the window is made not current.
* An error is returned if for instance the window wasn't connected in the
* first place.
*/
@@ -221,6 +245,54 @@ static inline int native_window_disconnect(
return window->perform(window, NATIVE_WINDOW_DISCONNECT, api);
}
+/*
+ * native_window_set_crop(..., crop)
+ * Sets which region of the next queued buffers needs to be considered.
+ * A buffer's crop region is scaled to match the surface's size.
+ *
+ * The specified crop region applies to all buffers queued after it is called.
+ *
+ * if 'crop' is NULL, subsequently queued buffers won't be cropped.
+ *
+ * An error is returned if for instance the crop region is invalid,
+ * out of the buffer's bound or if the window is invalid.
+ */
+static inline int native_window_set_crop(
+ android_native_window_t* window,
+ android_native_rect_t const * crop)
+{
+ return window->perform(window, NATIVE_WINDOW_SET_CROP, crop);
+}
+
+/*
+ * native_window_set_buffer_count(..., count)
+ * Sets the number of buffers associated with this native window.
+ */
+static inline int native_window_set_buffer_count(
+ android_native_window_t* window,
+ size_t bufferCount)
+{
+ return window->perform(window, NATIVE_WINDOW_SET_BUFFER_COUNT, bufferCount);
+}
+
+/*
+ * native_window_set_buffers_geometry(..., int w, int h, int format)
+ * All buffers dequeued after this call will have the geometry specified.
+ * In particular, all buffers will have a fixed-size, independent form the
+ * native-window size. They will be appropriately scaled to the window-size
+ * upon composition.
+ *
+ * If all parameters are 0, the normal behavior is restored. That is,
+ * dequeued buffers following this call will be sized to the window's size.
+ *
+ */
+static inline int native_window_set_buffers_geometry(
+ android_native_window_t* window,
+ int w, int h, int format)
+{
+ return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
+ w, h, format);
+}
// ---------------------------------------------------------------------------
@@ -263,6 +335,15 @@ namespace android {
template <typename NATIVE_TYPE, typename TYPE, typename REF>
class EGLNativeBase : public NATIVE_TYPE, public REF
{
+public:
+ // Disambiguate between the incStrong in REF and NATIVE_TYPE
+ void incStrong(const void* id) const {
+ REF::incStrong(id);
+ }
+ void decStrong(const void* id) const {
+ REF::decStrong(id);
+ }
+
protected:
typedef EGLNativeBase<NATIVE_TYPE, TYPE, REF> BASE;
EGLNativeBase() : NATIVE_TYPE(), REF() {