Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 39a128a8 authored by Jeff Brown's avatar Jeff Brown Committed by Android Git Automerger
Browse files

am 46b9ac0a: Native input dispatch rewrite work in progress.

Merge commit '46b9ac0ae2162309774a7478cd9d4e578747bfc2' into gingerbread

* commit '46b9ac0ae2162309774a7478cd9d4e578747bfc2':
  Native input dispatch rewrite work in progress.
parents 1b02178d e839a589
Loading
Loading
Loading
Loading
+113 −44
Original line number Diff line number Diff line
@@ -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:
    EventHub();
    // Synthetic raw event type codes produced when devices are added or removed.
    enum {
        DEVICE_ADDED = 0x10000000,
        DEVICE_REMOVED = 0x20000000
    };

    status_t errorCheck() const;
    virtual uint32_t getDeviceClasses(int32_t deviceId) const = 0;

    // 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
    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;
};
    uint32_t getDeviceClasses(int32_t deviceId) const;

    String8 getDeviceName(int32_t deviceId) const;
class EventHub : public EventHubInterface
{
public:
    EventHub();

    int getAbsoluteInfo(int32_t deviceId, int axis, int *outMinValue,
            int* outMaxValue, int* outFlat, int* outFuzz) const;
    status_t errorCheck() const;

    int getSwitchState(int sw) const;
    int getSwitchState(int32_t deviceId, int sw) const;
    virtual uint32_t getDeviceClasses(int32_t deviceId) const;
    
    int getScancodeState(int key) const;
    int getScancodeState(int32_t deviceId, int key) const;
    virtual String8 getDeviceName(int32_t deviceId) const;
    
    int getKeycodeState(int key) const;
    int getKeycodeState(int32_t deviceId, int key) const;
    virtual int getAbsoluteInfo(int32_t deviceId, int axis, int *outMinValue,
            int* outMaxValue, int* outFlat, int* outFuzz) 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
    };
    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;

    // examine key input devices for specific framework keycode support
    bool hasKeys(size_t numCodes, int32_t* keyCodes, uint8_t* outFlags);
    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;
    

include/ui/Input.h

0 → 100644
+310 −0
Original line number Diff line number Diff line
/*
 * 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
+198 −0
Original line number Diff line number Diff line
/*
 * 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
+409 −0

File added.

Preview size limit exceeded, changes collapsed.

+134 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading