summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2010-04-22 18:58:52 -0700
committerJeff Brown <jeffbrown@google.com>2010-06-13 17:42:16 -0700
commit46b9ac0ae2162309774a7478cd9d4e578747bfc2 (patch)
tree46ad021a41e25ca9f1250b709a29b724dc6b504d /include
parentf62c57d684b83df7d2817db976c0afdb500ae92a (diff)
downloadframeworks_base-46b9ac0ae2162309774a7478cd9d4e578747bfc2.zip
frameworks_base-46b9ac0ae2162309774a7478cd9d4e578747bfc2.tar.gz
frameworks_base-46b9ac0ae2162309774a7478cd9d4e578747bfc2.tar.bz2
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
Diffstat (limited to 'include')
-rw-r--r--include/private/README4
-rw-r--r--include/ui/EventHub.h157
-rw-r--r--include/ui/Input.h310
-rw-r--r--include/ui/InputDispatchPolicy.h198
-rw-r--r--include/ui/InputDispatcher.h409
-rw-r--r--include/ui/InputManager.h134
-rw-r--r--include/ui/InputReader.h472
-rw-r--r--include/ui/InputTransport.h331
-rw-r--r--include/utils/BitSet.h67
-rw-r--r--include/utils/Buffer.h107
-rw-r--r--include/utils/PollLoop.h137
-rw-r--r--include/utils/Pool.h71
-rw-r--r--include/utils/StopWatch.h2
-rw-r--r--include/utils/Vector.h16
-rw-r--r--include/utils/VectorImpl.h4
15 files changed, 2267 insertions, 152 deletions
diff --git a/include/private/README b/include/private/README
new file mode 100644
index 0000000..ee41492
--- /dev/null
+++ b/include/private/README
@@ -0,0 +1,4 @@
+This folder contains private include files.
+
+These include files are part of the private implementation details of
+various framework components. Use at your peril.
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/Input.h b/include/ui/Input.h
new file mode 100644
index 0000000..6a5c8a8
--- /dev/null
+++ b/include/ui/Input.h
@@ -0,0 +1,310 @@
+/*
+ * 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 dispatch 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,
+};
+
+/*
+ * 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;
+};
+
+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;
+};
+
+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 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() const { return mRawX; }
+
+ inline float getRawY() const { return mRawY; }
+
+ inline float getX(size_t pointerIndex) const {
+ return getCurrentPointerCoords(pointerIndex).x;
+ }
+
+ inline float getY(size_t pointerIndex) const {
+ return getCurrentPointerCoords(pointerIndex).y;
+ }
+
+ 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 getHistoricalX(size_t pointerIndex, size_t historicalIndex) const {
+ return getHistoricalPointerCoords(pointerIndex, historicalIndex).x;
+ }
+
+ inline float getHistoricalY(size_t pointerIndex, size_t historicalIndex) const {
+ return getHistoricalPointerCoords(pointerIndex, historicalIndex).y;
+ }
+
+ 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 rawX,
+ float rawY,
+ 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);
+
+private:
+ int32_t mAction;
+ int32_t mEdgeFlags;
+ int32_t mMetaState;
+ float mRawX;
+ float mRawY;
+ 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/InputDispatchPolicy.h b/include/ui/InputDispatchPolicy.h
new file mode 100644
index 0000000..3546813
--- /dev/null
+++ b/include/ui/InputDispatchPolicy.h
@@ -0,0 +1,198 @@
+/*
+ * 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_DISPATCH_POLICY_H
+#define _UI_INPUT_DISPATCH_POLICY_H
+
+/**
+ * Native input dispatch policy.
+ */
+
+#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;
+
+/*
+ * 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 dispatch policy interface.
+ *
+ * The input dispatch policy is used by the input dispatcher to interact with the
+ * Window Manager and other system components. This separation of concerns keeps
+ * the input dispatcher relatively free of special case logic such as is required
+ * to determine the target of iput events, when to wake the device, how to interact
+ * with key guard, and when to transition to the home screen.
+ *
+ * The actual implementation is partially supported by callbacks into the DVM
+ * via JNI. This class is also mocked in the input dispatcher unit tests since
+ * it is an ideal test seam.
+ */
+class InputDispatchPolicyInterface : public virtual RefBase {
+protected:
+ InputDispatchPolicyInterface() { }
+ virtual ~InputDispatchPolicyInterface() { }
+
+public:
+ enum {
+ ROTATION_0 = 0,
+ ROTATION_90 = 1,
+ ROTATION_180 = 2,
+ ROTATION_270 = 3
+ };
+
+ 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
+ };
+
+ 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
+ };
+
+ 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;
+
+ virtual void notifyConfigurationChanged(nsecs_t when,
+ int32_t touchScreenConfig, int32_t keyboardConfig, int32_t navigationConfig) = 0;
+
+ virtual void notifyLidSwitchChanged(nsecs_t when, bool lidOpen) = 0;
+
+ 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;
+
+ virtual int32_t interceptKey(nsecs_t when, int32_t deviceId,
+ bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) = 0;
+
+ virtual int32_t interceptTrackball(nsecs_t when, bool buttonChanged, bool buttonDown,
+ bool rolled) = 0;
+
+ virtual int32_t interceptTouch(nsecs_t when) = 0;
+
+ virtual bool allowKeyRepeat() = 0;
+ virtual nsecs_t getKeyRepeatTimeout() = 0;
+
+ virtual void getKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
+ Vector<InputTarget>& outTargets) = 0;
+ virtual void getMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
+ Vector<InputTarget>& outTargets) = 0;
+
+ /* Determine 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;
+
+ /* Determine whether to turn on some hacks to improve touch interaction with another device
+ * where touch coordinate data can get corrupted.
+ */
+ virtual bool filterJumpyTouchEvents() = 0;
+
+ virtual void getVirtualKeyDefinitions(const String8& deviceName,
+ Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) = 0;
+ virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) = 0;
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_DISPATCH_POLICY_H
diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h
new file mode 100644
index 0000000..bde07f2
--- /dev/null
+++ b/include/ui/InputDispatcher.h
@@ -0,0 +1,409 @@
+/*
+ * 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/InputDispatchPolicy.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 {
+
+/* 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.
+ * The dispatcher will process most of these events asynchronously although some
+ * policy processing may occur synchronously.
+ *
+ * These methods should only be called on the input reader thread.
+ */
+ virtual void notifyConfigurationChanged(nsecs_t eventTime,
+ int32_t touchScreenConfig, int32_t keyboardConfig, int32_t navigationConfig) = 0;
+ virtual void notifyLidSwitchChanged(nsecs_t eventTime, bool lidOpen) = 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. */
+class InputDispatcher : public InputDispatcherInterface {
+protected:
+ virtual ~InputDispatcher();
+
+public:
+ explicit InputDispatcher(const sp<InputDispatchPolicyInterface>& policy);
+
+ virtual void dispatchOnce();
+
+ virtual void notifyConfigurationChanged(nsecs_t eventTime,
+ int32_t touchScreenConfig, int32_t keyboardConfig, int32_t navigationConfig);
+ virtual void notifyLidSwitchChanged(nsecs_t eventTime, bool lidOpen);
+ 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;
+ };
+
+ struct ConfigurationChangedEntry : EventEntry {
+ int32_t touchScreenConfig;
+ int32_t keyboardConfig;
+ int32_t navigationConfig;
+ };
+
+ 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;
+ };
+
+ 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;
+ };
+
+ 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);
+
+ void releaseEventEntry(EventEntry* entry);
+ void releaseConfigurationChangedEntry(ConfigurationChangedEntry* entry);
+ void releaseKeyEntry(KeyEntry* entry);
+ void releaseMotionEntry(MotionEntry* entry);
+ void releaseDispatchEntry(DispatchEntry* entry);
+
+ void appendMotionSample(MotionEntry* motionEntry,
+ nsecs_t eventTime, int32_t pointerCount, const PointerCoords* pointerCoords);
+ void freeMotionSample(MotionSample* sample);
+ void freeMotionSampleList(MotionSample* head);
+
+ private:
+ Pool<ConfigurationChangedEntry> mConfigurationChangeEntryPool;
+ Pool<KeyEntry> mKeyEntryPool;
+ Pool<MotionEntry> mMotionEntryPool;
+ Pool<MotionSample> mMotionSamplePool;
+ Pool<DispatchEntry> mDispatchEntryPool;
+ };
+
+ /* 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() { return inputChannel->getName().string(); }
+
+ // 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<InputDispatchPolicyInterface> mPolicy;
+
+ Mutex mLock;
+
+ Queue<EventEntry> mInboundQueue;
+ Allocator mAllocator;
+
+ sp<PollLoop> mPollLoop;
+
+ // 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;
+
+ // Pool of key and motion event objects used only to ask the input dispatch 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;
+
+ // 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();
+
+ // Process events that have just been dequeued from the head of the input queue.
+ void processConfigurationChangedLocked(nsecs_t currentTime, ConfigurationChangedEntry* entry);
+ void processKeyLocked(nsecs_t currentTime, KeyEntry* entry);
+ void processKeyRepeatLocked(nsecs_t currentTime);
+ void processMotionLocked(nsecs_t currentTime, MotionEntry* entry);
+
+ // Identify input targets for an event and dispatch to them.
+ void identifyInputTargetsAndDispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry);
+ void identifyInputTargetsAndDispatchMotionLocked(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);
+
+ // 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);
+};
+
+/* 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..eb27513
--- /dev/null
+++ b/include/ui/InputManager.h
@@ -0,0 +1,134 @@
+/*
+ * 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 <ui/InputDispatchPolicy.h>
+#include <utils/Errors.h>
+#include <utils/Vector.h>
+#include <utils/Timers.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+
+namespace android {
+
+class InputReader;
+class InputDispatcher;
+class InputReaderThread;
+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;
+
+ /*
+ * 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;
+
+ /* 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;
+};
+
+class InputManager : public InputManagerInterface {
+protected:
+ virtual ~InputManager();
+
+public:
+ /*
+ * Creates an input manager that reads events from the given
+ * event hub and applies the given input dispatch policy.
+ */
+ InputManager(const sp<EventHubInterface>& eventHub,
+ const sp<InputDispatchPolicyInterface>& policy);
+
+ 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 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<EventHubInterface> mEventHub;
+ sp<InputDispatchPolicyInterface> mPolicy;
+
+ sp<InputDispatcher> mDispatcher;
+ sp<InputDispatcherThread> mDispatcherThread;
+
+ sp<InputReader> mReader;
+ sp<InputReaderThread> mReaderThread;
+
+ void configureExcludedDevices();
+};
+
+} // 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..7e7a64c
--- /dev/null
+++ b/include/ui/InputReader.h
@@ -0,0 +1,472 @@
+/*
+ * 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/InputDispatchPolicy.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
+
+/** Amount that trackball needs to move in order to generate a key event. */
+#define TRACKBALL_MOVEMENT_THRESHOLD 6
+
+/* Slop distance for jumpy pointer detection.
+ * The vertical range of the screen divided by this is our epsilon value. */
+#define JUMPY_EPSILON_DIVISOR 212
+
+/* Number of jumpy points to drop for touchscreens that need it. */
+#define JUMPY_TRANSITION_DROPS 3
+#define JUMPY_DROP_LIMIT 3
+
+/* Maximum squared distance for averaging.
+ * If moving farther than this, turn of averaging to avoid lag in response. */
+#define AVERAGING_DISTANCE_LIMIT (75 * 75)
+
+/* 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); }
+};
+
+
+/* Processes raw input events and sends cooked event data to an input dispatcher
+ * in accordance with the input dispatch policy. */
+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;
+};
+
+/* 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 are controlled
+ * by the input dispatch policy, such as early event filtering in low power states.
+ */
+class InputReader : public InputReaderInterface {
+public:
+ InputReader(const sp<EventHubInterface>& eventHub,
+ const sp<InputDispatchPolicyInterface>& policy,
+ const sp<InputDispatcherInterface>& dispatcher);
+ virtual ~InputReader();
+
+ virtual void loopOnce();
+
+ virtual bool getCurrentVirtualKey(int32_t* outKeyCode, int32_t* outScanCode) 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
+ int32_t mGlobalVirtualKeyCode;
+ int32_t mGlobalVirtualScanCode;
+
+ // combined key meta state
+ int32_t mGlobalMetaState;
+
+ sp<EventHubInterface> mEventHub;
+ sp<InputDispatchPolicyInterface> 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, bool down, int32_t code);
+ 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);
+
+ // global meta state management for all devices
+ void resetGlobalMetaState();
+ int32_t globalMetaState();
+
+ // virtual key management
+ void updateGlobalVirtualKeyState();
+};
+
+
+/* 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..9537523
--- /dev/null
+++ b/include/ui/InputTransport.h
@@ -0,0 +1,331 @@
+/*
+ * 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,
+ InputChannel** outServerChannel, 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.
+ * 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.
+ * 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** event);
+
+ /* 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/utils/BitSet.h b/include/utils/BitSet.h
new file mode 100644
index 0000000..19c8bf0
--- /dev/null
+++ b/include/utils/BitSet.h
@@ -0,0 +1,67 @@
+/*
+ * 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 UTILS_BITSET_H
+#define UTILS_BITSET_H
+
+#include <stdint.h>
+
+/*
+ * Contains some bit manipulation helpers.
+ */
+
+namespace android {
+
+// A simple set of 32 bits that can be individually marked or cleared.
+struct BitSet32 {
+ uint32_t value;
+
+ inline BitSet32() : value(0) { }
+ explicit inline BitSet32(uint32_t value) : value(value) { }
+
+ // Gets the value associated with a particular bit index.
+ static inline uint32_t valueForBit(uint32_t n) { return 0x80000000 >> n; }
+
+ // Clears the bit set.
+ inline void clear() { value = 0; }
+
+ // Returns true if the bit set does not contain any marked bits.
+ inline bool isEmpty() const { return ! value; }
+
+ // Returns true if the specified bit is marked.
+ inline bool hasBit(uint32_t n) const { return value & valueForBit(n); }
+
+ // Marks the specified bit.
+ inline void markBit(uint32_t n) { value |= valueForBit(n); }
+
+ // Clears the specified bit.
+ inline void clearBit(uint32_t n) { value &= ~ valueForBit(n); }
+
+ // Finds the first marked bit in the set.
+ // Result is undefined if all bits are unmarked.
+ inline uint32_t firstMarkedBit() const { return __builtin_clz(value); }
+
+ // Finds the first unmarked bit in the set.
+ // Result is undefined if all bits are marked.
+ inline uint32_t firstUnmarkedBit() const { return __builtin_clz(~ value); }
+
+ inline bool operator== (const BitSet32& other) const { return value == other.value; }
+ inline bool operator!= (const BitSet32& other) const { return value != other.value; }
+};
+
+} // namespace android
+
+#endif // UTILS_BITSET_H
diff --git a/include/utils/Buffer.h b/include/utils/Buffer.h
deleted file mode 100644
index 8e22b0f..0000000
--- a/include/utils/Buffer.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2008 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 __UTILS_BUFFER_H__
-#define __UTILS_BUFFER_H__ 1
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-namespace android {
-
-class Buffer
-{
-private:
- char *buf;
- int bufsiz;
- int used;
- void ensureCapacity(int len);
-
- void
- makeRoomFor(int len)
- {
- if (len + used >= bufsiz) {
- bufsiz = (len + used) * 3/2 + 2;
- char *blah = new char[bufsiz];
-
- memcpy(blah, buf, used);
- delete[] buf;
- buf = blah;
- }
- }
-
-public:
- Buffer()
- {
- bufsiz = 16;
- buf = new char[bufsiz];
- clear();
- }
-
- ~Buffer()
- {
- delete[] buf;
- }
-
- void
- clear()
- {
- buf[0] = '\0';
- used = 0;
- }
-
- int
- length()
- {
- return used;
- }
-
- void
- append(const char c)
- {
- makeRoomFor(1);
- buf[used] = c;
- used++;
- buf[used] = '\0';
- }
-
- void
- append(const char *s, int len)
- {
- makeRoomFor(len);
-
- memcpy(buf + used, s, len);
- used += len;
- buf[used] = '\0';
- }
-
- void
- append(const char *s)
- {
- append(s, strlen(s));
- }
-
- char *
- getBytes()
- {
- return buf;
- }
-};
-
-}; // namespace android
-
-#endif
diff --git a/include/utils/PollLoop.h b/include/utils/PollLoop.h
new file mode 100644
index 0000000..2ec39fe
--- /dev/null
+++ b/include/utils/PollLoop.h
@@ -0,0 +1,137 @@
+/*
+ * 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 UTILS_POLL_LOOP_H
+#define UTILS_POLL_LOOP_H
+
+#include <utils/Vector.h>
+#include <utils/threads.h>
+
+#include <poll.h>
+
+namespace android {
+
+/**
+ * A basic file descriptor polling loop based on poll() with callbacks.
+ */
+class PollLoop : public RefBase {
+protected:
+ virtual ~PollLoop();
+
+public:
+ PollLoop();
+
+ /**
+ * A callback that it to be invoked when an event occurs on a file descriptor.
+ * Specifies the events that were triggered and the user data provided when the
+ * callback was set.
+ *
+ * Returns true if the callback should be kept, false if it should be removed automatically
+ * after the callback returns.
+ */
+ typedef bool (*Callback)(int fd, int events, void* data);
+
+ /**
+ * Performs a single call to poll() with optional timeout in milliseconds.
+ * Invokes callbacks for all file descriptors on which an event occurred.
+ *
+ * If the timeout is zero, returns immediately without blocking.
+ * If the timeout is negative, waits indefinitely until awoken.
+ *
+ * Returns true if a callback was invoked or if the loop was awoken by wake().
+ * Returns false if a timeout or error occurred.
+ *
+ * This method must only be called on the main thread.
+ * This method blocks until either a file descriptor is signalled, a timeout occurs,
+ * or wake() is called.
+ * This method does not return until it has finished invoking the appropriate callbacks
+ * for all file descriptors that were signalled.
+ */
+ bool pollOnce(int timeoutMillis);
+
+ /**
+ * Wakes the loop asynchronously.
+ *
+ * This method can be called on any thread.
+ * This method returns immediately.
+ */
+ void wake();
+
+ /**
+ * Sets the callback for a file descriptor, replacing the existing one, if any.
+ * It is an error to call this method with events == 0 or callback == NULL.
+ *
+ * Note that a callback can be invoked with the POLLERR, POLLHUP or POLLNVAL events
+ * even if it is not explicitly requested when registered.
+ *
+ * This method can be called on any thread.
+ * This method may block briefly if it needs to wake the poll loop.
+ */
+ void setCallback(int fd, int events, Callback callback, void* data = NULL);
+
+ /**
+ * Removes the callback for a file descriptor, if one exists.
+ *
+ * When this method returns, it is safe to close the file descriptor since the poll loop
+ * will no longer have a reference to it. However, it is possible for the callback to
+ * already be running or for it to run one last time if the file descriptor was already
+ * signalled. Calling code is responsible for ensuring that this case is safely handled.
+ * For example, if the callback takes care of removing itself during its own execution either
+ * by returning false or calling this method, then it can be guaranteed to not be invoked
+ * again at any later time unless registered anew.
+ *
+ * This method can be called on any thread.
+ * This method may block briefly if it needs to wake the poll loop.
+ *
+ * Returns true if a callback was actually removed, false if none was registered.
+ */
+ bool removeCallback(int fd);
+
+private:
+ struct RequestedCallback {
+ Callback callback;
+ void* data;
+ };
+
+ struct PendingCallback {
+ int fd;
+ int events;
+ Callback callback;
+ void* data;
+ };
+
+ Mutex mLock;
+ Condition mAwake;
+ bool mPolling;
+
+ int mWakeReadPipeFd;
+ int mWakeWritePipeFd;
+
+ Vector<struct pollfd> mRequestedFds;
+ Vector<RequestedCallback> mRequestedCallbacks;
+
+ Vector<PendingCallback> mPendingCallbacks; // used privately by pollOnce
+
+ void openWakePipe();
+ void closeWakePipe();
+
+ ssize_t getRequestIndexLocked(int fd);
+ void wakeAndLock();
+};
+
+} // namespace android
+
+#endif // UTILS_POLL_LOOP_H
diff --git a/include/utils/Pool.h b/include/utils/Pool.h
new file mode 100644
index 0000000..2ee768e
--- /dev/null
+++ b/include/utils/Pool.h
@@ -0,0 +1,71 @@
+/*
+ * 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 UTILS_POOL_H
+#define UTILS_POOL_H
+
+#include <utils/TypeHelpers.h>
+
+namespace android {
+
+class PoolImpl {
+public:
+ PoolImpl(size_t objSize);
+ ~PoolImpl();
+
+ void* allocImpl();
+ void freeImpl(void* obj);
+
+private:
+ size_t mObjSize;
+};
+
+/*
+ * A homogeneous typed memory pool for fixed size objects.
+ * Not intended to be thread-safe.
+ */
+template<typename T>
+class Pool : private PoolImpl {
+public:
+ /* Creates an initially empty pool. */
+ Pool() : PoolImpl(sizeof(T)) { }
+
+ /* Destroys the pool.
+ * Assumes that the pool is empty. */
+ ~Pool() { }
+
+ /* Allocates an object from the pool, growing the pool if needed. */
+ inline T* alloc() {
+ void* mem = allocImpl();
+ if (! traits<T>::has_trivial_ctor) {
+ return new (mem) T();
+ } else {
+ return static_cast<T*>(mem);
+ }
+ }
+
+ /* Frees an object from the pool. */
+ inline void free(T* obj) {
+ if (! traits<T>::has_trivial_dtor) {
+ obj->~T();
+ }
+ freeImpl(obj);
+ }
+};
+
+} // namespace android
+
+#endif // UTILS_POOL_H
diff --git a/include/utils/StopWatch.h b/include/utils/StopWatch.h
index cc0bebc..693dd3c 100644
--- a/include/utils/StopWatch.h
+++ b/include/utils/StopWatch.h
@@ -37,6 +37,8 @@ public:
const char* name() const;
nsecs_t lap();
nsecs_t elapsedTime() const;
+
+ void reset();
private:
const char* mName;
diff --git a/include/utils/Vector.h b/include/utils/Vector.h
index ad59fd6..d40ae16 100644
--- a/include/utils/Vector.h
+++ b/include/utils/Vector.h
@@ -114,6 +114,12 @@ public:
ssize_t appendVector(const Vector<TYPE>& vector);
+ //! insert an array at a given index
+ ssize_t insertArrayAt(const TYPE* array, size_t index, size_t numItems);
+
+ //! append an array at the end of this vector
+ ssize_t appendArray(const TYPE* array, size_t numItems);
+
/*!
* add/insert/replace items
*/
@@ -259,6 +265,16 @@ ssize_t Vector<TYPE>::appendVector(const Vector<TYPE>& vector) {
}
template<class TYPE> inline
+ssize_t Vector<TYPE>::insertArrayAt(const TYPE* array, size_t index, size_t numItems) {
+ return VectorImpl::insertAt(array, index, numItems);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::appendArray(const TYPE* array, size_t numItems) {
+ return VectorImpl::add(array, numItems);
+}
+
+template<class TYPE> inline
ssize_t Vector<TYPE>::insertAt(const TYPE& item, size_t index, size_t numItems) {
return VectorImpl::insertAt(&item, index, numItems);
}
diff --git a/include/utils/VectorImpl.h b/include/utils/VectorImpl.h
index 49b03f1..46a7bc2 100644
--- a/include/utils/VectorImpl.h
+++ b/include/utils/VectorImpl.h
@@ -76,7 +76,7 @@ public:
void push();
void push(const void* item);
ssize_t add();
- ssize_t add(const void* item);
+ ssize_t add(const void* item, size_t numItems = 1);
ssize_t replaceAt(size_t index);
ssize_t replaceAt(const void* item, size_t index);
@@ -184,6 +184,8 @@ private:
void push(const void* item);
ssize_t insertVectorAt(const VectorImpl& vector, size_t index);
ssize_t appendVector(const VectorImpl& vector);
+ ssize_t insertArrayAt(const void* array, size_t index, size_t numItems);
+ ssize_t appendArray(const void* array, size_t numItems);
ssize_t insertAt(size_t where, size_t numItems = 1);
ssize_t insertAt(const void* item, size_t where, size_t numItems = 1);
ssize_t replaceAt(size_t index);