michael@0: /* michael@0: * Copyright (C) 2010 The Android Open Source Project michael@0: * michael@0: * Licensed under the Apache License, Version 2.0 (the "License"); michael@0: * you may not use this file except in compliance with the License. michael@0: * You may obtain a copy of the License at michael@0: * michael@0: * http://www.apache.org/licenses/LICENSE-2.0 michael@0: * michael@0: * Unless required by applicable law or agreed to in writing, software michael@0: * distributed under the License is distributed on an "AS IS" BASIS, michael@0: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. michael@0: * See the License for the specific language governing permissions and michael@0: * limitations under the License. michael@0: */ michael@0: michael@0: #ifndef _UI_INPUT_READER_H michael@0: #define _UI_INPUT_READER_H michael@0: michael@0: #include "EventHub.h" michael@0: #include "PointerController.h" michael@0: #include "InputListener.h" michael@0: michael@0: #include "Input.h" michael@0: #include "VelocityControl.h" michael@0: #include "VelocityTracker.h" michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: #include michael@0: #include michael@0: michael@0: // Maximum supported size of a vibration pattern. michael@0: // Must be at least 2. michael@0: #define MAX_VIBRATE_PATTERN_SIZE 100 michael@0: michael@0: // Maximum allowable delay value in a vibration pattern before michael@0: // which the delay will be truncated. michael@0: #define MAX_VIBRATE_PATTERN_DELAY_NSECS (1000000 * 1000000000LL) michael@0: michael@0: namespace android { michael@0: michael@0: class InputDevice; michael@0: class InputMapper; michael@0: michael@0: /* michael@0: * Describes how coordinates are mapped on a physical display. michael@0: * See com.android.server.display.DisplayViewport. michael@0: */ michael@0: struct DisplayViewport { michael@0: int32_t displayId; // -1 if invalid michael@0: int32_t orientation; michael@0: int32_t logicalLeft; michael@0: int32_t logicalTop; michael@0: int32_t logicalRight; michael@0: int32_t logicalBottom; michael@0: int32_t physicalLeft; michael@0: int32_t physicalTop; michael@0: int32_t physicalRight; michael@0: int32_t physicalBottom; michael@0: int32_t deviceWidth; michael@0: int32_t deviceHeight; michael@0: michael@0: DisplayViewport() : michael@0: displayId(ADISPLAY_ID_NONE), orientation(DISPLAY_ORIENTATION_0), michael@0: logicalLeft(0), logicalTop(0), logicalRight(0), logicalBottom(0), michael@0: physicalLeft(0), physicalTop(0), physicalRight(0), physicalBottom(0), michael@0: deviceWidth(0), deviceHeight(0) { michael@0: } michael@0: michael@0: bool operator==(const DisplayViewport& other) const { michael@0: return displayId == other.displayId michael@0: && orientation == other.orientation michael@0: && logicalLeft == other.logicalLeft michael@0: && logicalTop == other.logicalTop michael@0: && logicalRight == other.logicalRight michael@0: && logicalBottom == other.logicalBottom michael@0: && physicalLeft == other.physicalLeft michael@0: && physicalTop == other.physicalTop michael@0: && physicalRight == other.physicalRight michael@0: && physicalBottom == other.physicalBottom michael@0: && deviceWidth == other.deviceWidth michael@0: && deviceHeight == other.deviceHeight; michael@0: } michael@0: michael@0: bool operator!=(const DisplayViewport& other) const { michael@0: return !(*this == other); michael@0: } michael@0: michael@0: inline bool isValid() const { michael@0: return displayId >= 0; michael@0: } michael@0: michael@0: void setNonDisplayViewport(int32_t width, int32_t height) { michael@0: displayId = ADISPLAY_ID_NONE; michael@0: orientation = DISPLAY_ORIENTATION_0; michael@0: logicalLeft = 0; michael@0: logicalTop = 0; michael@0: logicalRight = width; michael@0: logicalBottom = height; michael@0: physicalLeft = 0; michael@0: physicalTop = 0; michael@0: physicalRight = width; michael@0: physicalBottom = height; michael@0: deviceWidth = width; michael@0: deviceHeight = height; michael@0: } michael@0: }; michael@0: michael@0: /* michael@0: * Input reader configuration. michael@0: * michael@0: * Specifies various options that modify the behavior of the input reader. michael@0: */ michael@0: struct InputReaderConfiguration { michael@0: // Describes changes that have occurred. michael@0: enum { michael@0: // The pointer speed changed. michael@0: CHANGE_POINTER_SPEED = 1 << 0, michael@0: michael@0: // The pointer gesture control changed. michael@0: CHANGE_POINTER_GESTURE_ENABLEMENT = 1 << 1, michael@0: michael@0: // The display size or orientation changed. michael@0: CHANGE_DISPLAY_INFO = 1 << 2, michael@0: michael@0: // The visible touches option changed. michael@0: CHANGE_SHOW_TOUCHES = 1 << 3, michael@0: michael@0: // The keyboard layouts must be reloaded. michael@0: CHANGE_KEYBOARD_LAYOUTS = 1 << 4, michael@0: michael@0: // The device name alias supplied by the may have changed for some devices. michael@0: CHANGE_DEVICE_ALIAS = 1 << 5, michael@0: michael@0: // All devices must be reopened. michael@0: CHANGE_MUST_REOPEN = 1 << 31, michael@0: }; michael@0: michael@0: // Gets the amount of time to disable virtual keys after the screen is touched michael@0: // in order to filter out accidental virtual key presses due to swiping gestures michael@0: // or taps near the edge of the display. May be 0 to disable the feature. michael@0: nsecs_t virtualKeyQuietTime; michael@0: michael@0: // The excluded device names for the platform. michael@0: // Devices with these names will be ignored. michael@0: Vector excludedDeviceNames; michael@0: michael@0: // Velocity control parameters for mouse pointer movements. michael@0: VelocityControlParameters pointerVelocityControlParameters; michael@0: michael@0: // Velocity control parameters for mouse wheel movements. michael@0: VelocityControlParameters wheelVelocityControlParameters; michael@0: michael@0: // True if pointer gestures are enabled. michael@0: bool pointerGesturesEnabled; michael@0: michael@0: // Quiet time between certain pointer gesture transitions. michael@0: // Time to allow for all fingers or buttons to settle into a stable state before michael@0: // starting a new gesture. michael@0: nsecs_t pointerGestureQuietInterval; michael@0: michael@0: // The minimum speed that a pointer must travel for us to consider switching the active michael@0: // touch pointer to it during a drag. This threshold is set to avoid switching due michael@0: // to noise from a finger resting on the touch pad (perhaps just pressing it down). michael@0: float pointerGestureDragMinSwitchSpeed; // in pixels per second michael@0: michael@0: // Tap gesture delay time. michael@0: // The time between down and up must be less than this to be considered a tap. michael@0: nsecs_t pointerGestureTapInterval; michael@0: michael@0: // Tap drag gesture delay time. michael@0: // The time between the previous tap's up and the next down must be less than michael@0: // this to be considered a drag. Otherwise, the previous tap is finished and a michael@0: // new tap begins. michael@0: // michael@0: // Note that the previous tap will be held down for this entire duration so this michael@0: // interval must be shorter than the long press timeout. michael@0: nsecs_t pointerGestureTapDragInterval; michael@0: michael@0: // The distance in pixels that the pointer is allowed to move from initial down michael@0: // to up and still be called a tap. michael@0: float pointerGestureTapSlop; // in pixels michael@0: michael@0: // Time after the first touch points go down to settle on an initial centroid. michael@0: // This is intended to be enough time to handle cases where the user puts down two michael@0: // fingers at almost but not quite exactly the same time. michael@0: nsecs_t pointerGestureMultitouchSettleInterval; michael@0: michael@0: // The transition from PRESS to SWIPE or FREEFORM gesture mode is made when michael@0: // at least two pointers have moved at least this far from their starting place. michael@0: float pointerGestureMultitouchMinDistance; // in pixels michael@0: michael@0: // The transition from PRESS to SWIPE gesture mode can only occur when the michael@0: // cosine of the angle between the two vectors is greater than or equal to than this value michael@0: // which indicates that the vectors are oriented in the same direction. michael@0: // When the vectors are oriented in the exactly same direction, the cosine is 1.0. michael@0: // (In exactly opposite directions, the cosine is -1.0.) michael@0: float pointerGestureSwipeTransitionAngleCosine; michael@0: michael@0: // The transition from PRESS to SWIPE gesture mode can only occur when the michael@0: // fingers are no more than this far apart relative to the diagonal size of michael@0: // the touch pad. For example, a ratio of 0.5 means that the fingers must be michael@0: // no more than half the diagonal size of the touch pad apart. michael@0: float pointerGestureSwipeMaxWidthRatio; michael@0: michael@0: // The gesture movement speed factor relative to the size of the display. michael@0: // Movement speed applies when the fingers are moving in the same direction. michael@0: // Without acceleration, a full swipe of the touch pad diagonal in movement mode michael@0: // will cover this portion of the display diagonal. michael@0: float pointerGestureMovementSpeedRatio; michael@0: michael@0: // The gesture zoom speed factor relative to the size of the display. michael@0: // Zoom speed applies when the fingers are mostly moving relative to each other michael@0: // to execute a scale gesture or similar. michael@0: // Without acceleration, a full swipe of the touch pad diagonal in zoom mode michael@0: // will cover this portion of the display diagonal. michael@0: float pointerGestureZoomSpeedRatio; michael@0: michael@0: // True to show the location of touches on the touch screen as spots. michael@0: bool showTouches; michael@0: michael@0: InputReaderConfiguration() : michael@0: virtualKeyQuietTime(0), michael@0: pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f, 3.0f), michael@0: wheelVelocityControlParameters(1.0f, 15.0f, 50.0f, 4.0f), michael@0: pointerGesturesEnabled(true), michael@0: pointerGestureQuietInterval(100 * 1000000LL), // 100 ms michael@0: pointerGestureDragMinSwitchSpeed(50), // 50 pixels per second michael@0: pointerGestureTapInterval(150 * 1000000LL), // 150 ms michael@0: pointerGestureTapDragInterval(150 * 1000000LL), // 150 ms michael@0: pointerGestureTapSlop(10.0f), // 10 pixels michael@0: pointerGestureMultitouchSettleInterval(100 * 1000000LL), // 100 ms michael@0: pointerGestureMultitouchMinDistance(15), // 15 pixels michael@0: pointerGestureSwipeTransitionAngleCosine(0.2588f), // cosine of 75 degrees michael@0: pointerGestureSwipeMaxWidthRatio(0.25f), michael@0: pointerGestureMovementSpeedRatio(0.8f), michael@0: pointerGestureZoomSpeedRatio(0.3f), michael@0: showTouches(false) { } michael@0: michael@0: bool getDisplayInfo(bool external, DisplayViewport* outViewport) const; michael@0: void setDisplayInfo(bool external, const DisplayViewport& viewport); michael@0: michael@0: private: michael@0: DisplayViewport mInternalDisplay; michael@0: DisplayViewport mExternalDisplay; michael@0: }; michael@0: michael@0: michael@0: /* michael@0: * Input reader policy interface. michael@0: * michael@0: * The input reader policy is used by the input reader to interact with the Window Manager michael@0: * and other system components. michael@0: * michael@0: * The actual implementation is partially supported by callbacks into the DVM michael@0: * via JNI. This interface is also mocked in the unit tests. michael@0: * michael@0: * These methods must NOT re-enter the input reader since they may be called while michael@0: * holding the input reader lock. michael@0: */ michael@0: class InputReaderPolicyInterface : public virtual RefBase { michael@0: protected: michael@0: InputReaderPolicyInterface() { } michael@0: virtual ~InputReaderPolicyInterface() { } michael@0: michael@0: public: michael@0: /* Gets the input reader configuration. */ michael@0: virtual void getReaderConfiguration(InputReaderConfiguration* outConfig) = 0; michael@0: michael@0: /* Gets a pointer controller associated with the specified cursor device (ie. a mouse). */ michael@0: virtual sp obtainPointerController(int32_t deviceId) = 0; michael@0: michael@0: /* Notifies the input reader policy that some input devices have changed michael@0: * and provides information about all current input devices. michael@0: */ michael@0: virtual void notifyInputDevicesChanged(const Vector& inputDevices) = 0; michael@0: michael@0: /* Gets the keyboard layout for a particular input device. */ michael@0: virtual sp getKeyboardLayoutOverlay(const String8& inputDeviceDescriptor) = 0; michael@0: michael@0: /* Gets a user-supplied alias for a particular input device, or an empty string if none. */ michael@0: virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier) = 0; michael@0: }; michael@0: michael@0: michael@0: /* Processes raw input events and sends cooked event data to an input listener. */ michael@0: class InputReaderInterface : public virtual RefBase { michael@0: protected: michael@0: InputReaderInterface() { } michael@0: virtual ~InputReaderInterface() { } michael@0: michael@0: public: michael@0: /* Dumps the state of the input reader. michael@0: * michael@0: * This method may be called on any thread (usually by the input manager). */ michael@0: virtual void dump(String8& dump) = 0; michael@0: michael@0: /* Called by the heatbeat to ensures that the reader has not deadlocked. */ michael@0: virtual void monitor() = 0; michael@0: michael@0: /* Runs a single iteration of the processing loop. michael@0: * Nominally reads and processes one incoming message from the EventHub. michael@0: * michael@0: * This method should be called on the input reader thread. michael@0: */ michael@0: virtual void loopOnce() = 0; michael@0: michael@0: /* Gets information about all input devices. michael@0: * michael@0: * This method may be called on any thread (usually by the input manager). michael@0: */ michael@0: virtual void getInputDevices(Vector& outInputDevices) = 0; michael@0: michael@0: /* Query current input state. */ michael@0: virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask, michael@0: int32_t scanCode) = 0; michael@0: virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask, michael@0: int32_t keyCode) = 0; michael@0: virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask, michael@0: int32_t sw) = 0; michael@0: michael@0: /* Determine whether physical keys exist for the given framework-domain key codes. */ michael@0: virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask, michael@0: size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0; michael@0: michael@0: /* Requests that a reconfiguration of all input devices. michael@0: * The changes flag is a bitfield that indicates what has changed and whether michael@0: * the input devices must all be reopened. */ michael@0: virtual void requestRefreshConfiguration(uint32_t changes) = 0; michael@0: michael@0: /* Controls the vibrator of a particular input device. */ michael@0: virtual void vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize, michael@0: ssize_t repeat, int32_t token) = 0; michael@0: virtual void cancelVibrate(int32_t deviceId, int32_t token) = 0; michael@0: }; michael@0: michael@0: michael@0: /* Internal interface used by individual input devices to access global input device state michael@0: * and parameters maintained by the input reader. michael@0: */ michael@0: class InputReaderContext { michael@0: public: michael@0: InputReaderContext() { } michael@0: virtual ~InputReaderContext() { } michael@0: michael@0: virtual void updateGlobalMetaState() = 0; michael@0: virtual int32_t getGlobalMetaState() = 0; michael@0: michael@0: virtual void disableVirtualKeysUntil(nsecs_t time) = 0; michael@0: virtual bool shouldDropVirtualKey(nsecs_t now, michael@0: InputDevice* device, int32_t keyCode, int32_t scanCode) = 0; michael@0: michael@0: virtual void fadePointer() = 0; michael@0: michael@0: virtual void requestTimeoutAtTime(nsecs_t when) = 0; michael@0: virtual int32_t bumpGeneration() = 0; michael@0: michael@0: virtual InputReaderPolicyInterface* getPolicy() = 0; michael@0: virtual InputListenerInterface* getListener() = 0; michael@0: virtual EventHubInterface* getEventHub() = 0; michael@0: }; michael@0: michael@0: michael@0: /* The input reader reads raw event data from the event hub and processes it into input events michael@0: * that it sends to the input listener. Some functions of the input reader, such as early michael@0: * event filtering in low power states, are controlled by a separate policy object. michael@0: * michael@0: * The InputReader owns a collection of InputMappers. Most of the work it does happens michael@0: * on the input reader thread but the InputReader can receive queries from other system michael@0: * components running on arbitrary threads. To keep things manageable, the InputReader michael@0: * uses a single Mutex to guard its state. The Mutex may be held while calling into the michael@0: * EventHub or the InputReaderPolicy but it is never held while calling into the michael@0: * InputListener. michael@0: */ michael@0: class InputReader : public InputReaderInterface { michael@0: public: michael@0: InputReader(const sp& eventHub, michael@0: const sp& policy, michael@0: const sp& listener); michael@0: virtual ~InputReader(); michael@0: michael@0: virtual void dump(String8& dump); michael@0: virtual void monitor(); michael@0: michael@0: virtual void loopOnce(); michael@0: michael@0: virtual void getInputDevices(Vector& outInputDevices); michael@0: michael@0: virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask, michael@0: int32_t scanCode); michael@0: virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask, michael@0: int32_t keyCode); michael@0: virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask, michael@0: int32_t sw); michael@0: michael@0: virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask, michael@0: size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags); michael@0: michael@0: virtual void requestRefreshConfiguration(uint32_t changes); michael@0: michael@0: virtual void vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize, michael@0: ssize_t repeat, int32_t token); michael@0: virtual void cancelVibrate(int32_t deviceId, int32_t token); michael@0: michael@0: protected: michael@0: // These members are protected so they can be instrumented by test cases. michael@0: virtual InputDevice* createDeviceLocked(int32_t deviceId, michael@0: const InputDeviceIdentifier& identifier, uint32_t classes); michael@0: michael@0: class ContextImpl : public InputReaderContext { michael@0: InputReader* mReader; michael@0: michael@0: public: michael@0: ContextImpl(InputReader* reader); michael@0: michael@0: virtual void updateGlobalMetaState(); michael@0: virtual int32_t getGlobalMetaState(); michael@0: virtual void disableVirtualKeysUntil(nsecs_t time); michael@0: virtual bool shouldDropVirtualKey(nsecs_t now, michael@0: InputDevice* device, int32_t keyCode, int32_t scanCode); michael@0: virtual void fadePointer(); michael@0: virtual void requestTimeoutAtTime(nsecs_t when); michael@0: virtual int32_t bumpGeneration(); michael@0: virtual InputReaderPolicyInterface* getPolicy(); michael@0: virtual InputListenerInterface* getListener(); michael@0: virtual EventHubInterface* getEventHub(); michael@0: } mContext; michael@0: michael@0: friend class ContextImpl; michael@0: michael@0: private: michael@0: Mutex mLock; michael@0: michael@0: Condition mReaderIsAliveCondition; michael@0: michael@0: sp mEventHub; michael@0: sp mPolicy; michael@0: sp mQueuedListener; michael@0: michael@0: InputReaderConfiguration mConfig; michael@0: michael@0: // The event queue. michael@0: static const int EVENT_BUFFER_SIZE = 256; michael@0: RawEvent mEventBuffer[EVENT_BUFFER_SIZE]; michael@0: michael@0: KeyedVector mDevices; michael@0: michael@0: // low-level input event decoding and device management michael@0: void processEventsLocked(const RawEvent* rawEvents, size_t count); michael@0: michael@0: void addDeviceLocked(nsecs_t when, int32_t deviceId); michael@0: void removeDeviceLocked(nsecs_t when, int32_t deviceId); michael@0: void processEventsForDeviceLocked(int32_t deviceId, const RawEvent* rawEvents, size_t count); michael@0: void timeoutExpiredLocked(nsecs_t when); michael@0: michael@0: void handleConfigurationChangedLocked(nsecs_t when); michael@0: michael@0: int32_t mGlobalMetaState; michael@0: void updateGlobalMetaStateLocked(); michael@0: int32_t getGlobalMetaStateLocked(); michael@0: michael@0: void fadePointerLocked(); michael@0: michael@0: int32_t mGeneration; michael@0: int32_t bumpGenerationLocked(); michael@0: michael@0: void getInputDevicesLocked(Vector& outInputDevices); michael@0: michael@0: nsecs_t mDisableVirtualKeysTimeout; michael@0: void disableVirtualKeysUntilLocked(nsecs_t time); michael@0: bool shouldDropVirtualKeyLocked(nsecs_t now, michael@0: InputDevice* device, int32_t keyCode, int32_t scanCode); michael@0: michael@0: nsecs_t mNextTimeout; michael@0: void requestTimeoutAtTimeLocked(nsecs_t when); michael@0: michael@0: uint32_t mConfigurationChangesToRefresh; michael@0: void refreshConfigurationLocked(uint32_t changes); michael@0: michael@0: // state queries michael@0: typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code); michael@0: int32_t getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code, michael@0: GetStateFunc getStateFunc); michael@0: bool markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask, size_t numCodes, michael@0: const int32_t* keyCodes, uint8_t* outFlags); michael@0: }; michael@0: michael@0: michael@0: /* Reads raw events from the event hub and processes them, endlessly. */ michael@0: class InputReaderThread : public Thread { michael@0: public: michael@0: InputReaderThread(const sp& reader); michael@0: virtual ~InputReaderThread(); michael@0: michael@0: private: michael@0: uint32_t mFoo; michael@0: sp mReader; michael@0: michael@0: virtual bool threadLoop(); michael@0: }; michael@0: michael@0: michael@0: /* Represents the state of a single input device. */ michael@0: class InputDevice { michael@0: public: michael@0: InputDevice(InputReaderContext* context, int32_t id, int32_t generation, michael@0: const InputDeviceIdentifier& identifier, uint32_t classes); michael@0: ~InputDevice(); michael@0: michael@0: inline InputReaderContext* getContext() { return mContext; } michael@0: inline int32_t getId() { return mId; } michael@0: inline int32_t getGeneration() { return mGeneration; } michael@0: inline const String8& getName() { return mIdentifier.name; } michael@0: inline uint32_t getClasses() { return mClasses; } michael@0: inline uint32_t getSources() { return mSources; } michael@0: michael@0: inline bool isExternal() { return mIsExternal; } michael@0: inline void setExternal(bool external) { mIsExternal = external; } michael@0: michael@0: inline bool isIgnored() { return mMappers.isEmpty(); } michael@0: michael@0: void dump(String8& dump); michael@0: void addMapper(InputMapper* mapper); michael@0: void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes); michael@0: void reset(nsecs_t when); michael@0: void process(const RawEvent* rawEvents, size_t count); michael@0: void timeoutExpired(nsecs_t when); michael@0: michael@0: void getDeviceInfo(InputDeviceInfo* outDeviceInfo); michael@0: int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode); michael@0: int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode); michael@0: int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode); michael@0: bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, michael@0: const int32_t* keyCodes, uint8_t* outFlags); michael@0: void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, int32_t token); michael@0: void cancelVibrate(int32_t token); michael@0: michael@0: int32_t getMetaState(); michael@0: michael@0: void fadePointer(); michael@0: michael@0: void bumpGeneration(); michael@0: michael@0: void notifyReset(nsecs_t when); michael@0: michael@0: inline const PropertyMap& getConfiguration() { return mConfiguration; } michael@0: inline EventHubInterface* getEventHub() { return mContext->getEventHub(); } michael@0: michael@0: bool hasKey(int32_t code) { michael@0: return getEventHub()->hasScanCode(mId, code); michael@0: } michael@0: michael@0: bool hasAbsoluteAxis(int32_t code) { michael@0: RawAbsoluteAxisInfo info; michael@0: getEventHub()->getAbsoluteAxisInfo(mId, code, &info); michael@0: return info.valid; michael@0: } michael@0: michael@0: bool isKeyPressed(int32_t code) { michael@0: return getEventHub()->getScanCodeState(mId, code) == AKEY_STATE_DOWN; michael@0: } michael@0: michael@0: int32_t getAbsoluteAxisValue(int32_t code) { michael@0: int32_t value; michael@0: getEventHub()->getAbsoluteAxisValue(mId, code, &value); michael@0: return value; michael@0: } michael@0: michael@0: private: michael@0: InputReaderContext* mContext; michael@0: int32_t mId; michael@0: int32_t mGeneration; michael@0: InputDeviceIdentifier mIdentifier; michael@0: String8 mAlias; michael@0: uint32_t mClasses; michael@0: michael@0: Vector mMappers; michael@0: michael@0: uint32_t mSources; michael@0: bool mIsExternal; michael@0: bool mDropUntilNextSync; michael@0: michael@0: typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code); michael@0: int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc); michael@0: michael@0: PropertyMap mConfiguration; michael@0: }; michael@0: michael@0: michael@0: /* Keeps track of the state of mouse or touch pad buttons. */ michael@0: class CursorButtonAccumulator { michael@0: public: michael@0: CursorButtonAccumulator(); michael@0: void reset(InputDevice* device); michael@0: michael@0: void process(const RawEvent* rawEvent); michael@0: michael@0: uint32_t getButtonState() const; michael@0: michael@0: private: michael@0: bool mBtnLeft; michael@0: bool mBtnRight; michael@0: bool mBtnMiddle; michael@0: bool mBtnBack; michael@0: bool mBtnSide; michael@0: bool mBtnForward; michael@0: bool mBtnExtra; michael@0: bool mBtnTask; michael@0: michael@0: void clearButtons(); michael@0: }; michael@0: michael@0: michael@0: /* Keeps track of cursor movements. */ michael@0: michael@0: class CursorMotionAccumulator { michael@0: public: michael@0: CursorMotionAccumulator(); michael@0: void reset(InputDevice* device); michael@0: michael@0: void process(const RawEvent* rawEvent); michael@0: void finishSync(); michael@0: michael@0: inline int32_t getRelativeX() const { return mRelX; } michael@0: inline int32_t getRelativeY() const { return mRelY; } michael@0: michael@0: private: michael@0: int32_t mRelX; michael@0: int32_t mRelY; michael@0: michael@0: void clearRelativeAxes(); michael@0: }; michael@0: michael@0: michael@0: /* Keeps track of cursor scrolling motions. */ michael@0: michael@0: class CursorScrollAccumulator { michael@0: public: michael@0: CursorScrollAccumulator(); michael@0: void configure(InputDevice* device); michael@0: void reset(InputDevice* device); michael@0: michael@0: void process(const RawEvent* rawEvent); michael@0: void finishSync(); michael@0: michael@0: inline bool haveRelativeVWheel() const { return mHaveRelWheel; } michael@0: inline bool haveRelativeHWheel() const { return mHaveRelHWheel; } michael@0: michael@0: inline int32_t getRelativeX() const { return mRelX; } michael@0: inline int32_t getRelativeY() const { return mRelY; } michael@0: inline int32_t getRelativeVWheel() const { return mRelWheel; } michael@0: inline int32_t getRelativeHWheel() const { return mRelHWheel; } michael@0: michael@0: private: michael@0: bool mHaveRelWheel; michael@0: bool mHaveRelHWheel; michael@0: michael@0: int32_t mRelX; michael@0: int32_t mRelY; michael@0: int32_t mRelWheel; michael@0: int32_t mRelHWheel; michael@0: michael@0: void clearRelativeAxes(); michael@0: }; michael@0: michael@0: michael@0: /* Keeps track of the state of touch, stylus and tool buttons. */ michael@0: class TouchButtonAccumulator { michael@0: public: michael@0: TouchButtonAccumulator(); michael@0: void configure(InputDevice* device); michael@0: void reset(InputDevice* device); michael@0: michael@0: void process(const RawEvent* rawEvent); michael@0: michael@0: uint32_t getButtonState() const; michael@0: int32_t getToolType() const; michael@0: bool isToolActive() const; michael@0: bool isHovering() const; michael@0: bool hasStylus() const; michael@0: michael@0: private: michael@0: bool mHaveBtnTouch; michael@0: bool mHaveStylus; michael@0: michael@0: bool mBtnTouch; michael@0: bool mBtnStylus; michael@0: bool mBtnStylus2; michael@0: bool mBtnToolFinger; michael@0: bool mBtnToolPen; michael@0: bool mBtnToolRubber; michael@0: bool mBtnToolBrush; michael@0: bool mBtnToolPencil; michael@0: bool mBtnToolAirbrush; michael@0: bool mBtnToolMouse; michael@0: bool mBtnToolLens; michael@0: bool mBtnToolDoubleTap; michael@0: bool mBtnToolTripleTap; michael@0: bool mBtnToolQuadTap; michael@0: michael@0: void clearButtons(); michael@0: }; michael@0: michael@0: michael@0: /* Raw axis information from the driver. */ michael@0: struct RawPointerAxes { michael@0: RawAbsoluteAxisInfo x; michael@0: RawAbsoluteAxisInfo y; michael@0: RawAbsoluteAxisInfo pressure; michael@0: RawAbsoluteAxisInfo touchMajor; michael@0: RawAbsoluteAxisInfo touchMinor; michael@0: RawAbsoluteAxisInfo toolMajor; michael@0: RawAbsoluteAxisInfo toolMinor; michael@0: RawAbsoluteAxisInfo orientation; michael@0: RawAbsoluteAxisInfo distance; michael@0: RawAbsoluteAxisInfo tiltX; michael@0: RawAbsoluteAxisInfo tiltY; michael@0: RawAbsoluteAxisInfo trackingId; michael@0: RawAbsoluteAxisInfo slot; michael@0: michael@0: RawPointerAxes(); michael@0: void clear(); michael@0: }; michael@0: michael@0: michael@0: /* Raw data for a collection of pointers including a pointer id mapping table. */ michael@0: struct RawPointerData { michael@0: struct Pointer { michael@0: uint32_t id; michael@0: int32_t x; michael@0: int32_t y; michael@0: int32_t pressure; michael@0: int32_t touchMajor; michael@0: int32_t touchMinor; michael@0: int32_t toolMajor; michael@0: int32_t toolMinor; michael@0: int32_t orientation; michael@0: int32_t distance; michael@0: int32_t tiltX; michael@0: int32_t tiltY; michael@0: int32_t toolType; // a fully decoded AMOTION_EVENT_TOOL_TYPE constant michael@0: bool isHovering; michael@0: }; michael@0: michael@0: uint32_t pointerCount; michael@0: Pointer pointers[MAX_POINTERS]; michael@0: BitSet32 hoveringIdBits, touchingIdBits; michael@0: uint32_t idToIndex[MAX_POINTER_ID + 1]; michael@0: michael@0: RawPointerData(); michael@0: void clear(); michael@0: void copyFrom(const RawPointerData& other); michael@0: void getCentroidOfTouchingPointers(float* outX, float* outY) const; michael@0: michael@0: inline void markIdBit(uint32_t id, bool isHovering) { michael@0: if (isHovering) { michael@0: hoveringIdBits.markBit(id); michael@0: } else { michael@0: touchingIdBits.markBit(id); michael@0: } michael@0: } michael@0: michael@0: inline void clearIdBits() { michael@0: hoveringIdBits.clear(); michael@0: touchingIdBits.clear(); michael@0: } michael@0: michael@0: inline const Pointer& pointerForId(uint32_t id) const { michael@0: return pointers[idToIndex[id]]; michael@0: } michael@0: michael@0: inline bool isHovering(uint32_t pointerIndex) { michael@0: return pointers[pointerIndex].isHovering; michael@0: } michael@0: }; michael@0: michael@0: michael@0: /* Cooked data for a collection of pointers including a pointer id mapping table. */ michael@0: struct CookedPointerData { michael@0: uint32_t pointerCount; michael@0: PointerProperties pointerProperties[MAX_POINTERS]; michael@0: PointerCoords pointerCoords[MAX_POINTERS]; michael@0: BitSet32 hoveringIdBits, touchingIdBits; michael@0: uint32_t idToIndex[MAX_POINTER_ID + 1]; michael@0: michael@0: CookedPointerData(); michael@0: void clear(); michael@0: void copyFrom(const CookedPointerData& other); michael@0: michael@0: inline const PointerCoords& pointerCoordsForId(uint32_t id) const { michael@0: return pointerCoords[idToIndex[id]]; michael@0: } michael@0: michael@0: inline bool isHovering(uint32_t pointerIndex) { michael@0: return hoveringIdBits.hasBit(pointerProperties[pointerIndex].id); michael@0: } michael@0: }; michael@0: michael@0: michael@0: /* Keeps track of the state of single-touch protocol. */ michael@0: class SingleTouchMotionAccumulator { michael@0: public: michael@0: SingleTouchMotionAccumulator(); michael@0: michael@0: void process(const RawEvent* rawEvent); michael@0: void reset(InputDevice* device); michael@0: michael@0: inline int32_t getAbsoluteX() const { return mAbsX; } michael@0: inline int32_t getAbsoluteY() const { return mAbsY; } michael@0: inline int32_t getAbsolutePressure() const { return mAbsPressure; } michael@0: inline int32_t getAbsoluteToolWidth() const { return mAbsToolWidth; } michael@0: inline int32_t getAbsoluteDistance() const { return mAbsDistance; } michael@0: inline int32_t getAbsoluteTiltX() const { return mAbsTiltX; } michael@0: inline int32_t getAbsoluteTiltY() const { return mAbsTiltY; } michael@0: michael@0: private: michael@0: int32_t mAbsX; michael@0: int32_t mAbsY; michael@0: int32_t mAbsPressure; michael@0: int32_t mAbsToolWidth; michael@0: int32_t mAbsDistance; michael@0: int32_t mAbsTiltX; michael@0: int32_t mAbsTiltY; michael@0: michael@0: void clearAbsoluteAxes(); michael@0: }; michael@0: michael@0: michael@0: /* Keeps track of the state of multi-touch protocol. */ michael@0: class MultiTouchMotionAccumulator { michael@0: public: michael@0: class Slot { michael@0: public: michael@0: inline bool isInUse() const { return mInUse; } michael@0: inline int32_t getX() const { return mAbsMTPositionX; } michael@0: inline int32_t getY() const { return mAbsMTPositionY; } michael@0: inline int32_t getTouchMajor() const { return mAbsMTTouchMajor; } michael@0: inline int32_t getTouchMinor() const { michael@0: return mHaveAbsMTTouchMinor ? mAbsMTTouchMinor : mAbsMTTouchMajor; } michael@0: inline int32_t getToolMajor() const { return mAbsMTWidthMajor; } michael@0: inline int32_t getToolMinor() const { michael@0: return mHaveAbsMTWidthMinor ? mAbsMTWidthMinor : mAbsMTWidthMajor; } michael@0: inline int32_t getOrientation() const { return mAbsMTOrientation; } michael@0: inline int32_t getTrackingId() const { return mAbsMTTrackingId; } michael@0: inline int32_t getPressure() const { return mAbsMTPressure; } michael@0: inline int32_t getDistance() const { return mAbsMTDistance; } michael@0: inline int32_t getToolType() const; michael@0: michael@0: private: michael@0: friend class MultiTouchMotionAccumulator; michael@0: michael@0: bool mInUse; michael@0: bool mHaveAbsMTTouchMinor; michael@0: bool mHaveAbsMTWidthMinor; michael@0: bool mHaveAbsMTToolType; michael@0: michael@0: int32_t mAbsMTPositionX; michael@0: int32_t mAbsMTPositionY; michael@0: int32_t mAbsMTTouchMajor; michael@0: int32_t mAbsMTTouchMinor; michael@0: int32_t mAbsMTWidthMajor; michael@0: int32_t mAbsMTWidthMinor; michael@0: int32_t mAbsMTOrientation; michael@0: int32_t mAbsMTTrackingId; michael@0: int32_t mAbsMTPressure; michael@0: int32_t mAbsMTDistance; michael@0: int32_t mAbsMTToolType; michael@0: michael@0: Slot(); michael@0: void clear(); michael@0: }; michael@0: michael@0: MultiTouchMotionAccumulator(); michael@0: ~MultiTouchMotionAccumulator(); michael@0: michael@0: void configure(InputDevice* device, size_t slotCount, bool usingSlotsProtocol); michael@0: void reset(InputDevice* device); michael@0: void process(const RawEvent* rawEvent); michael@0: void finishSync(); michael@0: bool hasStylus() const; michael@0: michael@0: inline size_t getSlotCount() const { return mSlotCount; } michael@0: inline const Slot* getSlot(size_t index) const { return &mSlots[index]; } michael@0: michael@0: private: michael@0: int32_t mCurrentSlot; michael@0: Slot* mSlots; michael@0: size_t mSlotCount; michael@0: bool mUsingSlotsProtocol; michael@0: bool mHaveStylus; michael@0: michael@0: void clearSlots(int32_t initialSlot); michael@0: }; michael@0: michael@0: michael@0: /* An input mapper transforms raw input events into cooked event data. michael@0: * A single input device can have multiple associated input mappers in order to interpret michael@0: * different classes of events. michael@0: * michael@0: * InputMapper lifecycle: michael@0: * - create michael@0: * - configure with 0 changes michael@0: * - reset michael@0: * - process, process, process (may occasionally reconfigure with non-zero changes or reset) michael@0: * - reset michael@0: * - destroy michael@0: */ michael@0: class InputMapper { michael@0: public: michael@0: InputMapper(InputDevice* device); michael@0: virtual ~InputMapper(); michael@0: michael@0: inline InputDevice* getDevice() { return mDevice; } michael@0: inline int32_t getDeviceId() { return mDevice->getId(); } michael@0: inline const String8 getDeviceName() { return mDevice->getName(); } michael@0: inline InputReaderContext* getContext() { return mContext; } michael@0: inline InputReaderPolicyInterface* getPolicy() { return mContext->getPolicy(); } michael@0: inline InputListenerInterface* getListener() { return mContext->getListener(); } michael@0: inline EventHubInterface* getEventHub() { return mContext->getEventHub(); } michael@0: michael@0: virtual uint32_t getSources() = 0; michael@0: virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); michael@0: virtual void dump(String8& dump); michael@0: virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes); michael@0: virtual void reset(nsecs_t when); michael@0: virtual void process(const RawEvent* rawEvent) = 0; michael@0: virtual void timeoutExpired(nsecs_t when); michael@0: michael@0: virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode); michael@0: virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode); michael@0: virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode); michael@0: virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, michael@0: const int32_t* keyCodes, uint8_t* outFlags); michael@0: virtual void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, michael@0: int32_t token); michael@0: virtual void cancelVibrate(int32_t token); michael@0: michael@0: virtual int32_t getMetaState(); michael@0: michael@0: virtual void fadePointer(); michael@0: michael@0: protected: michael@0: InputDevice* mDevice; michael@0: InputReaderContext* mContext; michael@0: michael@0: status_t getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo); michael@0: void bumpGeneration(); michael@0: michael@0: static void dumpRawAbsoluteAxisInfo(String8& dump, michael@0: const RawAbsoluteAxisInfo& axis, const char* name); michael@0: }; michael@0: michael@0: michael@0: class SwitchInputMapper : public InputMapper { michael@0: public: michael@0: SwitchInputMapper(InputDevice* device); michael@0: virtual ~SwitchInputMapper(); michael@0: michael@0: virtual uint32_t getSources(); michael@0: virtual void process(const RawEvent* rawEvent); michael@0: michael@0: virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode); michael@0: michael@0: private: michael@0: uint32_t mUpdatedSwitchValues; michael@0: uint32_t mUpdatedSwitchMask; michael@0: michael@0: void processSwitch(int32_t switchCode, int32_t switchValue); michael@0: void sync(nsecs_t when); michael@0: }; michael@0: michael@0: michael@0: class VibratorInputMapper : public InputMapper { michael@0: public: michael@0: VibratorInputMapper(InputDevice* device); michael@0: virtual ~VibratorInputMapper(); michael@0: michael@0: virtual uint32_t getSources(); michael@0: virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); michael@0: virtual void process(const RawEvent* rawEvent); michael@0: michael@0: virtual void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, michael@0: int32_t token); michael@0: virtual void cancelVibrate(int32_t token); michael@0: virtual void timeoutExpired(nsecs_t when); michael@0: virtual void dump(String8& dump); michael@0: michael@0: private: michael@0: bool mVibrating; michael@0: nsecs_t mPattern[MAX_VIBRATE_PATTERN_SIZE]; michael@0: size_t mPatternSize; michael@0: ssize_t mRepeat; michael@0: int32_t mToken; michael@0: ssize_t mIndex; michael@0: nsecs_t mNextStepTime; michael@0: michael@0: void nextStep(); michael@0: void stopVibrating(); michael@0: }; michael@0: michael@0: michael@0: class KeyboardInputMapper : public InputMapper { michael@0: public: michael@0: KeyboardInputMapper(InputDevice* device, uint32_t source, int32_t keyboardType); michael@0: virtual ~KeyboardInputMapper(); michael@0: michael@0: virtual uint32_t getSources(); michael@0: virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); michael@0: virtual void dump(String8& dump); michael@0: virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes); michael@0: virtual void reset(nsecs_t when); michael@0: virtual void process(const RawEvent* rawEvent); michael@0: michael@0: virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode); michael@0: virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode); michael@0: virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, michael@0: const int32_t* keyCodes, uint8_t* outFlags); michael@0: michael@0: virtual int32_t getMetaState(); michael@0: michael@0: private: michael@0: struct KeyDown { michael@0: int32_t keyCode; michael@0: int32_t scanCode; michael@0: }; michael@0: michael@0: uint32_t mSource; michael@0: int32_t mKeyboardType; michael@0: michael@0: int32_t mOrientation; // orientation for dpad keys michael@0: michael@0: Vector mKeyDowns; // keys that are down michael@0: int32_t mMetaState; michael@0: nsecs_t mDownTime; // time of most recent key down michael@0: michael@0: int32_t mCurrentHidUsage; // most recent HID usage seen this packet, or 0 if none michael@0: michael@0: struct LedState { michael@0: bool avail; // led is available michael@0: bool on; // we think the led is currently on michael@0: }; michael@0: LedState mCapsLockLedState; michael@0: LedState mNumLockLedState; michael@0: LedState mScrollLockLedState; michael@0: michael@0: // Immutable configuration parameters. michael@0: struct Parameters { michael@0: bool hasAssociatedDisplay; michael@0: bool orientationAware; michael@0: } mParameters; michael@0: michael@0: void configureParameters(); michael@0: void dumpParameters(String8& dump); michael@0: michael@0: bool isKeyboardOrGamepadKey(int32_t scanCode); michael@0: michael@0: void processKey(nsecs_t when, bool down, int32_t keyCode, int32_t scanCode, michael@0: uint32_t policyFlags); michael@0: michael@0: ssize_t findKeyDown(int32_t scanCode); michael@0: michael@0: void resetLedState(); michael@0: void initializeLedState(LedState& ledState, int32_t led); michael@0: void updateLedState(bool reset); michael@0: void updateLedStateForModifier(LedState& ledState, int32_t led, michael@0: int32_t modifier, bool reset); michael@0: }; michael@0: michael@0: michael@0: class CursorInputMapper : public InputMapper { michael@0: public: michael@0: CursorInputMapper(InputDevice* device); michael@0: virtual ~CursorInputMapper(); michael@0: michael@0: virtual uint32_t getSources(); michael@0: virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); michael@0: virtual void dump(String8& dump); michael@0: virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes); michael@0: virtual void reset(nsecs_t when); michael@0: virtual void process(const RawEvent* rawEvent); michael@0: michael@0: virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode); michael@0: michael@0: virtual void fadePointer(); michael@0: michael@0: private: michael@0: // Amount that trackball needs to move in order to generate a key event. michael@0: static const int32_t TRACKBALL_MOVEMENT_THRESHOLD = 6; michael@0: michael@0: // Immutable configuration parameters. michael@0: struct Parameters { michael@0: enum Mode { michael@0: MODE_POINTER, michael@0: MODE_NAVIGATION, michael@0: }; michael@0: michael@0: Mode mode; michael@0: bool hasAssociatedDisplay; michael@0: bool orientationAware; michael@0: } mParameters; michael@0: michael@0: CursorButtonAccumulator mCursorButtonAccumulator; michael@0: CursorMotionAccumulator mCursorMotionAccumulator; michael@0: CursorScrollAccumulator mCursorScrollAccumulator; michael@0: michael@0: int32_t mSource; michael@0: float mXScale; michael@0: float mYScale; michael@0: float mXPrecision; michael@0: float mYPrecision; michael@0: michael@0: float mVWheelScale; michael@0: float mHWheelScale; michael@0: michael@0: // Velocity controls for mouse pointer and wheel movements. michael@0: // The controls for X and Y wheel movements are separate to keep them decoupled. michael@0: VelocityControl mPointerVelocityControl; michael@0: VelocityControl mWheelXVelocityControl; michael@0: VelocityControl mWheelYVelocityControl; michael@0: michael@0: int32_t mOrientation; michael@0: michael@0: sp mPointerController; michael@0: michael@0: int32_t mButtonState; michael@0: nsecs_t mDownTime; michael@0: michael@0: void configureParameters(); michael@0: void dumpParameters(String8& dump); michael@0: michael@0: void sync(nsecs_t when); michael@0: }; michael@0: michael@0: michael@0: class TouchInputMapper : public InputMapper { michael@0: public: michael@0: TouchInputMapper(InputDevice* device); michael@0: virtual ~TouchInputMapper(); michael@0: michael@0: virtual uint32_t getSources(); michael@0: virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); michael@0: virtual void dump(String8& dump); michael@0: virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes); michael@0: virtual void reset(nsecs_t when); michael@0: virtual void process(const RawEvent* rawEvent); michael@0: michael@0: virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode); michael@0: virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode); michael@0: virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, michael@0: const int32_t* keyCodes, uint8_t* outFlags); michael@0: michael@0: virtual void fadePointer(); michael@0: virtual void timeoutExpired(nsecs_t when); michael@0: michael@0: protected: michael@0: CursorButtonAccumulator mCursorButtonAccumulator; michael@0: CursorScrollAccumulator mCursorScrollAccumulator; michael@0: TouchButtonAccumulator mTouchButtonAccumulator; michael@0: michael@0: struct VirtualKey { michael@0: int32_t keyCode; michael@0: int32_t scanCode; michael@0: uint32_t flags; michael@0: michael@0: // computed hit box, specified in touch screen coords based on known display size michael@0: int32_t hitLeft; michael@0: int32_t hitTop; michael@0: int32_t hitRight; michael@0: int32_t hitBottom; michael@0: michael@0: inline bool isHit(int32_t x, int32_t y) const { michael@0: return x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom; michael@0: } michael@0: }; michael@0: michael@0: // Input sources and device mode. michael@0: uint32_t mSource; michael@0: michael@0: enum DeviceMode { michael@0: DEVICE_MODE_DISABLED, // input is disabled michael@0: DEVICE_MODE_DIRECT, // direct mapping (touchscreen) michael@0: DEVICE_MODE_UNSCALED, // unscaled mapping (touchpad) michael@0: DEVICE_MODE_NAVIGATION, // unscaled mapping with assist gesture (touch navigation) michael@0: DEVICE_MODE_POINTER, // pointer mapping (pointer) michael@0: }; michael@0: DeviceMode mDeviceMode; michael@0: michael@0: // The reader's configuration. michael@0: InputReaderConfiguration mConfig; michael@0: michael@0: // Immutable configuration parameters. michael@0: struct Parameters { michael@0: enum DeviceType { michael@0: DEVICE_TYPE_TOUCH_SCREEN, michael@0: DEVICE_TYPE_TOUCH_PAD, michael@0: DEVICE_TYPE_TOUCH_NAVIGATION, michael@0: DEVICE_TYPE_POINTER, michael@0: }; michael@0: michael@0: DeviceType deviceType; michael@0: bool hasAssociatedDisplay; michael@0: bool associatedDisplayIsExternal; michael@0: bool orientationAware; michael@0: michael@0: enum GestureMode { michael@0: GESTURE_MODE_POINTER, michael@0: GESTURE_MODE_SPOTS, michael@0: }; michael@0: GestureMode gestureMode; michael@0: } mParameters; michael@0: michael@0: // Immutable calibration parameters in parsed form. michael@0: struct Calibration { michael@0: // Size michael@0: enum SizeCalibration { michael@0: SIZE_CALIBRATION_DEFAULT, michael@0: SIZE_CALIBRATION_NONE, michael@0: SIZE_CALIBRATION_GEOMETRIC, michael@0: SIZE_CALIBRATION_DIAMETER, michael@0: SIZE_CALIBRATION_BOX, michael@0: SIZE_CALIBRATION_AREA, michael@0: }; michael@0: michael@0: SizeCalibration sizeCalibration; michael@0: michael@0: bool haveSizeScale; michael@0: float sizeScale; michael@0: bool haveSizeBias; michael@0: float sizeBias; michael@0: bool haveSizeIsSummed; michael@0: bool sizeIsSummed; michael@0: michael@0: // Pressure michael@0: enum PressureCalibration { michael@0: PRESSURE_CALIBRATION_DEFAULT, michael@0: PRESSURE_CALIBRATION_NONE, michael@0: PRESSURE_CALIBRATION_PHYSICAL, michael@0: PRESSURE_CALIBRATION_AMPLITUDE, michael@0: }; michael@0: michael@0: PressureCalibration pressureCalibration; michael@0: bool havePressureScale; michael@0: float pressureScale; michael@0: michael@0: // Orientation michael@0: enum OrientationCalibration { michael@0: ORIENTATION_CALIBRATION_DEFAULT, michael@0: ORIENTATION_CALIBRATION_NONE, michael@0: ORIENTATION_CALIBRATION_INTERPOLATED, michael@0: ORIENTATION_CALIBRATION_VECTOR, michael@0: }; michael@0: michael@0: OrientationCalibration orientationCalibration; michael@0: michael@0: // Distance michael@0: enum DistanceCalibration { michael@0: DISTANCE_CALIBRATION_DEFAULT, michael@0: DISTANCE_CALIBRATION_NONE, michael@0: DISTANCE_CALIBRATION_SCALED, michael@0: }; michael@0: michael@0: DistanceCalibration distanceCalibration; michael@0: bool haveDistanceScale; michael@0: float distanceScale; michael@0: michael@0: enum CoverageCalibration { michael@0: COVERAGE_CALIBRATION_DEFAULT, michael@0: COVERAGE_CALIBRATION_NONE, michael@0: COVERAGE_CALIBRATION_BOX, michael@0: }; michael@0: michael@0: CoverageCalibration coverageCalibration; michael@0: michael@0: inline void applySizeScaleAndBias(float* outSize) const { michael@0: if (haveSizeScale) { michael@0: *outSize *= sizeScale; michael@0: } michael@0: if (haveSizeBias) { michael@0: *outSize += sizeBias; michael@0: } michael@0: } michael@0: } mCalibration; michael@0: michael@0: // Raw pointer axis information from the driver. michael@0: RawPointerAxes mRawPointerAxes; michael@0: michael@0: // Raw pointer sample data. michael@0: RawPointerData mCurrentRawPointerData; michael@0: RawPointerData mLastRawPointerData; michael@0: michael@0: // Cooked pointer sample data. michael@0: CookedPointerData mCurrentCookedPointerData; michael@0: CookedPointerData mLastCookedPointerData; michael@0: michael@0: // Button state. michael@0: int32_t mCurrentButtonState; michael@0: int32_t mLastButtonState; michael@0: michael@0: // Scroll state. michael@0: int32_t mCurrentRawVScroll; michael@0: int32_t mCurrentRawHScroll; michael@0: michael@0: // Id bits used to differentiate fingers, stylus and mouse tools. michael@0: BitSet32 mCurrentFingerIdBits; // finger or unknown michael@0: BitSet32 mLastFingerIdBits; michael@0: BitSet32 mCurrentStylusIdBits; // stylus or eraser michael@0: BitSet32 mLastStylusIdBits; michael@0: BitSet32 mCurrentMouseIdBits; // mouse or lens michael@0: BitSet32 mLastMouseIdBits; michael@0: michael@0: // True if we sent a HOVER_ENTER event. michael@0: bool mSentHoverEnter; michael@0: michael@0: // The time the primary pointer last went down. michael@0: nsecs_t mDownTime; michael@0: michael@0: // The pointer controller, or null if the device is not a pointer. michael@0: sp mPointerController; michael@0: michael@0: Vector mVirtualKeys; michael@0: michael@0: virtual void configureParameters(); michael@0: virtual void dumpParameters(String8& dump); michael@0: virtual void configureRawPointerAxes(); michael@0: virtual void dumpRawPointerAxes(String8& dump); michael@0: virtual void configureSurface(nsecs_t when, bool* outResetNeeded); michael@0: virtual void dumpSurface(String8& dump); michael@0: virtual void configureVirtualKeys(); michael@0: virtual void dumpVirtualKeys(String8& dump); michael@0: virtual void parseCalibration(); michael@0: virtual void resolveCalibration(); michael@0: virtual void dumpCalibration(String8& dump); michael@0: virtual bool hasStylus() const = 0; michael@0: michael@0: virtual void syncTouch(nsecs_t when, bool* outHavePointerIds) = 0; michael@0: michael@0: private: michael@0: // The current viewport. michael@0: // The components of the viewport are specified in the display's rotated orientation. michael@0: DisplayViewport mViewport; michael@0: michael@0: // The surface orientation, width and height set by configureSurface(). michael@0: // The width and height are derived from the viewport but are specified michael@0: // in the natural orientation. michael@0: // The surface origin specifies how the surface coordinates should be translated michael@0: // to align with the logical display coordinate space. michael@0: // The orientation may be different from the viewport orientation as it specifies michael@0: // the rotation of the surface coordinates required to produce the viewport's michael@0: // requested orientation, so it will depend on whether the device is orientation aware. michael@0: int32_t mSurfaceWidth; michael@0: int32_t mSurfaceHeight; michael@0: int32_t mSurfaceLeft; michael@0: int32_t mSurfaceTop; michael@0: int32_t mSurfaceOrientation; michael@0: michael@0: // Translation and scaling factors, orientation-independent. michael@0: float mXTranslate; michael@0: float mXScale; michael@0: float mXPrecision; michael@0: michael@0: float mYTranslate; michael@0: float mYScale; michael@0: float mYPrecision; michael@0: michael@0: float mGeometricScale; michael@0: michael@0: float mPressureScale; michael@0: michael@0: float mSizeScale; michael@0: michael@0: float mOrientationScale; michael@0: michael@0: float mDistanceScale; michael@0: michael@0: bool mHaveTilt; michael@0: float mTiltXCenter; michael@0: float mTiltXScale; michael@0: float mTiltYCenter; michael@0: float mTiltYScale; michael@0: michael@0: // Oriented motion ranges for input device info. michael@0: struct OrientedRanges { michael@0: InputDeviceInfo::MotionRange x; michael@0: InputDeviceInfo::MotionRange y; michael@0: InputDeviceInfo::MotionRange pressure; michael@0: michael@0: bool haveSize; michael@0: InputDeviceInfo::MotionRange size; michael@0: michael@0: bool haveTouchSize; michael@0: InputDeviceInfo::MotionRange touchMajor; michael@0: InputDeviceInfo::MotionRange touchMinor; michael@0: michael@0: bool haveToolSize; michael@0: InputDeviceInfo::MotionRange toolMajor; michael@0: InputDeviceInfo::MotionRange toolMinor; michael@0: michael@0: bool haveOrientation; michael@0: InputDeviceInfo::MotionRange orientation; michael@0: michael@0: bool haveDistance; michael@0: InputDeviceInfo::MotionRange distance; michael@0: michael@0: bool haveTilt; michael@0: InputDeviceInfo::MotionRange tilt; michael@0: michael@0: OrientedRanges() { michael@0: clear(); michael@0: } michael@0: michael@0: void clear() { michael@0: haveSize = false; michael@0: haveTouchSize = false; michael@0: haveToolSize = false; michael@0: haveOrientation = false; michael@0: haveDistance = false; michael@0: haveTilt = false; michael@0: } michael@0: } mOrientedRanges; michael@0: michael@0: // Oriented dimensions and precision. michael@0: float mOrientedXPrecision; michael@0: float mOrientedYPrecision; michael@0: michael@0: struct CurrentVirtualKeyState { michael@0: bool down; michael@0: bool ignored; michael@0: nsecs_t downTime; michael@0: int32_t keyCode; michael@0: int32_t scanCode; michael@0: } mCurrentVirtualKey; michael@0: michael@0: // Scale factor for gesture or mouse based pointer movements. michael@0: float mPointerXMovementScale; michael@0: float mPointerYMovementScale; michael@0: michael@0: // Scale factor for gesture based zooming and other freeform motions. michael@0: float mPointerXZoomScale; michael@0: float mPointerYZoomScale; michael@0: michael@0: // The maximum swipe width. michael@0: float mPointerGestureMaxSwipeWidth; michael@0: michael@0: struct PointerDistanceHeapElement { michael@0: uint32_t currentPointerIndex : 8; michael@0: uint32_t lastPointerIndex : 8; michael@0: uint64_t distance : 48; // squared distance michael@0: }; michael@0: michael@0: enum PointerUsage { michael@0: POINTER_USAGE_NONE, michael@0: POINTER_USAGE_GESTURES, michael@0: POINTER_USAGE_STYLUS, michael@0: POINTER_USAGE_MOUSE, michael@0: }; michael@0: PointerUsage mPointerUsage; michael@0: michael@0: struct PointerGesture { michael@0: enum Mode { michael@0: // No fingers, button is not pressed. michael@0: // Nothing happening. michael@0: NEUTRAL, michael@0: michael@0: // No fingers, button is not pressed. michael@0: // Tap detected. michael@0: // Emits DOWN and UP events at the pointer location. michael@0: TAP, michael@0: michael@0: // Exactly one finger dragging following a tap. michael@0: // Pointer follows the active finger. michael@0: // Emits DOWN, MOVE and UP events at the pointer location. michael@0: // michael@0: // Detect double-taps when the finger goes up while in TAP_DRAG mode. michael@0: TAP_DRAG, michael@0: michael@0: // Button is pressed. michael@0: // Pointer follows the active finger if there is one. Other fingers are ignored. michael@0: // Emits DOWN, MOVE and UP events at the pointer location. michael@0: BUTTON_CLICK_OR_DRAG, michael@0: michael@0: // Exactly one finger, button is not pressed. michael@0: // Pointer follows the active finger. michael@0: // Emits HOVER_MOVE events at the pointer location. michael@0: // michael@0: // Detect taps when the finger goes up while in HOVER mode. michael@0: HOVER, michael@0: michael@0: // Exactly two fingers but neither have moved enough to clearly indicate michael@0: // whether a swipe or freeform gesture was intended. We consider the michael@0: // pointer to be pressed so this enables clicking or long-pressing on buttons. michael@0: // Pointer does not move. michael@0: // Emits DOWN, MOVE and UP events with a single stationary pointer coordinate. michael@0: PRESS, michael@0: michael@0: // Exactly two fingers moving in the same direction, button is not pressed. michael@0: // Pointer does not move. michael@0: // Emits DOWN, MOVE and UP events with a single pointer coordinate that michael@0: // follows the midpoint between both fingers. michael@0: SWIPE, michael@0: michael@0: // Two or more fingers moving in arbitrary directions, button is not pressed. michael@0: // Pointer does not move. michael@0: // Emits DOWN, POINTER_DOWN, MOVE, POINTER_UP and UP events that follow michael@0: // each finger individually relative to the initial centroid of the finger. michael@0: FREEFORM, michael@0: michael@0: // Waiting for quiet time to end before starting the next gesture. michael@0: QUIET, michael@0: }; michael@0: michael@0: // Time the first finger went down. michael@0: nsecs_t firstTouchTime; michael@0: michael@0: // The active pointer id from the raw touch data. michael@0: int32_t activeTouchId; // -1 if none michael@0: michael@0: // The active pointer id from the gesture last delivered to the application. michael@0: int32_t activeGestureId; // -1 if none michael@0: michael@0: // Pointer coords and ids for the current and previous pointer gesture. michael@0: Mode currentGestureMode; michael@0: BitSet32 currentGestureIdBits; michael@0: uint32_t currentGestureIdToIndex[MAX_POINTER_ID + 1]; michael@0: PointerProperties currentGestureProperties[MAX_POINTERS]; michael@0: PointerCoords currentGestureCoords[MAX_POINTERS]; michael@0: michael@0: Mode lastGestureMode; michael@0: BitSet32 lastGestureIdBits; michael@0: uint32_t lastGestureIdToIndex[MAX_POINTER_ID + 1]; michael@0: PointerProperties lastGestureProperties[MAX_POINTERS]; michael@0: PointerCoords lastGestureCoords[MAX_POINTERS]; michael@0: michael@0: // Time the pointer gesture last went down. michael@0: nsecs_t downTime; michael@0: michael@0: // Time when the pointer went down for a TAP. michael@0: nsecs_t tapDownTime; michael@0: michael@0: // Time when the pointer went up for a TAP. michael@0: nsecs_t tapUpTime; michael@0: michael@0: // Location of initial tap. michael@0: float tapX, tapY; michael@0: michael@0: // Time we started waiting for quiescence. michael@0: nsecs_t quietTime; michael@0: michael@0: // Reference points for multitouch gestures. michael@0: float referenceTouchX; // reference touch X/Y coordinates in surface units michael@0: float referenceTouchY; michael@0: float referenceGestureX; // reference gesture X/Y coordinates in pixels michael@0: float referenceGestureY; michael@0: michael@0: // Distance that each pointer has traveled which has not yet been michael@0: // subsumed into the reference gesture position. michael@0: BitSet32 referenceIdBits; michael@0: struct Delta { michael@0: float dx, dy; michael@0: }; michael@0: Delta referenceDeltas[MAX_POINTER_ID + 1]; michael@0: michael@0: // Describes how touch ids are mapped to gesture ids for freeform gestures. michael@0: uint32_t freeformTouchToGestureIdMap[MAX_POINTER_ID + 1]; michael@0: michael@0: // A velocity tracker for determining whether to switch active pointers during drags. michael@0: VelocityTracker velocityTracker; michael@0: michael@0: void reset() { michael@0: firstTouchTime = LLONG_MIN; michael@0: activeTouchId = -1; michael@0: activeGestureId = -1; michael@0: currentGestureMode = NEUTRAL; michael@0: currentGestureIdBits.clear(); michael@0: lastGestureMode = NEUTRAL; michael@0: lastGestureIdBits.clear(); michael@0: downTime = 0; michael@0: velocityTracker.clear(); michael@0: resetTap(); michael@0: resetQuietTime(); michael@0: } michael@0: michael@0: void resetTap() { michael@0: tapDownTime = LLONG_MIN; michael@0: tapUpTime = LLONG_MIN; michael@0: } michael@0: michael@0: void resetQuietTime() { michael@0: quietTime = LLONG_MIN; michael@0: } michael@0: } mPointerGesture; michael@0: michael@0: struct PointerSimple { michael@0: PointerCoords currentCoords; michael@0: PointerProperties currentProperties; michael@0: PointerCoords lastCoords; michael@0: PointerProperties lastProperties; michael@0: michael@0: // True if the pointer is down. michael@0: bool down; michael@0: michael@0: // True if the pointer is hovering. michael@0: bool hovering; michael@0: michael@0: // Time the pointer last went down. michael@0: nsecs_t downTime; michael@0: michael@0: void reset() { michael@0: currentCoords.clear(); michael@0: currentProperties.clear(); michael@0: lastCoords.clear(); michael@0: lastProperties.clear(); michael@0: down = false; michael@0: hovering = false; michael@0: downTime = 0; michael@0: } michael@0: } mPointerSimple; michael@0: michael@0: // The pointer and scroll velocity controls. michael@0: VelocityControl mPointerVelocityControl; michael@0: VelocityControl mWheelXVelocityControl; michael@0: VelocityControl mWheelYVelocityControl; michael@0: michael@0: void sync(nsecs_t when); michael@0: michael@0: bool consumeRawTouches(nsecs_t when, uint32_t policyFlags); michael@0: void dispatchVirtualKey(nsecs_t when, uint32_t policyFlags, michael@0: int32_t keyEventAction, int32_t keyEventFlags); michael@0: michael@0: void dispatchTouches(nsecs_t when, uint32_t policyFlags); michael@0: void dispatchHoverExit(nsecs_t when, uint32_t policyFlags); michael@0: void dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags); michael@0: void cookPointerData(); michael@0: michael@0: void dispatchPointerUsage(nsecs_t when, uint32_t policyFlags, PointerUsage pointerUsage); michael@0: void abortPointerUsage(nsecs_t when, uint32_t policyFlags); michael@0: michael@0: void dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, bool isTimeout); michael@0: void abortPointerGestures(nsecs_t when, uint32_t policyFlags); michael@0: bool preparePointerGestures(nsecs_t when, michael@0: bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, michael@0: bool isTimeout); michael@0: michael@0: void dispatchPointerStylus(nsecs_t when, uint32_t policyFlags); michael@0: void abortPointerStylus(nsecs_t when, uint32_t policyFlags); michael@0: michael@0: void dispatchPointerMouse(nsecs_t when, uint32_t policyFlags); michael@0: void abortPointerMouse(nsecs_t when, uint32_t policyFlags); michael@0: michael@0: void dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, michael@0: bool down, bool hovering); michael@0: void abortPointerSimple(nsecs_t when, uint32_t policyFlags); michael@0: michael@0: // Dispatches a motion event. michael@0: // If the changedId is >= 0 and the action is POINTER_DOWN or POINTER_UP, the michael@0: // method will take care of setting the index and transmuting the action to DOWN or UP michael@0: // it is the first / last pointer to go down / up. michael@0: void dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source, michael@0: int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, michael@0: int32_t edgeFlags, michael@0: const PointerProperties* properties, const PointerCoords* coords, michael@0: const uint32_t* idToIndex, BitSet32 idBits, michael@0: int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime); michael@0: michael@0: // Updates pointer coords and properties for pointers with specified ids that have moved. michael@0: // Returns true if any of them changed. michael@0: bool updateMovedPointers(const PointerProperties* inProperties, michael@0: const PointerCoords* inCoords, const uint32_t* inIdToIndex, michael@0: PointerProperties* outProperties, PointerCoords* outCoords, michael@0: const uint32_t* outIdToIndex, BitSet32 idBits) const; michael@0: michael@0: bool isPointInsideSurface(int32_t x, int32_t y); michael@0: const VirtualKey* findVirtualKeyHit(int32_t x, int32_t y); michael@0: michael@0: void assignPointerIds(); michael@0: }; michael@0: michael@0: michael@0: class SingleTouchInputMapper : public TouchInputMapper { michael@0: public: michael@0: SingleTouchInputMapper(InputDevice* device); michael@0: virtual ~SingleTouchInputMapper(); michael@0: michael@0: virtual void reset(nsecs_t when); michael@0: virtual void process(const RawEvent* rawEvent); michael@0: michael@0: protected: michael@0: virtual void syncTouch(nsecs_t when, bool* outHavePointerIds); michael@0: virtual void configureRawPointerAxes(); michael@0: virtual bool hasStylus() const; michael@0: michael@0: private: michael@0: SingleTouchMotionAccumulator mSingleTouchMotionAccumulator; michael@0: }; michael@0: michael@0: michael@0: class MultiTouchInputMapper : public TouchInputMapper { michael@0: public: michael@0: MultiTouchInputMapper(InputDevice* device); michael@0: virtual ~MultiTouchInputMapper(); michael@0: michael@0: virtual void reset(nsecs_t when); michael@0: virtual void process(const RawEvent* rawEvent); michael@0: michael@0: protected: michael@0: virtual void syncTouch(nsecs_t when, bool* outHavePointerIds); michael@0: virtual void configureRawPointerAxes(); michael@0: virtual bool hasStylus() const; michael@0: michael@0: private: michael@0: MultiTouchMotionAccumulator mMultiTouchMotionAccumulator; michael@0: michael@0: // Specifies the pointer id bits that are in use, and their associated tracking id. michael@0: BitSet32 mPointerIdBits; michael@0: int32_t mPointerTrackingIdMap[MAX_POINTER_ID + 1]; michael@0: }; michael@0: michael@0: michael@0: class JoystickInputMapper : public InputMapper { michael@0: public: michael@0: JoystickInputMapper(InputDevice* device); michael@0: virtual ~JoystickInputMapper(); michael@0: michael@0: virtual uint32_t getSources(); michael@0: virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); michael@0: virtual void dump(String8& dump); michael@0: virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes); michael@0: virtual void reset(nsecs_t when); michael@0: virtual void process(const RawEvent* rawEvent); michael@0: michael@0: private: michael@0: struct Axis { michael@0: RawAbsoluteAxisInfo rawAxisInfo; michael@0: AxisInfo axisInfo; michael@0: michael@0: bool explicitlyMapped; // true if the axis was explicitly assigned an axis id michael@0: michael@0: float scale; // scale factor from raw to normalized values michael@0: float offset; // offset to add after scaling for normalization michael@0: float highScale; // scale factor from raw to normalized values of high split michael@0: float highOffset; // offset to add after scaling for normalization of high split michael@0: michael@0: float min; // normalized inclusive minimum michael@0: float max; // normalized inclusive maximum michael@0: float flat; // normalized flat region size michael@0: float fuzz; // normalized error tolerance michael@0: float resolution; // normalized resolution in units/mm michael@0: michael@0: float filter; // filter out small variations of this size michael@0: float currentValue; // current value michael@0: float newValue; // most recent value michael@0: float highCurrentValue; // current value of high split michael@0: float highNewValue; // most recent value of high split michael@0: michael@0: void initialize(const RawAbsoluteAxisInfo& rawAxisInfo, const AxisInfo& axisInfo, michael@0: bool explicitlyMapped, float scale, float offset, michael@0: float highScale, float highOffset, michael@0: float min, float max, float flat, float fuzz, float resolution) { michael@0: this->rawAxisInfo = rawAxisInfo; michael@0: this->axisInfo = axisInfo; michael@0: this->explicitlyMapped = explicitlyMapped; michael@0: this->scale = scale; michael@0: this->offset = offset; michael@0: this->highScale = highScale; michael@0: this->highOffset = highOffset; michael@0: this->min = min; michael@0: this->max = max; michael@0: this->flat = flat; michael@0: this->fuzz = fuzz; michael@0: this->resolution = resolution; michael@0: this->filter = 0; michael@0: resetValue(); michael@0: } michael@0: michael@0: void resetValue() { michael@0: this->currentValue = 0; michael@0: this->newValue = 0; michael@0: this->highCurrentValue = 0; michael@0: this->highNewValue = 0; michael@0: } michael@0: }; michael@0: michael@0: // Axes indexed by raw ABS_* axis index. michael@0: KeyedVector mAxes; michael@0: michael@0: void sync(nsecs_t when, bool force); michael@0: michael@0: bool haveAxis(int32_t axisId); michael@0: void pruneAxes(bool ignoreExplicitlyMappedAxes); michael@0: bool filterAxes(bool force); michael@0: michael@0: static bool hasValueChangedSignificantly(float filter, michael@0: float newValue, float currentValue, float min, float max); michael@0: static bool hasMovedNearerToValueWithinFilteredRange(float filter, michael@0: float newValue, float currentValue, float thresholdValue); michael@0: michael@0: static bool isCenteredAxis(int32_t axis); michael@0: static int32_t getCompatAxis(int32_t axis); michael@0: michael@0: static void addMotionRange(int32_t axisId, const Axis& axis, InputDeviceInfo* info); michael@0: static void setPointerCoordsAxisValue(PointerCoords* pointerCoords, int32_t axis, michael@0: float value); michael@0: }; michael@0: michael@0: } // namespace android michael@0: michael@0: #endif // _UI_INPUT_READER_H