am 6d0fec2d: Refactor input reader to support new device types more easily.
Merge commit '6d0fec2de3601821f4f44eeb7d7deedebb2b7117' into gingerbread-plus-aosp * commit '6d0fec2de3601821f4f44eeb7d7deedebb2b7117': Refactor input reader to support new device types more easily.
This commit is contained in:
@@ -173768,6 +173768,17 @@
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="getKeyboardType"
|
||||
return="int"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="getMotionRange"
|
||||
return="android.view.InputDevice.MotionRange"
|
||||
abstract="false"
|
||||
@@ -173816,6 +173827,39 @@
|
||||
<parameter name="keyCode" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<field name="KEYBOARD_TYPE_ALPHABETIC"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="2"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="KEYBOARD_TYPE_NONE"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="0"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="KEYBOARD_TYPE_NON_ALPHABETIC"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="1"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="MOTION_RANGE_ORIENTATION"
|
||||
type="int"
|
||||
transient="false"
|
||||
@@ -173915,6 +173959,17 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="SOURCE_ANY"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="-256"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="SOURCE_CLASS_BUTTON"
|
||||
type="int"
|
||||
transient="false"
|
||||
|
||||
@@ -30,11 +30,13 @@ package android.view;
|
||||
* As a further wrinkle, different kinds of input sources uses different coordinate systems
|
||||
* to describe motion events. Refer to the comments on the input source constants for
|
||||
* the appropriate interpretation.
|
||||
* </p>
|
||||
*/
|
||||
public final class InputDevice {
|
||||
private int mId;
|
||||
private String mName;
|
||||
private int mSources;
|
||||
private int mKeyboardType;
|
||||
|
||||
/**
|
||||
* A mask for input source classes.
|
||||
@@ -173,6 +175,12 @@ public final class InputDevice {
|
||||
* @see #SOURCE_CLASS_JOYSTICK
|
||||
*/
|
||||
public static final int SOURCE_JOYSTICK_RIGHT = 0x02000000 | SOURCE_CLASS_JOYSTICK;
|
||||
|
||||
/**
|
||||
* A special input source constant that is used when filtering input devices
|
||||
* to match devices that provide any type of input source.
|
||||
*/
|
||||
public static final int SOURCE_ANY = 0xffffff00;
|
||||
|
||||
/**
|
||||
* Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#x}.
|
||||
@@ -237,6 +245,22 @@ public final class InputDevice {
|
||||
* @see #getMotionRange
|
||||
*/
|
||||
public static final int MOTION_RANGE_ORIENTATION = 8;
|
||||
|
||||
/**
|
||||
* There is no keyboard.
|
||||
*/
|
||||
public static final int KEYBOARD_TYPE_NONE = 0;
|
||||
|
||||
/**
|
||||
* The keyboard is not fully alphabetic. It may be a numeric keypad or an assortment
|
||||
* of buttons that are not mapped as alphabetic keys suitable for text input.
|
||||
*/
|
||||
public static final int KEYBOARD_TYPE_NON_ALPHABETIC = 1;
|
||||
|
||||
/**
|
||||
* The keyboard supports a complement of alphabetic keys.
|
||||
*/
|
||||
public static final int KEYBOARD_TYPE_ALPHABETIC = 2;
|
||||
|
||||
/**
|
||||
* Gets information about the input device with the specified id.
|
||||
@@ -264,6 +288,14 @@ public final class InputDevice {
|
||||
return mSources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the keyboard type.
|
||||
* @return The keyboard type.
|
||||
*/
|
||||
public int getKeyboardType() {
|
||||
return mKeyboardType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the key character map associated with this input device.
|
||||
* @return The key character map.
|
||||
|
||||
@@ -181,61 +181,61 @@ public final class MotionEvent extends InputEvent implements Parcelable {
|
||||
* Offset for the sample's X coordinate.
|
||||
* @hide
|
||||
*/
|
||||
static public final int SAMPLE_X = 0;
|
||||
static private final int SAMPLE_X = 0;
|
||||
|
||||
/**
|
||||
* Offset for the sample's Y coordinate.
|
||||
* @hide
|
||||
*/
|
||||
static public final int SAMPLE_Y = 1;
|
||||
static private final int SAMPLE_Y = 1;
|
||||
|
||||
/**
|
||||
* Offset for the sample's pressure.
|
||||
* @hide
|
||||
*/
|
||||
static public final int SAMPLE_PRESSURE = 2;
|
||||
static private final int SAMPLE_PRESSURE = 2;
|
||||
|
||||
/**
|
||||
* Offset for the sample's size
|
||||
* @hide
|
||||
*/
|
||||
static public final int SAMPLE_SIZE = 3;
|
||||
static private final int SAMPLE_SIZE = 3;
|
||||
|
||||
/**
|
||||
* Offset for the sample's touch major axis length.
|
||||
* @hide
|
||||
*/
|
||||
static public final int SAMPLE_TOUCH_MAJOR = 4;
|
||||
static private final int SAMPLE_TOUCH_MAJOR = 4;
|
||||
|
||||
/**
|
||||
* Offset for the sample's touch minor axis length.
|
||||
* @hide
|
||||
*/
|
||||
static public final int SAMPLE_TOUCH_MINOR = 5;
|
||||
static private final int SAMPLE_TOUCH_MINOR = 5;
|
||||
|
||||
/**
|
||||
* Offset for the sample's tool major axis length.
|
||||
* @hide
|
||||
*/
|
||||
static public final int SAMPLE_TOOL_MAJOR = 6;
|
||||
static private final int SAMPLE_TOOL_MAJOR = 6;
|
||||
|
||||
/**
|
||||
* Offset for the sample's tool minor axis length.
|
||||
* @hide
|
||||
*/
|
||||
static public final int SAMPLE_TOOL_MINOR = 7;
|
||||
static private final int SAMPLE_TOOL_MINOR = 7;
|
||||
|
||||
/**
|
||||
* Offset for the sample's orientation.
|
||||
* @hide
|
||||
*/
|
||||
static public final int SAMPLE_ORIENTATION = 8;
|
||||
static private final int SAMPLE_ORIENTATION = 8;
|
||||
|
||||
/**
|
||||
* Number of data items for each sample.
|
||||
* @hide
|
||||
*/
|
||||
static public final int NUM_SAMPLE_DATA = 9;
|
||||
static private final int NUM_SAMPLE_DATA = 9;
|
||||
|
||||
/**
|
||||
* Number of possible pointers.
|
||||
@@ -918,7 +918,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
|
||||
* upwards, is perfectly circular or is of unknown orientation. A positive angle
|
||||
* indicates that the major axis of contact is oriented to the right. A negative angle
|
||||
* indicates that the major axis of contact is oriented to the left.
|
||||
* The full range is from -PI/4 radians (finger pointing fully left) to PI/4 radians
|
||||
* The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians
|
||||
* (finger pointing fully right).
|
||||
* @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
|
||||
* (the first pointer that is down) to {@link #getPointerCount()}-1.
|
||||
@@ -1614,28 +1614,28 @@ public final class MotionEvent extends InputEvent implements Parcelable {
|
||||
* upwards, is perfectly circular or is of unknown orientation. A positive angle
|
||||
* indicates that the major axis of contact is oriented to the right. A negative angle
|
||||
* indicates that the major axis of contact is oriented to the left.
|
||||
* The full range is from -PI/4 radians (finger pointing fully left) to PI/4 radians
|
||||
* The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians
|
||||
* (finger pointing fully right).
|
||||
*/
|
||||
public float orientation;
|
||||
|
||||
/*
|
||||
private static final float PI_8 = (float) (Math.PI / 8);
|
||||
private static final float PI_4 = (float) (Math.PI / 4);
|
||||
|
||||
public float getTouchWidth() {
|
||||
return Math.abs(orientation) > PI_8 ? touchMajor : touchMinor;
|
||||
return Math.abs(orientation) > PI_4 ? touchMajor : touchMinor;
|
||||
}
|
||||
|
||||
public float getTouchHeight() {
|
||||
return Math.abs(orientation) > PI_8 ? touchMinor : touchMajor;
|
||||
return Math.abs(orientation) > PI_4 ? touchMinor : touchMajor;
|
||||
}
|
||||
|
||||
public float getToolWidth() {
|
||||
return Math.abs(orientation) > PI_8 ? toolMajor : toolMinor;
|
||||
return Math.abs(orientation) > PI_4 ? toolMajor : toolMinor;
|
||||
}
|
||||
|
||||
public float getToolHeight() {
|
||||
return Math.abs(orientation) > PI_8 ? toolMinor : toolMajor;
|
||||
return Math.abs(orientation) > PI_4 ? toolMinor : toolMajor;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -59,6 +59,31 @@ namespace android {
|
||||
|
||||
class KeyLayoutMap;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
};
|
||||
|
||||
/* Describes an absolute axis. */
|
||||
struct RawAbsoluteAxisInfo {
|
||||
bool valid; // true if the information is valid, false otherwise
|
||||
|
||||
int32_t minValue; // minimum value
|
||||
int32_t maxValue; // maximum value
|
||||
int32_t flat; // center flat position, eg. flat == 8 means center is between -8 and 8
|
||||
int32_t fuzz; // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise
|
||||
|
||||
inline int32_t getRange() { return maxValue - minValue; }
|
||||
};
|
||||
|
||||
/*
|
||||
* Input device classes.
|
||||
*/
|
||||
@@ -82,7 +107,10 @@ enum {
|
||||
INPUT_DEVICE_CLASS_DPAD = 0x00000020,
|
||||
|
||||
/* The input device is a gamepad (implies keyboard). */
|
||||
INPUT_DEVICE_CLASS_GAMEPAD = 0x00000040
|
||||
INPUT_DEVICE_CLASS_GAMEPAD = 0x00000040,
|
||||
|
||||
/* The input device has switches. */
|
||||
INPUT_DEVICE_CLASS_SWITCH = 0x00000080,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -114,8 +142,8 @@ public:
|
||||
|
||||
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 getAbsoluteAxisInfo(int32_t deviceId, int axis,
|
||||
RawAbsoluteAxisInfo* outAxisInfo) const = 0;
|
||||
|
||||
virtual status_t scancodeToKeycode(int32_t deviceId, int scancode,
|
||||
int32_t* outKeycode, uint32_t* outFlags) const = 0;
|
||||
@@ -131,26 +159,19 @@ public:
|
||||
* 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;
|
||||
virtual bool getEvent(RawEvent* outEvent) = 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;
|
||||
virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const = 0;
|
||||
virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const = 0;
|
||||
virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const = 0;
|
||||
|
||||
/*
|
||||
* Examine key input devices for specific framework keycode support
|
||||
*/
|
||||
virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes,
|
||||
virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
|
||||
uint8_t* outFlags) const = 0;
|
||||
};
|
||||
|
||||
@@ -165,33 +186,28 @@ public:
|
||||
|
||||
virtual String8 getDeviceName(int32_t deviceId) const;
|
||||
|
||||
virtual int getAbsoluteInfo(int32_t deviceId, int axis, int *outMinValue,
|
||||
int* outMaxValue, int* outFlat, int* outFuzz) const;
|
||||
|
||||
virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
|
||||
RawAbsoluteAxisInfo* outAxisInfo) const;
|
||||
|
||||
virtual status_t scancodeToKeycode(int32_t deviceId, int scancode,
|
||||
int32_t* outKeycode, uint32_t* outFlags) const;
|
||||
|
||||
virtual void addExcludedDevice(const char* deviceName);
|
||||
|
||||
virtual int32_t getScanCodeState(int32_t deviceId, int32_t deviceClasses,
|
||||
int32_t scanCode) const;
|
||||
virtual int32_t getKeyCodeState(int32_t deviceId, int32_t deviceClasses,
|
||||
int32_t keyCode) const;
|
||||
virtual int32_t getSwitchState(int32_t deviceId, int32_t deviceClasses,
|
||||
int32_t sw) const;
|
||||
virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const;
|
||||
virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const;
|
||||
virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const;
|
||||
|
||||
virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const;
|
||||
virtual bool markSupportedKeyCodes(int32_t deviceId, 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,
|
||||
int32_t* outValue, nsecs_t* outWhen);
|
||||
virtual bool getEvent(RawEvent* outEvent);
|
||||
|
||||
protected:
|
||||
virtual ~EventHub();
|
||||
|
||||
private:
|
||||
bool openPlatformInput(void);
|
||||
int32_t convertDeviceKey_TI_P2(int code);
|
||||
|
||||
int open_device(const char *device);
|
||||
int close_device(const char *device);
|
||||
@@ -220,6 +236,8 @@ private:
|
||||
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;
|
||||
bool markSupportedKeyCodesLocked(device_t* device, size_t numCodes,
|
||||
const int32_t* keyCodes, uint8_t* outFlags) const;
|
||||
|
||||
// Protect all internal state.
|
||||
mutable Mutex mLock;
|
||||
|
||||
@@ -23,7 +23,10 @@
|
||||
|
||||
#include <android/input.h>
|
||||
#include <utils/Vector.h>
|
||||
#include <utils/KeyedVector.h>
|
||||
#include <utils/Timers.h>
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/String8.h>
|
||||
|
||||
/*
|
||||
* Additional private constants not defined in ndk/ui/input.h.
|
||||
@@ -47,21 +50,16 @@ struct AInputEvent {
|
||||
virtual ~AInputEvent() { }
|
||||
};
|
||||
|
||||
namespace android {
|
||||
|
||||
/*
|
||||
* A raw event as retrieved from the EventHub.
|
||||
* Declare a concrete type for the NDK's input device forward declaration.
|
||||
*/
|
||||
struct RawEvent {
|
||||
nsecs_t when;
|
||||
int32_t deviceId;
|
||||
int32_t type;
|
||||
int32_t scanCode;
|
||||
int32_t keyCode;
|
||||
int32_t value;
|
||||
uint32_t flags;
|
||||
struct AInputDevice {
|
||||
virtual ~AInputDevice() { }
|
||||
};
|
||||
|
||||
|
||||
namespace android {
|
||||
|
||||
/*
|
||||
* Flags that flow alongside events in the input dispatch system to help with certain
|
||||
* policy decisions such as waking from device sleep.
|
||||
@@ -424,6 +422,69 @@ private:
|
||||
MotionEvent mMotionEvent;
|
||||
};
|
||||
|
||||
/*
|
||||
* Describes the characteristics and capabilities of an input device.
|
||||
*/
|
||||
class InputDeviceInfo {
|
||||
public:
|
||||
InputDeviceInfo();
|
||||
InputDeviceInfo(const InputDeviceInfo& other);
|
||||
~InputDeviceInfo();
|
||||
|
||||
struct MotionRange {
|
||||
float min;
|
||||
float max;
|
||||
float flat;
|
||||
float fuzz;
|
||||
};
|
||||
|
||||
void initialize(int32_t id, const String8& name);
|
||||
|
||||
inline int32_t getId() const { return mId; }
|
||||
inline const String8 getName() const { return mName; }
|
||||
inline uint32_t getSources() const { return mSources; }
|
||||
|
||||
const MotionRange* getMotionRange(int32_t rangeType) const;
|
||||
|
||||
void addSource(uint32_t source);
|
||||
void addMotionRange(int32_t rangeType, float min, float max, float flat, float fuzz);
|
||||
void addMotionRange(int32_t rangeType, const MotionRange& range);
|
||||
|
||||
inline void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; }
|
||||
inline int32_t getKeyboardType() const { return mKeyboardType; }
|
||||
|
||||
private:
|
||||
int32_t mId;
|
||||
String8 mName;
|
||||
uint32_t mSources;
|
||||
int32_t mKeyboardType;
|
||||
|
||||
KeyedVector<int32_t, MotionRange> mMotionRanges;
|
||||
};
|
||||
|
||||
/*
|
||||
* Provides remote access to information about an input device.
|
||||
*
|
||||
* Note: This is essentially a wrapper for Binder calls into the Window Manager Service.
|
||||
*/
|
||||
class InputDeviceProxy : public RefBase, public AInputDevice {
|
||||
protected:
|
||||
InputDeviceProxy();
|
||||
virtual ~InputDeviceProxy();
|
||||
|
||||
public:
|
||||
static void getDeviceIds(Vector<int32_t>& outIds);
|
||||
|
||||
static sp<InputDeviceProxy> getDevice(int32_t id);
|
||||
|
||||
inline const InputDeviceInfo* getInfo() { return & mInfo; }
|
||||
|
||||
// TODO add hasKeys, keymap, etc...
|
||||
|
||||
private:
|
||||
InputDeviceInfo mInfo;
|
||||
};
|
||||
|
||||
|
||||
} // namespace android
|
||||
|
||||
|
||||
@@ -1,353 +0,0 @@
|
||||
/*
|
||||
* 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_DEVICE_H
|
||||
#define _UI_INPUT_DEVICE_H
|
||||
|
||||
#include <ui/EventHub.h>
|
||||
#include <ui/Input.h>
|
||||
#include <utils/KeyedVector.h>
|
||||
#include <utils/threads.h>
|
||||
#include <utils/Timers.h>
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/String8.h>
|
||||
#include <utils/BitSet.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Maximum pointer id value supported.
|
||||
* (This is limited by our use of BitSet32 to track pointer assignments.) */
|
||||
#define MAX_POINTER_ID 31
|
||||
|
||||
/* Maximum number of historical samples to average. */
|
||||
#define AVERAGING_HISTORY_SIZE 5
|
||||
|
||||
|
||||
namespace android {
|
||||
|
||||
extern int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState);
|
||||
extern int32_t rotateKeyCode(int32_t keyCode, int32_t orientation);
|
||||
|
||||
|
||||
/*
|
||||
* An input device structure tracks the state of a single input device.
|
||||
*
|
||||
* This structure is only used by ReaderThread and is not intended to be shared with
|
||||
* DispatcherThread (because that would require locking). This works out fine because
|
||||
* DispatcherThread is only interested in cooked event data anyways and does not need
|
||||
* any of the low-level data from InputDevice.
|
||||
*/
|
||||
struct InputDevice {
|
||||
struct AbsoluteAxisInfo {
|
||||
bool valid; // set to true if axis parameters are known, false otherwise
|
||||
|
||||
int32_t minValue; // minimum value
|
||||
int32_t maxValue; // maximum value
|
||||
int32_t range; // range of values, equal to maxValue - minValue
|
||||
int32_t flat; // center flat position, eg. flat == 8 means center is between -8 and 8
|
||||
int32_t fuzz; // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise
|
||||
};
|
||||
|
||||
struct VirtualKey {
|
||||
int32_t keyCode;
|
||||
int32_t scanCode;
|
||||
uint32_t flags;
|
||||
|
||||
// computed hit box, specified in touch screen coords based on known display size
|
||||
int32_t hitLeft;
|
||||
int32_t hitTop;
|
||||
int32_t hitRight;
|
||||
int32_t hitBottom;
|
||||
|
||||
inline bool isHit(int32_t x, int32_t y) const {
|
||||
return x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom;
|
||||
}
|
||||
};
|
||||
|
||||
struct KeyboardState {
|
||||
struct Current {
|
||||
int32_t metaState;
|
||||
nsecs_t downTime; // time of most recent key down
|
||||
} current;
|
||||
|
||||
void reset();
|
||||
};
|
||||
|
||||
struct TrackballState {
|
||||
struct Accumulator {
|
||||
enum {
|
||||
FIELD_BTN_MOUSE = 1,
|
||||
FIELD_REL_X = 2,
|
||||
FIELD_REL_Y = 4
|
||||
};
|
||||
|
||||
uint32_t fields;
|
||||
|
||||
bool btnMouse;
|
||||
int32_t relX;
|
||||
int32_t relY;
|
||||
|
||||
inline void clear() {
|
||||
fields = 0;
|
||||
}
|
||||
|
||||
inline bool isDirty() {
|
||||
return fields != 0;
|
||||
}
|
||||
} accumulator;
|
||||
|
||||
struct Current {
|
||||
bool down;
|
||||
nsecs_t downTime;
|
||||
} current;
|
||||
|
||||
struct Precalculated {
|
||||
float xScale;
|
||||
float yScale;
|
||||
float xPrecision;
|
||||
float yPrecision;
|
||||
} precalculated;
|
||||
|
||||
void reset();
|
||||
};
|
||||
|
||||
struct SingleTouchScreenState {
|
||||
struct Accumulator {
|
||||
enum {
|
||||
FIELD_BTN_TOUCH = 1,
|
||||
FIELD_ABS_X = 2,
|
||||
FIELD_ABS_Y = 4,
|
||||
FIELD_ABS_PRESSURE = 8,
|
||||
FIELD_ABS_TOOL_WIDTH = 16
|
||||
};
|
||||
|
||||
uint32_t fields;
|
||||
|
||||
bool btnTouch;
|
||||
int32_t absX;
|
||||
int32_t absY;
|
||||
int32_t absPressure;
|
||||
int32_t absToolWidth;
|
||||
|
||||
inline void clear() {
|
||||
fields = 0;
|
||||
}
|
||||
|
||||
inline bool isDirty() {
|
||||
return fields != 0;
|
||||
}
|
||||
} accumulator;
|
||||
|
||||
struct Current {
|
||||
bool down;
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
int32_t pressure;
|
||||
int32_t size;
|
||||
} current;
|
||||
|
||||
void reset();
|
||||
};
|
||||
|
||||
struct MultiTouchScreenState {
|
||||
struct Accumulator {
|
||||
enum {
|
||||
FIELD_ABS_MT_POSITION_X = 1,
|
||||
FIELD_ABS_MT_POSITION_Y = 2,
|
||||
FIELD_ABS_MT_TOUCH_MAJOR = 4,
|
||||
FIELD_ABS_MT_TOUCH_MINOR = 8,
|
||||
FIELD_ABS_MT_WIDTH_MAJOR = 16,
|
||||
FIELD_ABS_MT_WIDTH_MINOR = 32,
|
||||
FIELD_ABS_MT_ORIENTATION = 64,
|
||||
FIELD_ABS_MT_TRACKING_ID = 128
|
||||
};
|
||||
|
||||
uint32_t pointerCount;
|
||||
struct Pointer {
|
||||
uint32_t fields;
|
||||
|
||||
int32_t absMTPositionX;
|
||||
int32_t absMTPositionY;
|
||||
int32_t absMTTouchMajor;
|
||||
int32_t absMTTouchMinor;
|
||||
int32_t absMTWidthMajor;
|
||||
int32_t absMTWidthMinor;
|
||||
int32_t absMTOrientation;
|
||||
int32_t absMTTrackingId;
|
||||
|
||||
inline void clear() {
|
||||
fields = 0;
|
||||
}
|
||||
} pointers[MAX_POINTERS + 1]; // + 1 to remove the need for extra range checks
|
||||
|
||||
inline void clear() {
|
||||
pointerCount = 0;
|
||||
pointers[0].clear();
|
||||
}
|
||||
|
||||
inline bool isDirty() {
|
||||
return pointerCount != 0;
|
||||
}
|
||||
} accumulator;
|
||||
|
||||
void reset();
|
||||
};
|
||||
|
||||
struct PointerData {
|
||||
uint32_t id;
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
int32_t pressure;
|
||||
int32_t size;
|
||||
int32_t touchMajor;
|
||||
int32_t touchMinor;
|
||||
int32_t toolMajor;
|
||||
int32_t toolMinor;
|
||||
int32_t orientation;
|
||||
};
|
||||
|
||||
struct TouchData {
|
||||
uint32_t pointerCount;
|
||||
PointerData pointers[MAX_POINTERS];
|
||||
BitSet32 idBits;
|
||||
uint32_t idToIndex[MAX_POINTER_ID + 1];
|
||||
|
||||
void copyFrom(const TouchData& other);
|
||||
|
||||
inline void clear() {
|
||||
pointerCount = 0;
|
||||
idBits.clear();
|
||||
}
|
||||
};
|
||||
|
||||
// common state used for both single-touch and multi-touch screens after the initial
|
||||
// touch decoding has been performed
|
||||
struct TouchScreenState {
|
||||
Vector<VirtualKey> virtualKeys;
|
||||
|
||||
struct Parameters {
|
||||
bool useBadTouchFilter;
|
||||
bool useJumpyTouchFilter;
|
||||
bool useAveragingTouchFilter;
|
||||
|
||||
AbsoluteAxisInfo xAxis;
|
||||
AbsoluteAxisInfo yAxis;
|
||||
AbsoluteAxisInfo pressureAxis;
|
||||
AbsoluteAxisInfo sizeAxis;
|
||||
AbsoluteAxisInfo orientationAxis;
|
||||
} parameters;
|
||||
|
||||
// The touch data of the current sample being processed.
|
||||
TouchData currentTouch;
|
||||
|
||||
// The touch data of the previous sample that was processed. This is updated
|
||||
// incrementally while the current sample is being processed.
|
||||
TouchData lastTouch;
|
||||
|
||||
// The time the primary pointer last went down.
|
||||
nsecs_t downTime;
|
||||
|
||||
struct CurrentVirtualKeyState {
|
||||
enum Status {
|
||||
STATUS_UP,
|
||||
STATUS_DOWN,
|
||||
STATUS_CANCELED
|
||||
};
|
||||
|
||||
Status status;
|
||||
nsecs_t downTime;
|
||||
int32_t keyCode;
|
||||
int32_t scanCode;
|
||||
} currentVirtualKey;
|
||||
|
||||
struct AveragingTouchFilterState {
|
||||
// Individual history tracks are stored by pointer id
|
||||
uint32_t historyStart[MAX_POINTERS];
|
||||
uint32_t historyEnd[MAX_POINTERS];
|
||||
struct {
|
||||
struct {
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
int32_t pressure;
|
||||
} pointers[MAX_POINTERS];
|
||||
} historyData[AVERAGING_HISTORY_SIZE];
|
||||
} averagingTouchFilter;
|
||||
|
||||
struct JumpTouchFilterState {
|
||||
int32_t jumpyPointsDropped;
|
||||
} jumpyTouchFilter;
|
||||
|
||||
struct Precalculated {
|
||||
int32_t xOrigin;
|
||||
float xScale;
|
||||
|
||||
int32_t yOrigin;
|
||||
float yScale;
|
||||
|
||||
int32_t pressureOrigin;
|
||||
float pressureScale;
|
||||
|
||||
int32_t sizeOrigin;
|
||||
float sizeScale;
|
||||
|
||||
float orientationScale;
|
||||
} precalculated;
|
||||
|
||||
void reset();
|
||||
|
||||
bool applyBadTouchFilter();
|
||||
bool applyJumpyTouchFilter();
|
||||
void applyAveragingTouchFilter();
|
||||
void calculatePointerIds();
|
||||
|
||||
bool isPointInsideDisplay(int32_t x, int32_t y) const;
|
||||
const InputDevice::VirtualKey* findVirtualKeyHit() const;
|
||||
};
|
||||
|
||||
InputDevice(int32_t id, uint32_t classes, String8 name);
|
||||
|
||||
int32_t id;
|
||||
uint32_t classes;
|
||||
String8 name;
|
||||
bool ignored;
|
||||
|
||||
KeyboardState keyboard;
|
||||
TrackballState trackball;
|
||||
TouchScreenState touchScreen;
|
||||
union {
|
||||
SingleTouchScreenState singleTouchScreen;
|
||||
MultiTouchScreenState multiTouchScreen;
|
||||
};
|
||||
|
||||
void reset();
|
||||
|
||||
inline bool isKeyboard() const { return classes & INPUT_DEVICE_CLASS_KEYBOARD; }
|
||||
inline bool isAlphaKey() const { return classes & INPUT_DEVICE_CLASS_ALPHAKEY; }
|
||||
inline bool isTrackball() const { return classes & INPUT_DEVICE_CLASS_TRACKBALL; }
|
||||
inline bool isDPad() const { return classes & INPUT_DEVICE_CLASS_DPAD; }
|
||||
inline bool isSingleTouchScreen() const { return (classes
|
||||
& (INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT))
|
||||
== INPUT_DEVICE_CLASS_TOUCHSCREEN; }
|
||||
inline bool isMultiTouchScreen() const { return classes
|
||||
& INPUT_DEVICE_CLASS_TOUCHSCREEN_MT; }
|
||||
inline bool isTouchScreen() const { return classes
|
||||
& (INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT); }
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // _UI_INPUT_DEVICE_H
|
||||
@@ -96,22 +96,28 @@ public:
|
||||
virtual void preemptInputDispatch() = 0;
|
||||
|
||||
/* Gets input device configuration. */
|
||||
virtual void getInputConfiguration(InputConfiguration* outConfiguration) const = 0;
|
||||
virtual void getInputConfiguration(InputConfiguration* outConfiguration) = 0;
|
||||
|
||||
/*
|
||||
* Queries current input state.
|
||||
* deviceId may be -1 to search for the device automatically, filtered by class.
|
||||
* deviceClasses may be -1 to ignore device class while searching.
|
||||
/* Gets information about the specified input device.
|
||||
* Returns OK if the device information was obtained or NAME_NOT_FOUND if there
|
||||
* was no such device.
|
||||
*/
|
||||
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;
|
||||
virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) = 0;
|
||||
|
||||
/* Gets the list of all registered device ids. */
|
||||
virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds) = 0;
|
||||
|
||||
/* Queries current input state. */
|
||||
virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
|
||||
int32_t scanCode) = 0;
|
||||
virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
|
||||
int32_t keyCode) = 0;
|
||||
virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
|
||||
int32_t sw) = 0;
|
||||
|
||||
/* Determines whether physical keys exist for the given framework-domain key codes. */
|
||||
virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const = 0;
|
||||
virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
|
||||
size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0;
|
||||
};
|
||||
|
||||
class InputManager : public InputManagerInterface {
|
||||
@@ -140,14 +146,17 @@ public:
|
||||
|
||||
virtual void preemptInputDispatch();
|
||||
|
||||
virtual void getInputConfiguration(InputConfiguration* outConfiguration) const;
|
||||
virtual int32_t getScanCodeState(int32_t deviceId, int32_t deviceClasses,
|
||||
int32_t scanCode) const;
|
||||
virtual int32_t getKeyCodeState(int32_t deviceId, int32_t deviceClasses,
|
||||
int32_t keyCode) const;
|
||||
virtual int32_t getSwitchState(int32_t deviceId, int32_t deviceClasses,
|
||||
int32_t sw) const;
|
||||
virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const;
|
||||
virtual void getInputConfiguration(InputConfiguration* outConfiguration);
|
||||
virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo);
|
||||
virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds);
|
||||
virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
|
||||
int32_t scanCode);
|
||||
virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
|
||||
int32_t keyCode);
|
||||
virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
|
||||
int32_t sw);
|
||||
virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
|
||||
size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags);
|
||||
|
||||
private:
|
||||
sp<InputReaderInterface> mReader;
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#include <ui/EventHub.h>
|
||||
#include <ui/Input.h>
|
||||
#include <ui/InputDevice.h>
|
||||
#include <ui/InputDispatcher.h>
|
||||
#include <utils/KeyedVector.h>
|
||||
#include <utils/threads.h>
|
||||
@@ -33,6 +32,10 @@
|
||||
|
||||
namespace android {
|
||||
|
||||
class InputDevice;
|
||||
class InputMapper;
|
||||
|
||||
|
||||
/*
|
||||
* Input reader policy interface.
|
||||
*
|
||||
@@ -68,14 +71,6 @@ public:
|
||||
// The input dispatcher should perform special filtering in preparation for
|
||||
// a pending app switch.
|
||||
ACTION_APP_SWITCH_COMING = 0x00000002,
|
||||
|
||||
// The input dispatcher should add POLICY_FLAG_WOKE_HERE to the policy flags it
|
||||
// passes through the dispatch pipeline.
|
||||
ACTION_WOKE_HERE = 0x00000004,
|
||||
|
||||
// The input dispatcher should add POLICY_FLAG_BRIGHT_HERE to the policy flags it
|
||||
// passes through the dispatch pipeline.
|
||||
ACTION_BRIGHT_HERE = 0x00000008,
|
||||
};
|
||||
|
||||
/* Describes a virtual key. */
|
||||
@@ -101,38 +96,30 @@ public:
|
||||
|
||||
/* Intercepts a key event.
|
||||
* The policy can use this method as an opportunity to perform power management functions
|
||||
* and early event preprocessing.
|
||||
* and early event preprocessing such as updating policy flags.
|
||||
*
|
||||
* Returns a policy action constant such as ACTION_DISPATCH.
|
||||
*/
|
||||
virtual int32_t interceptKey(nsecs_t when, int32_t deviceId,
|
||||
bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) = 0;
|
||||
|
||||
/* Intercepts a trackball event.
|
||||
* The policy can use this method as an opportunity to perform power management functions
|
||||
* and early event preprocessing.
|
||||
*
|
||||
* Returns a policy action constant such as ACTION_DISPATCH.
|
||||
*/
|
||||
virtual int32_t interceptTrackball(nsecs_t when, bool buttonChanged, bool buttonDown,
|
||||
bool rolled) = 0;
|
||||
|
||||
/* Intercepts a touch event.
|
||||
* The policy can use this method as an opportunity to perform power management functions
|
||||
* and early event preprocessing.
|
||||
*
|
||||
* Returns a policy action constant such as ACTION_DISPATCH.
|
||||
*/
|
||||
virtual int32_t interceptTouch(nsecs_t when) = 0;
|
||||
bool down, int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) = 0;
|
||||
|
||||
/* Intercepts a switch event.
|
||||
* The policy can use this method as an opportunity to perform power management functions
|
||||
* and early event preprocessing.
|
||||
* and early event preprocessing such as updating policy flags.
|
||||
*
|
||||
* Switches are not dispatched to applications so this method should
|
||||
* usually return ACTION_NONE.
|
||||
*/
|
||||
virtual int32_t interceptSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) = 0;
|
||||
virtual int32_t interceptSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
|
||||
uint32_t& policyFlags) = 0;
|
||||
|
||||
/* Intercepts a generic touch, trackball or other event.
|
||||
* The policy can use this method as an opportunity to perform power management functions
|
||||
* and early event preprocessing such as updating policy flags.
|
||||
*
|
||||
* Returns a policy action constant such as ACTION_DISPATCH.
|
||||
*/
|
||||
virtual int32_t interceptGeneric(nsecs_t when, uint32_t& policyFlags) = 0;
|
||||
|
||||
/* Determines whether to turn on some hacks we have to improve the touch interaction with a
|
||||
* certain device whose screen currently is not all that good.
|
||||
@@ -167,32 +154,52 @@ public:
|
||||
*/
|
||||
virtual void loopOnce() = 0;
|
||||
|
||||
/* Gets the current virtual key. Returns false if not down.
|
||||
*
|
||||
* This method may be called on any thread (usually by the input manager).
|
||||
*/
|
||||
virtual bool getCurrentVirtualKey(int32_t* outKeyCode, int32_t* outScanCode) const = 0;
|
||||
|
||||
/* Gets the current input device configuration.
|
||||
*
|
||||
* This method may be called on any thread (usually by the input manager).
|
||||
*/
|
||||
virtual void getCurrentInputConfiguration(InputConfiguration* outConfiguration) const = 0;
|
||||
virtual void getInputConfiguration(InputConfiguration* outConfiguration) = 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.
|
||||
/* Gets information about the specified input device.
|
||||
* Returns OK if the device information was obtained or NAME_NOT_FOUND if there
|
||||
* was no such device.
|
||||
*
|
||||
* This method may be called on any thread (usually by the input manager).
|
||||
*/
|
||||
virtual int32_t getCurrentScanCodeState(int32_t deviceId, int32_t deviceClasses,
|
||||
int32_t scanCode) const = 0;
|
||||
virtual int32_t getCurrentKeyCodeState(int32_t deviceId, int32_t deviceClasses,
|
||||
int32_t keyCode) const = 0;
|
||||
virtual int32_t getCurrentSwitchState(int32_t deviceId, int32_t deviceClasses,
|
||||
int32_t sw) const = 0;
|
||||
virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) = 0;
|
||||
|
||||
/* Gets the list of all registered device ids. */
|
||||
virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds) = 0;
|
||||
|
||||
/* Query current input state. */
|
||||
virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
|
||||
int32_t scanCode) = 0;
|
||||
virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
|
||||
int32_t keyCode) = 0;
|
||||
virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
|
||||
int32_t sw) = 0;
|
||||
|
||||
/* Determine whether physical keys exist for the given framework-domain key codes. */
|
||||
virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const = 0;
|
||||
virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
|
||||
size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0;
|
||||
};
|
||||
|
||||
|
||||
/* Internal interface used by individual input devices to access global input device state
|
||||
* and parameters maintained by the input reader.
|
||||
*/
|
||||
class InputReaderContext {
|
||||
protected:
|
||||
InputReaderContext() { }
|
||||
virtual ~InputReaderContext() { }
|
||||
|
||||
public:
|
||||
virtual void updateGlobalMetaState() = 0;
|
||||
virtual int32_t getGlobalMetaState() = 0;
|
||||
|
||||
virtual InputReaderPolicyInterface* getPolicy() = 0;
|
||||
virtual InputDispatcherInterface* getDispatcher() = 0;
|
||||
virtual EventHubInterface* getEventHub() = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -201,10 +208,11 @@ public:
|
||||
* event filtering in low power states, are controlled by a separate policy object.
|
||||
*
|
||||
* IMPORTANT INVARIANT:
|
||||
* Because the policy can potentially block or cause re-entrance into the input reader,
|
||||
* the input reader never calls into the policy while holding its internal locks.
|
||||
* Because the policy and dispatcher can potentially block or cause re-entrance into
|
||||
* the input reader, the input reader never calls into other components while holding
|
||||
* an exclusive internal lock.
|
||||
*/
|
||||
class InputReader : public InputReaderInterface {
|
||||
class InputReader : public InputReaderInterface, private InputReaderContext {
|
||||
public:
|
||||
InputReader(const sp<EventHubInterface>& eventHub,
|
||||
const sp<InputReaderPolicyInterface>& policy,
|
||||
@@ -213,107 +221,69 @@ public:
|
||||
|
||||
virtual void loopOnce();
|
||||
|
||||
virtual bool getCurrentVirtualKey(int32_t* outKeyCode, int32_t* outScanCode) const;
|
||||
virtual void getInputConfiguration(InputConfiguration* outConfiguration);
|
||||
|
||||
virtual void getCurrentInputConfiguration(InputConfiguration* outConfiguration) const;
|
||||
virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo);
|
||||
virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds);
|
||||
|
||||
virtual int32_t getCurrentScanCodeState(int32_t deviceId, int32_t deviceClasses,
|
||||
int32_t scanCode) const;
|
||||
virtual int32_t getCurrentKeyCodeState(int32_t deviceId, int32_t deviceClasses,
|
||||
int32_t keyCode) const;
|
||||
virtual int32_t getCurrentSwitchState(int32_t deviceId, int32_t deviceClasses,
|
||||
int32_t sw) const;
|
||||
virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
|
||||
int32_t scanCode);
|
||||
virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
|
||||
int32_t keyCode);
|
||||
virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
|
||||
int32_t sw);
|
||||
|
||||
virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const;
|
||||
virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
|
||||
size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags);
|
||||
|
||||
private:
|
||||
// Lock that must be acquired while manipulating state that may be concurrently accessed
|
||||
// from other threads by input state query methods. It should be held for as short a
|
||||
// time as possible.
|
||||
//
|
||||
// Exported state:
|
||||
// - global virtual key code and scan code
|
||||
// - device list and immutable properties of devices such as id, name, and class
|
||||
// (but not other internal device state)
|
||||
mutable Mutex mExportedStateLock;
|
||||
|
||||
// current virtual key information (lock mExportedStateLock)
|
||||
int32_t mExportedVirtualKeyCode;
|
||||
int32_t mExportedVirtualScanCode;
|
||||
|
||||
// current input configuration (lock mExportedStateLock)
|
||||
InputConfiguration mExportedInputConfiguration;
|
||||
|
||||
// combined key meta state
|
||||
int32_t mGlobalMetaState;
|
||||
|
||||
sp<EventHubInterface> mEventHub;
|
||||
sp<InputReaderPolicyInterface> mPolicy;
|
||||
sp<InputDispatcherInterface> mDispatcher;
|
||||
|
||||
virtual InputReaderPolicyInterface* getPolicy() { return mPolicy.get(); }
|
||||
virtual InputDispatcherInterface* getDispatcher() { return mDispatcher.get(); }
|
||||
virtual EventHubInterface* getEventHub() { return mEventHub.get(); }
|
||||
|
||||
// This reader/writer lock guards the list of input devices.
|
||||
// The writer lock must be held whenever the list of input devices is modified
|
||||
// and then promptly released.
|
||||
// The reader lock must be held whenever the list of input devices is traversed or an
|
||||
// input device in the list is accessed.
|
||||
// This lock only protects the registry and prevents inadvertent deletion of device objects
|
||||
// that are in use. Individual devices are responsible for guarding their own internal state
|
||||
// as needed for concurrent operation.
|
||||
RWLock mDeviceRegistryLock;
|
||||
KeyedVector<int32_t, InputDevice*> mDevices;
|
||||
|
||||
// display properties needed to translate touch screen coordinates into display coordinates
|
||||
int32_t mDisplayOrientation;
|
||||
int32_t mDisplayWidth;
|
||||
int32_t mDisplayHeight;
|
||||
|
||||
// low-level input event decoding
|
||||
// low-level input event decoding and device management
|
||||
void process(const RawEvent* rawEvent);
|
||||
void handleDeviceAdded(const RawEvent* rawEvent);
|
||||
void handleDeviceRemoved(const RawEvent* rawEvent);
|
||||
void handleSync(const RawEvent* rawEvent);
|
||||
void handleKey(const RawEvent* rawEvent);
|
||||
void handleRelativeMotion(const RawEvent* rawEvent);
|
||||
void handleAbsoluteMotion(const RawEvent* rawEvent);
|
||||
void handleSwitch(const RawEvent* rawEvent);
|
||||
|
||||
// input policy processing and dispatch
|
||||
void onKey(nsecs_t when, InputDevice* device, bool down,
|
||||
int32_t keyCode, int32_t scanCode, uint32_t policyFlags);
|
||||
void onSwitch(nsecs_t when, InputDevice* device, int32_t switchCode, int32_t switchValue);
|
||||
void onSingleTouchScreenStateChanged(nsecs_t when, InputDevice* device);
|
||||
void onMultiTouchScreenStateChanged(nsecs_t when, InputDevice* device);
|
||||
void onTouchScreenChanged(nsecs_t when, InputDevice* device, bool havePointerIds);
|
||||
void onTrackballStateChanged(nsecs_t when, InputDevice* device);
|
||||
void onConfigurationChanged(nsecs_t when);
|
||||
|
||||
bool applyStandardInputDispatchPolicyActions(nsecs_t when,
|
||||
int32_t policyActions, uint32_t* policyFlags);
|
||||
|
||||
bool consumeVirtualKeyTouches(nsecs_t when, InputDevice* device, uint32_t policyFlags);
|
||||
void dispatchVirtualKey(nsecs_t when, InputDevice* device, uint32_t policyFlags,
|
||||
int32_t keyEventAction, int32_t keyEventFlags);
|
||||
void dispatchTouches(nsecs_t when, InputDevice* device, uint32_t policyFlags);
|
||||
void dispatchTouch(nsecs_t when, InputDevice* device, uint32_t policyFlags,
|
||||
InputDevice::TouchData* touch, BitSet32 idBits, uint32_t changedId,
|
||||
int32_t motionEventAction);
|
||||
|
||||
// display
|
||||
void resetDisplayProperties();
|
||||
bool refreshDisplayProperties();
|
||||
|
||||
// device management
|
||||
InputDevice* getDevice(int32_t deviceId);
|
||||
InputDevice* getNonIgnoredDevice(int32_t deviceId);
|
||||
void addDevice(nsecs_t when, int32_t deviceId);
|
||||
void removeDevice(nsecs_t when, InputDevice* device);
|
||||
void configureDevice(InputDevice* device);
|
||||
void configureDeviceForCurrentDisplaySize(InputDevice* device);
|
||||
void configureVirtualKeys(InputDevice* device);
|
||||
void configureAbsoluteAxisInfo(InputDevice* device, int axis, const char* name,
|
||||
InputDevice::AbsoluteAxisInfo* out);
|
||||
void removeDevice(nsecs_t when, int32_t deviceId);
|
||||
InputDevice* createDevice(int32_t deviceId, const String8& name, uint32_t classes);
|
||||
void configureExcludedDevices();
|
||||
|
||||
// global meta state management for all devices
|
||||
void resetGlobalMetaState();
|
||||
int32_t globalMetaState();
|
||||
void consumeEvent(const RawEvent* rawEvent);
|
||||
|
||||
// virtual key management
|
||||
void updateExportedVirtualKeyState();
|
||||
void handleConfigurationChanged(nsecs_t when);
|
||||
|
||||
// input configuration management
|
||||
void updateExportedInputConfiguration();
|
||||
// state management for all devices
|
||||
Mutex mStateLock;
|
||||
|
||||
int32_t mGlobalMetaState;
|
||||
virtual void updateGlobalMetaState();
|
||||
virtual int32_t getGlobalMetaState();
|
||||
|
||||
InputConfiguration mInputConfiguration;
|
||||
void updateInputConfiguration();
|
||||
|
||||
// state queries
|
||||
typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code);
|
||||
int32_t getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
|
||||
GetStateFunc getStateFunc);
|
||||
bool markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
|
||||
const int32_t* keyCodes, uint8_t* outFlags);
|
||||
};
|
||||
|
||||
|
||||
@@ -329,6 +299,527 @@ private:
|
||||
virtual bool threadLoop();
|
||||
};
|
||||
|
||||
|
||||
/* Represents the state of a single input device. */
|
||||
class InputDevice {
|
||||
public:
|
||||
InputDevice(InputReaderContext* context, int32_t id, const String8& name);
|
||||
~InputDevice();
|
||||
|
||||
inline InputReaderContext* getContext() { return mContext; }
|
||||
inline int32_t getId() { return mId; }
|
||||
inline const String8& getName() { return mName; }
|
||||
inline uint32_t getSources() { return mSources; }
|
||||
|
||||
inline bool isIgnored() { return mMappers.isEmpty(); }
|
||||
|
||||
void addMapper(InputMapper* mapper);
|
||||
void configure();
|
||||
void reset();
|
||||
void process(const RawEvent* rawEvent);
|
||||
|
||||
void getDeviceInfo(InputDeviceInfo* outDeviceInfo);
|
||||
int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
|
||||
int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
|
||||
int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
|
||||
bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
|
||||
const int32_t* keyCodes, uint8_t* outFlags);
|
||||
|
||||
int32_t getMetaState();
|
||||
|
||||
private:
|
||||
InputReaderContext* mContext;
|
||||
int32_t mId;
|
||||
|
||||
Vector<InputMapper*> mMappers;
|
||||
|
||||
String8 mName;
|
||||
uint32_t mSources;
|
||||
|
||||
typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code);
|
||||
int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc);
|
||||
};
|
||||
|
||||
|
||||
/* An input mapper transforms raw input events into cooked event data.
|
||||
* A single input device can have multiple associated input mappers in order to interpret
|
||||
* different classes of events.
|
||||
*/
|
||||
class InputMapper {
|
||||
public:
|
||||
InputMapper(InputDevice* device);
|
||||
virtual ~InputMapper();
|
||||
|
||||
inline InputDevice* getDevice() { return mDevice; }
|
||||
inline int32_t getDeviceId() { return mDevice->getId(); }
|
||||
inline const String8 getDeviceName() { return mDevice->getName(); }
|
||||
inline InputReaderContext* getContext() { return mContext; }
|
||||
inline InputReaderPolicyInterface* getPolicy() { return mContext->getPolicy(); }
|
||||
inline InputDispatcherInterface* getDispatcher() { return mContext->getDispatcher(); }
|
||||
inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
|
||||
|
||||
virtual uint32_t getSources() = 0;
|
||||
virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
|
||||
virtual void configure();
|
||||
virtual void reset();
|
||||
virtual void process(const RawEvent* rawEvent) = 0;
|
||||
|
||||
virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
|
||||
virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
|
||||
virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
|
||||
virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
|
||||
const int32_t* keyCodes, uint8_t* outFlags);
|
||||
|
||||
virtual int32_t getMetaState();
|
||||
|
||||
protected:
|
||||
InputDevice* mDevice;
|
||||
InputReaderContext* mContext;
|
||||
|
||||
bool applyStandardPolicyActions(nsecs_t when, int32_t policyActions);
|
||||
};
|
||||
|
||||
|
||||
class SwitchInputMapper : public InputMapper {
|
||||
public:
|
||||
SwitchInputMapper(InputDevice* device);
|
||||
virtual ~SwitchInputMapper();
|
||||
|
||||
virtual uint32_t getSources();
|
||||
virtual void process(const RawEvent* rawEvent);
|
||||
|
||||
virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
|
||||
|
||||
private:
|
||||
void processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue);
|
||||
};
|
||||
|
||||
|
||||
class KeyboardInputMapper : public InputMapper {
|
||||
public:
|
||||
KeyboardInputMapper(InputDevice* device, int32_t associatedDisplayId, uint32_t sources,
|
||||
int32_t keyboardType);
|
||||
virtual ~KeyboardInputMapper();
|
||||
|
||||
virtual uint32_t getSources();
|
||||
virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
|
||||
virtual void reset();
|
||||
virtual void process(const RawEvent* rawEvent);
|
||||
|
||||
virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
|
||||
virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
|
||||
virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
|
||||
const int32_t* keyCodes, uint8_t* outFlags);
|
||||
|
||||
virtual int32_t getMetaState();
|
||||
|
||||
private:
|
||||
struct KeyDown {
|
||||
int32_t keyCode;
|
||||
int32_t scanCode;
|
||||
};
|
||||
|
||||
int32_t mAssociatedDisplayId;
|
||||
uint32_t mSources;
|
||||
int32_t mKeyboardType;
|
||||
|
||||
Vector<KeyDown> mKeyDowns; // keys that are down
|
||||
int32_t mMetaState;
|
||||
nsecs_t mDownTime; // time of most recent key down
|
||||
|
||||
void initialize();
|
||||
|
||||
bool isKeyboardOrGamepadKey(int32_t scanCode);
|
||||
void processKey(nsecs_t when, bool down, int32_t keyCode, int32_t scanCode,
|
||||
uint32_t policyFlags);
|
||||
|
||||
ssize_t findKeyDown(int32_t scanCode);
|
||||
};
|
||||
|
||||
|
||||
class TrackballInputMapper : public InputMapper {
|
||||
public:
|
||||
TrackballInputMapper(InputDevice* device, int32_t associatedDisplayId);
|
||||
virtual ~TrackballInputMapper();
|
||||
|
||||
virtual uint32_t getSources();
|
||||
virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
|
||||
virtual void reset();
|
||||
virtual void process(const RawEvent* rawEvent);
|
||||
|
||||
private:
|
||||
// Amount that trackball needs to move in order to generate a key event.
|
||||
static const int32_t TRACKBALL_MOVEMENT_THRESHOLD = 6;
|
||||
|
||||
int32_t mAssociatedDisplayId;
|
||||
|
||||
struct Accumulator {
|
||||
enum {
|
||||
FIELD_BTN_MOUSE = 1,
|
||||
FIELD_REL_X = 2,
|
||||
FIELD_REL_Y = 4
|
||||
};
|
||||
|
||||
uint32_t fields;
|
||||
|
||||
bool btnMouse;
|
||||
int32_t relX;
|
||||
int32_t relY;
|
||||
|
||||
inline void clear() {
|
||||
fields = 0;
|
||||
}
|
||||
|
||||
inline bool isDirty() {
|
||||
return fields != 0;
|
||||
}
|
||||
} mAccumulator;
|
||||
|
||||
bool mDown;
|
||||
nsecs_t mDownTime;
|
||||
|
||||
float mXScale;
|
||||
float mYScale;
|
||||
float mXPrecision;
|
||||
float mYPrecision;
|
||||
|
||||
void initialize();
|
||||
|
||||
void sync(nsecs_t when);
|
||||
};
|
||||
|
||||
|
||||
class TouchInputMapper : public InputMapper {
|
||||
public:
|
||||
TouchInputMapper(InputDevice* device, int32_t associatedDisplayId);
|
||||
virtual ~TouchInputMapper();
|
||||
|
||||
virtual uint32_t getSources();
|
||||
virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
|
||||
virtual void configure();
|
||||
virtual void reset();
|
||||
|
||||
virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
|
||||
virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
|
||||
virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
|
||||
const int32_t* keyCodes, uint8_t* outFlags);
|
||||
|
||||
protected:
|
||||
/* Maximum pointer id value supported.
|
||||
* (This is limited by our use of BitSet32 to track pointer assignments.) */
|
||||
static const uint32_t MAX_POINTER_ID = 31;
|
||||
|
||||
struct VirtualKey {
|
||||
int32_t keyCode;
|
||||
int32_t scanCode;
|
||||
uint32_t flags;
|
||||
|
||||
// computed hit box, specified in touch screen coords based on known display size
|
||||
int32_t hitLeft;
|
||||
int32_t hitTop;
|
||||
int32_t hitRight;
|
||||
int32_t hitBottom;
|
||||
|
||||
inline bool isHit(int32_t x, int32_t y) const {
|
||||
return x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom;
|
||||
}
|
||||
};
|
||||
|
||||
struct PointerData {
|
||||
uint32_t id;
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
int32_t pressure;
|
||||
int32_t size;
|
||||
int32_t touchMajor;
|
||||
int32_t touchMinor;
|
||||
int32_t toolMajor;
|
||||
int32_t toolMinor;
|
||||
int32_t orientation;
|
||||
};
|
||||
|
||||
struct TouchData {
|
||||
uint32_t pointerCount;
|
||||
PointerData pointers[MAX_POINTERS];
|
||||
BitSet32 idBits;
|
||||
uint32_t idToIndex[MAX_POINTER_ID + 1];
|
||||
|
||||
void copyFrom(const TouchData& other) {
|
||||
pointerCount = other.pointerCount;
|
||||
idBits = other.idBits;
|
||||
|
||||
for (uint32_t i = 0; i < pointerCount; i++) {
|
||||
pointers[i] = other.pointers[i];
|
||||
idToIndex[i] = other.idToIndex[i];
|
||||
}
|
||||
}
|
||||
|
||||
inline void clear() {
|
||||
pointerCount = 0;
|
||||
idBits.clear();
|
||||
}
|
||||
};
|
||||
|
||||
int32_t mAssociatedDisplayId;
|
||||
Vector<VirtualKey> mVirtualKeys;
|
||||
|
||||
// Immutable configuration parameters.
|
||||
struct Parameters {
|
||||
bool useBadTouchFilter;
|
||||
bool useJumpyTouchFilter;
|
||||
bool useAveragingTouchFilter;
|
||||
} mParameters;
|
||||
|
||||
// Raw axis information.
|
||||
struct Axes {
|
||||
RawAbsoluteAxisInfo x;
|
||||
RawAbsoluteAxisInfo y;
|
||||
RawAbsoluteAxisInfo pressure;
|
||||
RawAbsoluteAxisInfo size;
|
||||
RawAbsoluteAxisInfo touchMajor;
|
||||
RawAbsoluteAxisInfo touchMinor;
|
||||
RawAbsoluteAxisInfo toolMajor;
|
||||
RawAbsoluteAxisInfo toolMinor;
|
||||
RawAbsoluteAxisInfo orientation;
|
||||
} mAxes;
|
||||
|
||||
// The surface orientation and width and height set by configureSurface().
|
||||
int32_t mSurfaceOrientation;
|
||||
int32_t mSurfaceWidth, mSurfaceHeight;
|
||||
|
||||
// Translation and scaling factors, orientation-independent.
|
||||
int32_t mXOrigin;
|
||||
float mXScale;
|
||||
float mXPrecision;
|
||||
|
||||
int32_t mYOrigin;
|
||||
float mYScale;
|
||||
float mYPrecision;
|
||||
|
||||
int32_t mPressureOrigin;
|
||||
float mPressureScale;
|
||||
|
||||
int32_t mSizeOrigin;
|
||||
float mSizeScale;
|
||||
|
||||
float mOrientationScale;
|
||||
|
||||
// Oriented motion ranges for input device info.
|
||||
struct OrientedRanges {
|
||||
InputDeviceInfo::MotionRange x;
|
||||
InputDeviceInfo::MotionRange y;
|
||||
InputDeviceInfo::MotionRange pressure;
|
||||
InputDeviceInfo::MotionRange size;
|
||||
InputDeviceInfo::MotionRange touchMajor;
|
||||
InputDeviceInfo::MotionRange touchMinor;
|
||||
InputDeviceInfo::MotionRange toolMajor;
|
||||
InputDeviceInfo::MotionRange toolMinor;
|
||||
InputDeviceInfo::MotionRange orientation;
|
||||
} mOrientedRanges;
|
||||
|
||||
// Oriented dimensions and precision.
|
||||
float mOrientedSurfaceWidth, mOrientedSurfaceHeight;
|
||||
float mOrientedXPrecision, mOrientedYPrecision;
|
||||
|
||||
// The touch data of the current sample being processed.
|
||||
TouchData mCurrentTouch;
|
||||
|
||||
// The touch data of the previous sample that was processed. This is updated
|
||||
// incrementally while the current sample is being processed.
|
||||
TouchData mLastTouch;
|
||||
|
||||
// The time the primary pointer last went down.
|
||||
nsecs_t mDownTime;
|
||||
|
||||
struct CurrentVirtualKeyState {
|
||||
bool down;
|
||||
nsecs_t downTime;
|
||||
int32_t keyCode;
|
||||
int32_t scanCode;
|
||||
} mCurrentVirtualKey;
|
||||
|
||||
// Lock for virtual key state.
|
||||
Mutex mVirtualKeyLock; // methods use "Lvk" suffix
|
||||
|
||||
virtual void configureAxes();
|
||||
virtual bool configureSurface();
|
||||
virtual void configureVirtualKeys();
|
||||
|
||||
enum TouchResult {
|
||||
// Dispatch the touch normally.
|
||||
DISPATCH_TOUCH,
|
||||
// Do not dispatch the touch, but keep tracking the current stroke.
|
||||
SKIP_TOUCH,
|
||||
// Do not dispatch the touch, and drop all information associated with the current stoke
|
||||
// so the next movement will appear as a new down.
|
||||
DROP_STROKE
|
||||
};
|
||||
|
||||
void syncTouch(nsecs_t when, bool havePointerIds);
|
||||
|
||||
private:
|
||||
/* Maximum number of historical samples to average. */
|
||||
static const uint32_t AVERAGING_HISTORY_SIZE = 5;
|
||||
|
||||
/* Slop distance for jumpy pointer detection.
|
||||
* The vertical range of the screen divided by this is our epsilon value. */
|
||||
static const uint32_t JUMPY_EPSILON_DIVISOR = 212;
|
||||
|
||||
/* Number of jumpy points to drop for touchscreens that need it. */
|
||||
static const uint32_t JUMPY_TRANSITION_DROPS = 3;
|
||||
static const uint32_t JUMPY_DROP_LIMIT = 3;
|
||||
|
||||
/* Maximum squared distance for averaging.
|
||||
* If moving farther than this, turn of averaging to avoid lag in response. */
|
||||
static const uint64_t AVERAGING_DISTANCE_LIMIT = 75 * 75;
|
||||
|
||||
struct AveragingTouchFilterState {
|
||||
// Individual history tracks are stored by pointer id
|
||||
uint32_t historyStart[MAX_POINTERS];
|
||||
uint32_t historyEnd[MAX_POINTERS];
|
||||
struct {
|
||||
struct {
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
int32_t pressure;
|
||||
} pointers[MAX_POINTERS];
|
||||
} historyData[AVERAGING_HISTORY_SIZE];
|
||||
} mAveragingTouchFilter;
|
||||
|
||||
struct JumpTouchFilterState {
|
||||
uint32_t jumpyPointsDropped;
|
||||
} mJumpyTouchFilter;
|
||||
|
||||
struct PointerDistanceHeapElement {
|
||||
uint32_t currentPointerIndex : 8;
|
||||
uint32_t lastPointerIndex : 8;
|
||||
uint64_t distance : 48; // squared distance
|
||||
};
|
||||
|
||||
void initialize();
|
||||
|
||||
TouchResult consumeOffScreenTouches(nsecs_t when, uint32_t policyFlags);
|
||||
void dispatchTouches(nsecs_t when, uint32_t policyFlags);
|
||||
void dispatchTouch(nsecs_t when, uint32_t policyFlags, TouchData* touch,
|
||||
BitSet32 idBits, uint32_t changedId, int32_t motionEventAction);
|
||||
|
||||
bool isPointInsideSurface(int32_t x, int32_t y);
|
||||
const VirtualKey* findVirtualKeyHitLvk(int32_t x, int32_t y);
|
||||
|
||||
bool applyBadTouchFilter();
|
||||
bool applyJumpyTouchFilter();
|
||||
void applyAveragingTouchFilter();
|
||||
void calculatePointerIds();
|
||||
};
|
||||
|
||||
|
||||
class SingleTouchInputMapper : public TouchInputMapper {
|
||||
public:
|
||||
SingleTouchInputMapper(InputDevice* device, int32_t associatedDisplayId);
|
||||
virtual ~SingleTouchInputMapper();
|
||||
|
||||
virtual void reset();
|
||||
virtual void process(const RawEvent* rawEvent);
|
||||
|
||||
protected:
|
||||
virtual void configureAxes();
|
||||
|
||||
private:
|
||||
struct Accumulator {
|
||||
enum {
|
||||
FIELD_BTN_TOUCH = 1,
|
||||
FIELD_ABS_X = 2,
|
||||
FIELD_ABS_Y = 4,
|
||||
FIELD_ABS_PRESSURE = 8,
|
||||
FIELD_ABS_TOOL_WIDTH = 16
|
||||
};
|
||||
|
||||
uint32_t fields;
|
||||
|
||||
bool btnTouch;
|
||||
int32_t absX;
|
||||
int32_t absY;
|
||||
int32_t absPressure;
|
||||
int32_t absToolWidth;
|
||||
|
||||
inline void clear() {
|
||||
fields = 0;
|
||||
}
|
||||
|
||||
inline bool isDirty() {
|
||||
return fields != 0;
|
||||
}
|
||||
} mAccumulator;
|
||||
|
||||
bool mDown;
|
||||
int32_t mX;
|
||||
int32_t mY;
|
||||
int32_t mPressure;
|
||||
int32_t mSize;
|
||||
|
||||
void initialize();
|
||||
|
||||
void sync(nsecs_t when);
|
||||
};
|
||||
|
||||
|
||||
class MultiTouchInputMapper : public TouchInputMapper {
|
||||
public:
|
||||
MultiTouchInputMapper(InputDevice* device, int32_t associatedDisplayId);
|
||||
virtual ~MultiTouchInputMapper();
|
||||
|
||||
virtual void reset();
|
||||
virtual void process(const RawEvent* rawEvent);
|
||||
|
||||
protected:
|
||||
virtual void configureAxes();
|
||||
|
||||
private:
|
||||
struct Accumulator {
|
||||
enum {
|
||||
FIELD_ABS_MT_POSITION_X = 1,
|
||||
FIELD_ABS_MT_POSITION_Y = 2,
|
||||
FIELD_ABS_MT_TOUCH_MAJOR = 4,
|
||||
FIELD_ABS_MT_TOUCH_MINOR = 8,
|
||||
FIELD_ABS_MT_WIDTH_MAJOR = 16,
|
||||
FIELD_ABS_MT_WIDTH_MINOR = 32,
|
||||
FIELD_ABS_MT_ORIENTATION = 64,
|
||||
FIELD_ABS_MT_TRACKING_ID = 128
|
||||
};
|
||||
|
||||
uint32_t pointerCount;
|
||||
struct Pointer {
|
||||
uint32_t fields;
|
||||
|
||||
int32_t absMTPositionX;
|
||||
int32_t absMTPositionY;
|
||||
int32_t absMTTouchMajor;
|
||||
int32_t absMTTouchMinor;
|
||||
int32_t absMTWidthMajor;
|
||||
int32_t absMTWidthMinor;
|
||||
int32_t absMTOrientation;
|
||||
int32_t absMTTrackingId;
|
||||
|
||||
inline void clear() {
|
||||
fields = 0;
|
||||
}
|
||||
} pointers[MAX_POINTERS + 1]; // + 1 to remove the need for extra range checks
|
||||
|
||||
inline void clear() {
|
||||
pointerCount = 0;
|
||||
pointers[0].clear();
|
||||
}
|
||||
|
||||
inline bool isDirty() {
|
||||
return pointerCount != 0;
|
||||
}
|
||||
} mAccumulator;
|
||||
|
||||
void initialize();
|
||||
|
||||
void sync(nsecs_t when);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // _UI_INPUT_READER_H
|
||||
|
||||
@@ -12,7 +12,6 @@ LOCAL_SRC_FILES:= \
|
||||
KeyLayoutMap.cpp \
|
||||
KeyCharacterMap.cpp \
|
||||
Input.cpp \
|
||||
InputDevice.cpp \
|
||||
InputDispatcher.cpp \
|
||||
InputManager.cpp \
|
||||
InputReader.cpp \
|
||||
|
||||
@@ -137,9 +137,14 @@ uint32_t EventHub::getDeviceClasses(int32_t deviceId) const
|
||||
return device->classes;
|
||||
}
|
||||
|
||||
int EventHub::getAbsoluteInfo(int32_t deviceId, int axis, int *outMinValue,
|
||||
int* outMaxValue, int* outFlat, int* outFuzz) const
|
||||
{
|
||||
status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,
|
||||
RawAbsoluteAxisInfo* outAxisInfo) const {
|
||||
outAxisInfo->valid = false;
|
||||
outAxisInfo->minValue = 0;
|
||||
outAxisInfo->maxValue = 0;
|
||||
outAxisInfo->flat = 0;
|
||||
outAxisInfo->fuzz = 0;
|
||||
|
||||
AutoMutex _l(mLock);
|
||||
device_t* device = getDevice(deviceId);
|
||||
if (device == NULL) return -1;
|
||||
@@ -147,38 +152,28 @@ int EventHub::getAbsoluteInfo(int32_t deviceId, int axis, int *outMinValue,
|
||||
struct input_absinfo info;
|
||||
|
||||
if(ioctl(mFDs[id_to_index(device->id)].fd, EVIOCGABS(axis), &info)) {
|
||||
LOGE("Error reading absolute controller %d for device %s fd %d\n",
|
||||
LOGW("Error reading absolute controller %d for device %s fd %d\n",
|
||||
axis, device->name.string(), mFDs[id_to_index(device->id)].fd);
|
||||
return -1;
|
||||
return -errno;
|
||||
}
|
||||
*outMinValue = info.minimum;
|
||||
*outMaxValue = info.maximum;
|
||||
*outFlat = info.flat;
|
||||
*outFuzz = info.fuzz;
|
||||
return 0;
|
||||
|
||||
if (info.minimum != info.maximum) {
|
||||
outAxisInfo->valid = true;
|
||||
outAxisInfo->minValue = info.minimum;
|
||||
outAxisInfo->maxValue = info.maximum;
|
||||
outAxisInfo->flat = info.flat;
|
||||
outAxisInfo->fuzz = info.fuzz;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t deviceClasses,
|
||||
int32_t scanCode) const {
|
||||
int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const {
|
||||
if (scanCode >= 0 && scanCode <= KEY_MAX) {
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
if (deviceId == -1) {
|
||||
for (int i = 0; i < mNumDevicesById; i++) {
|
||||
device_t* device = mDevicesById[i].device;
|
||||
if (device != NULL && (device->classes & deviceClasses) != 0) {
|
||||
int32_t result = getScanCodeStateLocked(device, scanCode);
|
||||
if (result >= AKEY_STATE_DOWN) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return AKEY_STATE_UP;
|
||||
} else {
|
||||
device_t* device = getDevice(deviceId);
|
||||
if (device != NULL) {
|
||||
return getScanCodeStateLocked(device, scanCode);
|
||||
}
|
||||
device_t* device = getDevice(deviceId);
|
||||
if (device != NULL) {
|
||||
return getScanCodeStateLocked(device, scanCode);
|
||||
}
|
||||
}
|
||||
return AKEY_STATE_UNKNOWN;
|
||||
@@ -194,25 +189,12 @@ int32_t EventHub::getScanCodeStateLocked(device_t* device, int32_t scanCode) con
|
||||
return AKEY_STATE_UNKNOWN;
|
||||
}
|
||||
|
||||
int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t deviceClasses,
|
||||
int32_t keyCode) const {
|
||||
int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
if (deviceId == -1) {
|
||||
for (int i = 0; i < mNumDevicesById; i++) {
|
||||
device_t* device = mDevicesById[i].device;
|
||||
if (device != NULL && (device->classes & deviceClasses) != 0) {
|
||||
int32_t result = getKeyCodeStateLocked(device, keyCode);
|
||||
if (result >= AKEY_STATE_DOWN) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return AKEY_STATE_UP;
|
||||
} else {
|
||||
device_t* device = getDevice(deviceId);
|
||||
if (device != NULL) {
|
||||
return getKeyCodeStateLocked(device, keyCode);
|
||||
}
|
||||
device_t* device = getDevice(deviceId);
|
||||
if (device != NULL) {
|
||||
return getKeyCodeStateLocked(device, keyCode);
|
||||
}
|
||||
return AKEY_STATE_UNKNOWN;
|
||||
}
|
||||
@@ -243,24 +225,15 @@ int32_t EventHub::getKeyCodeStateLocked(device_t* device, int32_t keyCode) const
|
||||
return AKEY_STATE_UNKNOWN;
|
||||
}
|
||||
|
||||
int32_t EventHub::getSwitchState(int32_t deviceId, int32_t deviceClasses, int32_t sw) const {
|
||||
int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const {
|
||||
#ifdef EV_SW
|
||||
if (sw >= 0 && sw <= SW_MAX) {
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
if (deviceId == -1) {
|
||||
deviceId = mSwitches[sw];
|
||||
if (deviceId == 0) {
|
||||
return AKEY_STATE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
device_t* device = getDevice(deviceId);
|
||||
if (device == NULL) {
|
||||
return AKEY_STATE_UNKNOWN;
|
||||
if (device != NULL) {
|
||||
return getSwitchStateLocked(device, sw);
|
||||
}
|
||||
|
||||
return getSwitchStateLocked(device, sw);
|
||||
}
|
||||
#endif
|
||||
return AKEY_STATE_UNKNOWN;
|
||||
@@ -276,6 +249,42 @@ int32_t EventHub::getSwitchStateLocked(device_t* device, int32_t sw) const {
|
||||
return AKEY_STATE_UNKNOWN;
|
||||
}
|
||||
|
||||
bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
|
||||
const int32_t* keyCodes, uint8_t* outFlags) const {
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
device_t* device = getDevice(deviceId);
|
||||
if (device != NULL) {
|
||||
return markSupportedKeyCodesLocked(device, numCodes, keyCodes, outFlags);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EventHub::markSupportedKeyCodesLocked(device_t* device, size_t numCodes,
|
||||
const int32_t* keyCodes, uint8_t* outFlags) const {
|
||||
if (device->layoutMap == NULL || device->keyBitmask == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector<int32_t> scanCodes;
|
||||
for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
|
||||
scanCodes.clear();
|
||||
|
||||
status_t err = device->layoutMap->findScancodes(keyCodes[codeIndex], &scanCodes);
|
||||
if (! err) {
|
||||
// check the possible scan codes identified by the layout map against the
|
||||
// map of codes actually emitted by the driver
|
||||
for (size_t sc = 0; sc < scanCodes.size(); sc++) {
|
||||
if (test_bit(scanCodes[sc], device->keyBitmask)) {
|
||||
outFlags[codeIndex] = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
status_t EventHub::scancodeToKeycode(int32_t deviceId, int scancode,
|
||||
int32_t* outKeycode, uint32_t* outFlags) const
|
||||
{
|
||||
@@ -324,17 +333,15 @@ EventHub::device_t* EventHub::getDevice(int32_t deviceId) const
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool EventHub::getEvent(int32_t* outDeviceId, int32_t* outType,
|
||||
int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags,
|
||||
int32_t* outValue, nsecs_t* outWhen)
|
||||
bool EventHub::getEvent(RawEvent* outEvent)
|
||||
{
|
||||
*outDeviceId = 0;
|
||||
*outType = 0;
|
||||
*outScancode = 0;
|
||||
*outKeycode = 0;
|
||||
*outFlags = 0;
|
||||
*outValue = 0;
|
||||
*outWhen = 0;
|
||||
outEvent->deviceId = 0;
|
||||
outEvent->type = 0;
|
||||
outEvent->scanCode = 0;
|
||||
outEvent->keyCode = 0;
|
||||
outEvent->flags = 0;
|
||||
outEvent->value = 0;
|
||||
outEvent->when = 0;
|
||||
|
||||
status_t err;
|
||||
|
||||
@@ -359,20 +366,27 @@ bool EventHub::getEvent(int32_t* outDeviceId, int32_t* outType,
|
||||
LOGV("Reporting device closed: id=0x%x, name=%s\n",
|
||||
device->id, device->path.string());
|
||||
mClosingDevices = device->next;
|
||||
*outDeviceId = device->id;
|
||||
if (*outDeviceId == mFirstKeyboardId) *outDeviceId = 0;
|
||||
*outType = DEVICE_REMOVED;
|
||||
if (device->id == mFirstKeyboardId) {
|
||||
outEvent->deviceId = 0;
|
||||
} else {
|
||||
outEvent->deviceId = device->id;
|
||||
}
|
||||
outEvent->type = DEVICE_REMOVED;
|
||||
delete device;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mOpeningDevices != NULL) {
|
||||
device_t* device = mOpeningDevices;
|
||||
LOGV("Reporting device opened: id=0x%x, name=%s\n",
|
||||
device->id, device->path.string());
|
||||
mOpeningDevices = device->next;
|
||||
*outDeviceId = device->id;
|
||||
if (*outDeviceId == mFirstKeyboardId) *outDeviceId = 0;
|
||||
*outType = DEVICE_ADDED;
|
||||
if (device->id == mFirstKeyboardId) {
|
||||
outEvent->deviceId = 0;
|
||||
} else {
|
||||
outEvent->deviceId = device->id;
|
||||
}
|
||||
outEvent->type = DEVICE_ADDED;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -399,27 +413,36 @@ bool EventHub::getEvent(int32_t* outDeviceId, int32_t* outType,
|
||||
if(mFDs[i].revents & POLLIN) {
|
||||
res = read(mFDs[i].fd, &iev, sizeof(iev));
|
||||
if (res == sizeof(iev)) {
|
||||
device_t* device = mDevices[i];
|
||||
LOGV("%s got: t0=%d, t1=%d, type=%d, code=%d, v=%d",
|
||||
mDevices[i]->path.string(),
|
||||
device->path.string(),
|
||||
(int) iev.time.tv_sec, (int) iev.time.tv_usec,
|
||||
iev.type, iev.code, iev.value);
|
||||
*outDeviceId = mDevices[i]->id;
|
||||
if (*outDeviceId == mFirstKeyboardId) *outDeviceId = 0;
|
||||
*outType = iev.type;
|
||||
*outScancode = iev.code;
|
||||
if (device->id == mFirstKeyboardId) {
|
||||
outEvent->deviceId = 0;
|
||||
} else {
|
||||
outEvent->deviceId = device->id;
|
||||
}
|
||||
outEvent->type = iev.type;
|
||||
outEvent->scanCode = iev.code;
|
||||
if (iev.type == EV_KEY) {
|
||||
err = mDevices[i]->layoutMap->map(iev.code, outKeycode, outFlags);
|
||||
LOGV("iev.code=%d outKeycode=%d outFlags=0x%08x err=%d\n",
|
||||
iev.code, *outKeycode, *outFlags, err);
|
||||
err = device->layoutMap->map(iev.code,
|
||||
& outEvent->keyCode, & outEvent->flags);
|
||||
LOGV("iev.code=%d keyCode=%d flags=0x%08x err=%d\n",
|
||||
iev.code, outEvent->keyCode, outEvent->flags, err);
|
||||
if (err != 0) {
|
||||
*outKeycode = AKEYCODE_UNKNOWN;
|
||||
*outFlags = 0;
|
||||
outEvent->keyCode = AKEYCODE_UNKNOWN;
|
||||
outEvent->flags = 0;
|
||||
}
|
||||
} else {
|
||||
*outKeycode = iev.code;
|
||||
outEvent->keyCode = iev.code;
|
||||
}
|
||||
*outValue = iev.value;
|
||||
*outWhen = s2ns(iev.time.tv_sec) + us2ns(iev.time.tv_usec);
|
||||
outEvent->value = iev.value;
|
||||
|
||||
// Use an event timestamp in the same timebase as
|
||||
// java.lang.System.nanoTime() and android.os.SystemClock.uptimeMillis()
|
||||
// as expected by the rest of the system.
|
||||
outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||
return true;
|
||||
} else {
|
||||
if (res<0) {
|
||||
@@ -479,37 +502,6 @@ bool EventHub::openPlatformInput(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inspect the known devices to determine whether physical keys exist for the given
|
||||
* framework-domain key codes.
|
||||
*/
|
||||
bool EventHub::hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const {
|
||||
for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
|
||||
outFlags[codeIndex] = 0;
|
||||
|
||||
// check each available hardware device for support for this keycode
|
||||
Vector<int32_t> scanCodes;
|
||||
for (int n = 0; (n < mFDCount) && (outFlags[codeIndex] == 0); n++) {
|
||||
if (mDevices[n]) {
|
||||
status_t err = mDevices[n]->layoutMap->findScancodes(
|
||||
keyCodes[codeIndex], &scanCodes);
|
||||
if (!err) {
|
||||
// check the possible scan codes identified by the layout map against the
|
||||
// map of codes actually emitted by the driver
|
||||
for (size_t sc = 0; sc < scanCodes.size(); sc++) {
|
||||
if (test_bit(scanCodes[sc], mDevices[n]->keyBitmask)) {
|
||||
outFlags[codeIndex] = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static bool containsNonZeroByte(const uint8_t* array, uint32_t startIndex, uint32_t endIndex) {
|
||||
@@ -715,16 +707,21 @@ int EventHub::open_device(const char *deviceName)
|
||||
// figure out the switches this device reports
|
||||
uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
|
||||
memset(sw_bitmask, 0, sizeof(sw_bitmask));
|
||||
bool hasSwitches = false;
|
||||
if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof(sw_bitmask)), sw_bitmask) >= 0) {
|
||||
for (int i=0; i<EV_SW; i++) {
|
||||
//LOGI("Device 0x%x sw %d: has=%d", device->id, i, test_bit(i, sw_bitmask));
|
||||
if (test_bit(i, sw_bitmask)) {
|
||||
hasSwitches = true;
|
||||
if (mSwitches[i] == 0) {
|
||||
mSwitches[i] = device->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasSwitches) {
|
||||
device->classes |= INPUT_DEVICE_CLASS_SWITCH;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
|
||||
|
||||
@@ -168,4 +168,63 @@ void MotionEvent::offsetLocation(float xOffset, float yOffset) {
|
||||
mYOffset += yOffset;
|
||||
}
|
||||
|
||||
// class InputDeviceInfo
|
||||
|
||||
InputDeviceInfo::InputDeviceInfo() {
|
||||
initialize(-1, String8("uninitialized device info"));
|
||||
}
|
||||
|
||||
InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) :
|
||||
mId(other.mId), mName(other.mName), mSources(other.mSources),
|
||||
mKeyboardType(other.mKeyboardType),
|
||||
mMotionRanges(other.mMotionRanges) {
|
||||
}
|
||||
|
||||
InputDeviceInfo::~InputDeviceInfo() {
|
||||
}
|
||||
|
||||
void InputDeviceInfo::initialize(int32_t id, const String8& name) {
|
||||
mId = id;
|
||||
mName = name;
|
||||
mSources = 0;
|
||||
mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
|
||||
mMotionRanges.clear();
|
||||
}
|
||||
|
||||
const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange(int32_t rangeType) const {
|
||||
ssize_t index = mMotionRanges.indexOfKey(rangeType);
|
||||
return index >= 0 ? & mMotionRanges.valueAt(index) : NULL;
|
||||
}
|
||||
|
||||
void InputDeviceInfo::addSource(uint32_t source) {
|
||||
mSources |= source;
|
||||
}
|
||||
|
||||
void InputDeviceInfo::addMotionRange(int32_t rangeType, float min, float max,
|
||||
float flat, float fuzz) {
|
||||
MotionRange range = { min, max, flat, fuzz };
|
||||
addMotionRange(rangeType, range);
|
||||
}
|
||||
|
||||
void InputDeviceInfo::addMotionRange(int32_t rangeType, const MotionRange& range) {
|
||||
mMotionRanges.add(rangeType, range);
|
||||
}
|
||||
|
||||
// class InputDeviceProxy
|
||||
|
||||
InputDeviceProxy::InputDeviceProxy() {
|
||||
}
|
||||
|
||||
InputDeviceProxy::~InputDeviceProxy() {
|
||||
}
|
||||
|
||||
void InputDeviceProxy::getDeviceIds(Vector<int32_t>& outIds) {
|
||||
// TODO use Binder
|
||||
}
|
||||
|
||||
sp<InputDeviceProxy> InputDeviceProxy::getDevice(int32_t id) {
|
||||
// TODO use Binder
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
@@ -1,729 +0,0 @@
|
||||
//
|
||||
// Copyright 2010 The Android Open Source Project
|
||||
//
|
||||
// The input reader.
|
||||
//
|
||||
#define LOG_TAG "InputDevice"
|
||||
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
// Log debug messages for each raw event received from the EventHub.
|
||||
#define DEBUG_RAW_EVENTS 0
|
||||
|
||||
// Log debug messages about touch screen filtering hacks.
|
||||
#define DEBUG_HACKS 0
|
||||
|
||||
// Log debug messages about virtual key processing.
|
||||
#define DEBUG_VIRTUAL_KEYS 0
|
||||
|
||||
// Log debug messages about pointers.
|
||||
#define DEBUG_POINTERS 0
|
||||
|
||||
// Log debug messages about pointer assignment calculations.
|
||||
#define DEBUG_POINTER_ASSIGNMENT 0
|
||||
|
||||
#include <cutils/log.h>
|
||||
#include <ui/InputDevice.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
/* Slop distance for jumpy pointer detection.
|
||||
* The vertical range of the screen divided by this is our epsilon value. */
|
||||
#define JUMPY_EPSILON_DIVISOR 212
|
||||
|
||||
/* Number of jumpy points to drop for touchscreens that need it. */
|
||||
#define JUMPY_TRANSITION_DROPS 3
|
||||
#define JUMPY_DROP_LIMIT 3
|
||||
|
||||
/* Maximum squared distance for averaging.
|
||||
* If moving farther than this, turn of averaging to avoid lag in response. */
|
||||
#define AVERAGING_DISTANCE_LIMIT (75 * 75)
|
||||
|
||||
|
||||
namespace android {
|
||||
|
||||
// --- Static Functions ---
|
||||
|
||||
template<typename T>
|
||||
inline static T abs(const T& value) {
|
||||
return value < 0 ? - value : value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline static T min(const T& a, const T& b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline static void swap(T& a, T& b) {
|
||||
T temp = a;
|
||||
a = b;
|
||||
b = temp;
|
||||
}
|
||||
|
||||
|
||||
// --- InputDevice ---
|
||||
|
||||
InputDevice::InputDevice(int32_t id, uint32_t classes, String8 name) :
|
||||
id(id), classes(classes), name(name), ignored(false) {
|
||||
}
|
||||
|
||||
void InputDevice::reset() {
|
||||
if (isKeyboard()) {
|
||||
keyboard.reset();
|
||||
}
|
||||
|
||||
if (isTrackball()) {
|
||||
trackball.reset();
|
||||
}
|
||||
|
||||
if (isMultiTouchScreen()) {
|
||||
multiTouchScreen.reset();
|
||||
} else if (isSingleTouchScreen()) {
|
||||
singleTouchScreen.reset();
|
||||
}
|
||||
|
||||
if (isTouchScreen()) {
|
||||
touchScreen.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --- InputDevice::TouchData ---
|
||||
|
||||
void InputDevice::TouchData::copyFrom(const TouchData& other) {
|
||||
pointerCount = other.pointerCount;
|
||||
idBits = other.idBits;
|
||||
|
||||
for (uint32_t i = 0; i < pointerCount; i++) {
|
||||
pointers[i] = other.pointers[i];
|
||||
idToIndex[i] = other.idToIndex[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --- InputDevice::KeyboardState ---
|
||||
|
||||
void InputDevice::KeyboardState::reset() {
|
||||
current.metaState = AMETA_NONE;
|
||||
current.downTime = 0;
|
||||
}
|
||||
|
||||
|
||||
// --- InputDevice::TrackballState ---
|
||||
|
||||
void InputDevice::TrackballState::reset() {
|
||||
accumulator.clear();
|
||||
current.down = false;
|
||||
current.downTime = 0;
|
||||
}
|
||||
|
||||
|
||||
// --- InputDevice::TouchScreenState ---
|
||||
|
||||
void InputDevice::TouchScreenState::reset() {
|
||||
lastTouch.clear();
|
||||
downTime = 0;
|
||||
currentVirtualKey.status = CurrentVirtualKeyState::STATUS_UP;
|
||||
|
||||
for (uint32_t i = 0; i < MAX_POINTERS; i++) {
|
||||
averagingTouchFilter.historyStart[i] = 0;
|
||||
averagingTouchFilter.historyEnd[i] = 0;
|
||||
}
|
||||
|
||||
jumpyTouchFilter.jumpyPointsDropped = 0;
|
||||
}
|
||||
|
||||
struct PointerDistanceHeapElement {
|
||||
uint32_t currentPointerIndex : 8;
|
||||
uint32_t lastPointerIndex : 8;
|
||||
uint64_t distance : 48; // squared distance
|
||||
};
|
||||
|
||||
void InputDevice::TouchScreenState::calculatePointerIds() {
|
||||
uint32_t currentPointerCount = currentTouch.pointerCount;
|
||||
uint32_t lastPointerCount = lastTouch.pointerCount;
|
||||
|
||||
if (currentPointerCount == 0) {
|
||||
// No pointers to assign.
|
||||
currentTouch.idBits.clear();
|
||||
} else if (lastPointerCount == 0) {
|
||||
// All pointers are new.
|
||||
currentTouch.idBits.clear();
|
||||
for (uint32_t i = 0; i < currentPointerCount; i++) {
|
||||
currentTouch.pointers[i].id = i;
|
||||
currentTouch.idToIndex[i] = i;
|
||||
currentTouch.idBits.markBit(i);
|
||||
}
|
||||
} else if (currentPointerCount == 1 && lastPointerCount == 1) {
|
||||
// Only one pointer and no change in count so it must have the same id as before.
|
||||
uint32_t id = lastTouch.pointers[0].id;
|
||||
currentTouch.pointers[0].id = id;
|
||||
currentTouch.idToIndex[id] = 0;
|
||||
currentTouch.idBits.value = BitSet32::valueForBit(id);
|
||||
} else {
|
||||
// General case.
|
||||
// We build a heap of squared euclidean distances between current and last pointers
|
||||
// associated with the current and last pointer indices. Then, we find the best
|
||||
// match (by distance) for each current pointer.
|
||||
PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
|
||||
|
||||
uint32_t heapSize = 0;
|
||||
for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
|
||||
currentPointerIndex++) {
|
||||
for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
|
||||
lastPointerIndex++) {
|
||||
int64_t deltaX = currentTouch.pointers[currentPointerIndex].x
|
||||
- lastTouch.pointers[lastPointerIndex].x;
|
||||
int64_t deltaY = currentTouch.pointers[currentPointerIndex].y
|
||||
- lastTouch.pointers[lastPointerIndex].y;
|
||||
|
||||
uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
|
||||
|
||||
// Insert new element into the heap (sift up).
|
||||
heap[heapSize].currentPointerIndex = currentPointerIndex;
|
||||
heap[heapSize].lastPointerIndex = lastPointerIndex;
|
||||
heap[heapSize].distance = distance;
|
||||
heapSize += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Heapify
|
||||
for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
|
||||
startIndex -= 1;
|
||||
for (uint32_t parentIndex = startIndex; ;) {
|
||||
uint32_t childIndex = parentIndex * 2 + 1;
|
||||
if (childIndex >= heapSize) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (childIndex + 1 < heapSize
|
||||
&& heap[childIndex + 1].distance < heap[childIndex].distance) {
|
||||
childIndex += 1;
|
||||
}
|
||||
|
||||
if (heap[parentIndex].distance <= heap[childIndex].distance) {
|
||||
break;
|
||||
}
|
||||
|
||||
swap(heap[parentIndex], heap[childIndex]);
|
||||
parentIndex = childIndex;
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG_POINTER_ASSIGNMENT
|
||||
LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
|
||||
for (size_t i = 0; i < heapSize; i++) {
|
||||
LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
|
||||
i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
|
||||
heap[i].distance);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Pull matches out by increasing order of distance.
|
||||
// To avoid reassigning pointers that have already been matched, the loop keeps track
|
||||
// of which last and current pointers have been matched using the matchedXXXBits variables.
|
||||
// It also tracks the used pointer id bits.
|
||||
BitSet32 matchedLastBits(0);
|
||||
BitSet32 matchedCurrentBits(0);
|
||||
BitSet32 usedIdBits(0);
|
||||
bool first = true;
|
||||
for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
|
||||
for (;;) {
|
||||
if (first) {
|
||||
// The first time through the loop, we just consume the root element of
|
||||
// the heap (the one with smallest distance).
|
||||
first = false;
|
||||
} else {
|
||||
// Previous iterations consumed the root element of the heap.
|
||||
// Pop root element off of the heap (sift down).
|
||||
heapSize -= 1;
|
||||
assert(heapSize > 0);
|
||||
|
||||
// Sift down.
|
||||
heap[0] = heap[heapSize];
|
||||
for (uint32_t parentIndex = 0; ;) {
|
||||
uint32_t childIndex = parentIndex * 2 + 1;
|
||||
if (childIndex >= heapSize) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (childIndex + 1 < heapSize
|
||||
&& heap[childIndex + 1].distance < heap[childIndex].distance) {
|
||||
childIndex += 1;
|
||||
}
|
||||
|
||||
if (heap[parentIndex].distance <= heap[childIndex].distance) {
|
||||
break;
|
||||
}
|
||||
|
||||
swap(heap[parentIndex], heap[childIndex]);
|
||||
parentIndex = childIndex;
|
||||
}
|
||||
|
||||
#if DEBUG_POINTER_ASSIGNMENT
|
||||
LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
|
||||
for (size_t i = 0; i < heapSize; i++) {
|
||||
LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
|
||||
i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
|
||||
heap[i].distance);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t currentPointerIndex = heap[0].currentPointerIndex;
|
||||
if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
|
||||
|
||||
uint32_t lastPointerIndex = heap[0].lastPointerIndex;
|
||||
if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
|
||||
|
||||
matchedCurrentBits.markBit(currentPointerIndex);
|
||||
matchedLastBits.markBit(lastPointerIndex);
|
||||
|
||||
uint32_t id = lastTouch.pointers[lastPointerIndex].id;
|
||||
currentTouch.pointers[currentPointerIndex].id = id;
|
||||
currentTouch.idToIndex[id] = currentPointerIndex;
|
||||
usedIdBits.markBit(id);
|
||||
|
||||
#if DEBUG_POINTER_ASSIGNMENT
|
||||
LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
|
||||
lastPointerIndex, currentPointerIndex, id, heap[0].distance);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Assign fresh ids to new pointers.
|
||||
if (currentPointerCount > lastPointerCount) {
|
||||
for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
|
||||
uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
|
||||
uint32_t id = usedIdBits.firstUnmarkedBit();
|
||||
|
||||
currentTouch.pointers[currentPointerIndex].id = id;
|
||||
currentTouch.idToIndex[id] = currentPointerIndex;
|
||||
usedIdBits.markBit(id);
|
||||
|
||||
#if DEBUG_POINTER_ASSIGNMENT
|
||||
LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
|
||||
currentPointerIndex, id);
|
||||
#endif
|
||||
|
||||
if (--i == 0) break; // done
|
||||
matchedCurrentBits.markBit(currentPointerIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Fix id bits.
|
||||
currentTouch.idBits = usedIdBits;
|
||||
}
|
||||
}
|
||||
|
||||
/* Special hack for devices that have bad screen data: if one of the
|
||||
* points has moved more than a screen height from the last position,
|
||||
* then drop it. */
|
||||
bool InputDevice::TouchScreenState::applyBadTouchFilter() {
|
||||
// This hack requires valid axis parameters.
|
||||
if (! parameters.yAxis.valid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t pointerCount = currentTouch.pointerCount;
|
||||
|
||||
// Nothing to do if there are no points.
|
||||
if (pointerCount == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't do anything if a finger is going down or up. We run
|
||||
// here before assigning pointer IDs, so there isn't a good
|
||||
// way to do per-finger matching.
|
||||
if (pointerCount != lastTouch.pointerCount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We consider a single movement across more than a 7/16 of
|
||||
// the long size of the screen to be bad. This was a magic value
|
||||
// determined by looking at the maximum distance it is feasible
|
||||
// to actually move in one sample.
|
||||
int32_t maxDeltaY = parameters.yAxis.range * 7 / 16;
|
||||
|
||||
// XXX The original code in InputDevice.java included commented out
|
||||
// code for testing the X axis. Note that when we drop a point
|
||||
// we don't actually restore the old X either. Strange.
|
||||
// The old code also tries to track when bad points were previously
|
||||
// detected but it turns out that due to the placement of a "break"
|
||||
// at the end of the loop, we never set mDroppedBadPoint to true
|
||||
// so it is effectively dead code.
|
||||
// Need to figure out if the old code is busted or just overcomplicated
|
||||
// but working as intended.
|
||||
|
||||
// Look through all new points and see if any are farther than
|
||||
// acceptable from all previous points.
|
||||
for (uint32_t i = pointerCount; i-- > 0; ) {
|
||||
int32_t y = currentTouch.pointers[i].y;
|
||||
int32_t closestY = INT_MAX;
|
||||
int32_t closestDeltaY = 0;
|
||||
|
||||
#if DEBUG_HACKS
|
||||
LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
|
||||
#endif
|
||||
|
||||
for (uint32_t j = pointerCount; j-- > 0; ) {
|
||||
int32_t lastY = lastTouch.pointers[j].y;
|
||||
int32_t deltaY = abs(y - lastY);
|
||||
|
||||
#if DEBUG_HACKS
|
||||
LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
|
||||
j, lastY, deltaY);
|
||||
#endif
|
||||
|
||||
if (deltaY < maxDeltaY) {
|
||||
goto SkipSufficientlyClosePoint;
|
||||
}
|
||||
if (deltaY < closestDeltaY) {
|
||||
closestDeltaY = deltaY;
|
||||
closestY = lastY;
|
||||
}
|
||||
}
|
||||
|
||||
// Must not have found a close enough match.
|
||||
#if DEBUG_HACKS
|
||||
LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
|
||||
i, y, closestY, closestDeltaY, maxDeltaY);
|
||||
#endif
|
||||
|
||||
currentTouch.pointers[i].y = closestY;
|
||||
return true; // XXX original code only corrects one point
|
||||
|
||||
SkipSufficientlyClosePoint: ;
|
||||
}
|
||||
|
||||
// No change.
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Special hack for devices that have bad screen data: drop points where
|
||||
* the coordinate value for one axis has jumped to the other pointer's location.
|
||||
*/
|
||||
bool InputDevice::TouchScreenState::applyJumpyTouchFilter() {
|
||||
// This hack requires valid axis parameters.
|
||||
if (! parameters.yAxis.valid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t pointerCount = currentTouch.pointerCount;
|
||||
if (lastTouch.pointerCount != pointerCount) {
|
||||
#if DEBUG_HACKS
|
||||
LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
|
||||
lastTouch.pointerCount, pointerCount);
|
||||
for (uint32_t i = 0; i < pointerCount; i++) {
|
||||
LOGD(" Pointer %d (%d, %d)", i,
|
||||
currentTouch.pointers[i].x, currentTouch.pointers[i].y);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (jumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
|
||||
if (lastTouch.pointerCount == 1 && pointerCount == 2) {
|
||||
// Just drop the first few events going from 1 to 2 pointers.
|
||||
// They're bad often enough that they're not worth considering.
|
||||
currentTouch.pointerCount = 1;
|
||||
jumpyTouchFilter.jumpyPointsDropped += 1;
|
||||
|
||||
#if DEBUG_HACKS
|
||||
LOGD("JumpyTouchFilter: Pointer 2 dropped");
|
||||
#endif
|
||||
return true;
|
||||
} else if (lastTouch.pointerCount == 2 && pointerCount == 1) {
|
||||
// The event when we go from 2 -> 1 tends to be messed up too
|
||||
currentTouch.pointerCount = 2;
|
||||
currentTouch.pointers[0] = lastTouch.pointers[0];
|
||||
currentTouch.pointers[1] = lastTouch.pointers[1];
|
||||
jumpyTouchFilter.jumpyPointsDropped += 1;
|
||||
|
||||
#if DEBUG_HACKS
|
||||
for (int32_t i = 0; i < 2; i++) {
|
||||
LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
|
||||
currentTouch.pointers[i].x, currentTouch.pointers[i].y);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Reset jumpy points dropped on other transitions or if limit exceeded.
|
||||
jumpyTouchFilter.jumpyPointsDropped = 0;
|
||||
|
||||
#if DEBUG_HACKS
|
||||
LOGD("JumpyTouchFilter: Transition - drop limit reset");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
// We have the same number of pointers as last time.
|
||||
// A 'jumpy' point is one where the coordinate value for one axis
|
||||
// has jumped to the other pointer's location. No need to do anything
|
||||
// else if we only have one pointer.
|
||||
if (pointerCount < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (jumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
|
||||
int jumpyEpsilon = parameters.yAxis.range / JUMPY_EPSILON_DIVISOR;
|
||||
|
||||
// We only replace the single worst jumpy point as characterized by pointer distance
|
||||
// in a single axis.
|
||||
int32_t badPointerIndex = -1;
|
||||
int32_t badPointerReplacementIndex = -1;
|
||||
int32_t badPointerDistance = INT_MIN; // distance to be corrected
|
||||
|
||||
for (uint32_t i = pointerCount; i-- > 0; ) {
|
||||
int32_t x = currentTouch.pointers[i].x;
|
||||
int32_t y = currentTouch.pointers[i].y;
|
||||
|
||||
#if DEBUG_HACKS
|
||||
LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
|
||||
#endif
|
||||
|
||||
// Check if a touch point is too close to another's coordinates
|
||||
bool dropX = false, dropY = false;
|
||||
for (uint32_t j = 0; j < pointerCount; j++) {
|
||||
if (i == j) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (abs(x - currentTouch.pointers[j].x) <= jumpyEpsilon) {
|
||||
dropX = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (abs(y - currentTouch.pointers[j].y) <= jumpyEpsilon) {
|
||||
dropY = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (! dropX && ! dropY) {
|
||||
continue; // not jumpy
|
||||
}
|
||||
|
||||
// Find a replacement candidate by comparing with older points on the
|
||||
// complementary (non-jumpy) axis.
|
||||
int32_t distance = INT_MIN; // distance to be corrected
|
||||
int32_t replacementIndex = -1;
|
||||
|
||||
if (dropX) {
|
||||
// X looks too close. Find an older replacement point with a close Y.
|
||||
int32_t smallestDeltaY = INT_MAX;
|
||||
for (uint32_t j = 0; j < pointerCount; j++) {
|
||||
int32_t deltaY = abs(y - lastTouch.pointers[j].y);
|
||||
if (deltaY < smallestDeltaY) {
|
||||
smallestDeltaY = deltaY;
|
||||
replacementIndex = j;
|
||||
}
|
||||
}
|
||||
distance = abs(x - lastTouch.pointers[replacementIndex].x);
|
||||
} else {
|
||||
// Y looks too close. Find an older replacement point with a close X.
|
||||
int32_t smallestDeltaX = INT_MAX;
|
||||
for (uint32_t j = 0; j < pointerCount; j++) {
|
||||
int32_t deltaX = abs(x - lastTouch.pointers[j].x);
|
||||
if (deltaX < smallestDeltaX) {
|
||||
smallestDeltaX = deltaX;
|
||||
replacementIndex = j;
|
||||
}
|
||||
}
|
||||
distance = abs(y - lastTouch.pointers[replacementIndex].y);
|
||||
}
|
||||
|
||||
// If replacing this pointer would correct a worse error than the previous ones
|
||||
// considered, then use this replacement instead.
|
||||
if (distance > badPointerDistance) {
|
||||
badPointerIndex = i;
|
||||
badPointerReplacementIndex = replacementIndex;
|
||||
badPointerDistance = distance;
|
||||
}
|
||||
}
|
||||
|
||||
// Correct the jumpy pointer if one was found.
|
||||
if (badPointerIndex >= 0) {
|
||||
#if DEBUG_HACKS
|
||||
LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
|
||||
badPointerIndex,
|
||||
lastTouch.pointers[badPointerReplacementIndex].x,
|
||||
lastTouch.pointers[badPointerReplacementIndex].y);
|
||||
#endif
|
||||
|
||||
currentTouch.pointers[badPointerIndex].x =
|
||||
lastTouch.pointers[badPointerReplacementIndex].x;
|
||||
currentTouch.pointers[badPointerIndex].y =
|
||||
lastTouch.pointers[badPointerReplacementIndex].y;
|
||||
jumpyTouchFilter.jumpyPointsDropped += 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
jumpyTouchFilter.jumpyPointsDropped = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Special hack for devices that have bad screen data: aggregate and
|
||||
* compute averages of the coordinate data, to reduce the amount of
|
||||
* jitter seen by applications. */
|
||||
void InputDevice::TouchScreenState::applyAveragingTouchFilter() {
|
||||
for (uint32_t currentIndex = 0; currentIndex < currentTouch.pointerCount; currentIndex++) {
|
||||
uint32_t id = currentTouch.pointers[currentIndex].id;
|
||||
int32_t x = currentTouch.pointers[currentIndex].x;
|
||||
int32_t y = currentTouch.pointers[currentIndex].y;
|
||||
int32_t pressure = currentTouch.pointers[currentIndex].pressure;
|
||||
|
||||
if (lastTouch.idBits.hasBit(id)) {
|
||||
// Pointer was down before and is still down now.
|
||||
// Compute average over history trace.
|
||||
uint32_t start = averagingTouchFilter.historyStart[id];
|
||||
uint32_t end = averagingTouchFilter.historyEnd[id];
|
||||
|
||||
int64_t deltaX = x - averagingTouchFilter.historyData[end].pointers[id].x;
|
||||
int64_t deltaY = y - averagingTouchFilter.historyData[end].pointers[id].y;
|
||||
uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
|
||||
|
||||
#if DEBUG_HACKS
|
||||
LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
|
||||
id, distance);
|
||||
#endif
|
||||
|
||||
if (distance < AVERAGING_DISTANCE_LIMIT) {
|
||||
// Increment end index in preparation for recording new historical data.
|
||||
end += 1;
|
||||
if (end > AVERAGING_HISTORY_SIZE) {
|
||||
end = 0;
|
||||
}
|
||||
|
||||
// If the end index has looped back to the start index then we have filled
|
||||
// the historical trace up to the desired size so we drop the historical
|
||||
// data at the start of the trace.
|
||||
if (end == start) {
|
||||
start += 1;
|
||||
if (start > AVERAGING_HISTORY_SIZE) {
|
||||
start = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the raw data to the historical trace.
|
||||
averagingTouchFilter.historyStart[id] = start;
|
||||
averagingTouchFilter.historyEnd[id] = end;
|
||||
averagingTouchFilter.historyData[end].pointers[id].x = x;
|
||||
averagingTouchFilter.historyData[end].pointers[id].y = y;
|
||||
averagingTouchFilter.historyData[end].pointers[id].pressure = pressure;
|
||||
|
||||
// Average over all historical positions in the trace by total pressure.
|
||||
int32_t averagedX = 0;
|
||||
int32_t averagedY = 0;
|
||||
int32_t totalPressure = 0;
|
||||
for (;;) {
|
||||
int32_t historicalX = averagingTouchFilter.historyData[start].pointers[id].x;
|
||||
int32_t historicalY = averagingTouchFilter.historyData[start].pointers[id].y;
|
||||
int32_t historicalPressure = averagingTouchFilter.historyData[start]
|
||||
.pointers[id].pressure;
|
||||
|
||||
averagedX += historicalX * historicalPressure;
|
||||
averagedY += historicalY * historicalPressure;
|
||||
totalPressure += historicalPressure;
|
||||
|
||||
if (start == end) {
|
||||
break;
|
||||
}
|
||||
|
||||
start += 1;
|
||||
if (start > AVERAGING_HISTORY_SIZE) {
|
||||
start = 0;
|
||||
}
|
||||
}
|
||||
|
||||
averagedX /= totalPressure;
|
||||
averagedY /= totalPressure;
|
||||
|
||||
#if DEBUG_HACKS
|
||||
LOGD("AveragingTouchFilter: Pointer id %d - "
|
||||
"totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
|
||||
averagedX, averagedY);
|
||||
#endif
|
||||
|
||||
currentTouch.pointers[currentIndex].x = averagedX;
|
||||
currentTouch.pointers[currentIndex].y = averagedY;
|
||||
} else {
|
||||
#if DEBUG_HACKS
|
||||
LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
#if DEBUG_HACKS
|
||||
LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Reset pointer history.
|
||||
averagingTouchFilter.historyStart[id] = 0;
|
||||
averagingTouchFilter.historyEnd[id] = 0;
|
||||
averagingTouchFilter.historyData[0].pointers[id].x = x;
|
||||
averagingTouchFilter.historyData[0].pointers[id].y = y;
|
||||
averagingTouchFilter.historyData[0].pointers[id].pressure = pressure;
|
||||
}
|
||||
}
|
||||
|
||||
bool InputDevice::TouchScreenState::isPointInsideDisplay(int32_t x, int32_t y) const {
|
||||
if (! parameters.xAxis.valid || ! parameters.yAxis.valid) {
|
||||
// Assume all points on a touch screen without valid axis parameters are
|
||||
// inside the display.
|
||||
return true;
|
||||
}
|
||||
|
||||
return x >= parameters.xAxis.minValue
|
||||
&& x <= parameters.xAxis.maxValue
|
||||
&& y >= parameters.yAxis.minValue
|
||||
&& y <= parameters.yAxis.maxValue;
|
||||
}
|
||||
|
||||
const InputDevice::VirtualKey* InputDevice::TouchScreenState::findVirtualKeyHit() const {
|
||||
int32_t x = currentTouch.pointers[0].x;
|
||||
int32_t y = currentTouch.pointers[0].y;
|
||||
for (size_t i = 0; i < virtualKeys.size(); i++) {
|
||||
const InputDevice::VirtualKey& virtualKey = virtualKeys[i];
|
||||
|
||||
#if DEBUG_VIRTUAL_KEYS
|
||||
LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
|
||||
"left=%d, top=%d, right=%d, bottom=%d",
|
||||
x, y,
|
||||
virtualKey.keyCode, virtualKey.scanCode,
|
||||
virtualKey.hitLeft, virtualKey.hitTop,
|
||||
virtualKey.hitRight, virtualKey.hitBottom);
|
||||
#endif
|
||||
|
||||
if (virtualKey.isHit(x, y)) {
|
||||
return & virtualKey;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// --- InputDevice::SingleTouchScreenState ---
|
||||
|
||||
void InputDevice::SingleTouchScreenState::reset() {
|
||||
accumulator.clear();
|
||||
current.down = false;
|
||||
current.x = 0;
|
||||
current.y = 0;
|
||||
current.pressure = 0;
|
||||
current.size = 0;
|
||||
}
|
||||
|
||||
|
||||
// --- InputDevice::MultiTouchScreenState ---
|
||||
|
||||
void InputDevice::MultiTouchScreenState::reset() {
|
||||
accumulator.clear();
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
@@ -89,26 +89,35 @@ void InputManager::preemptInputDispatch() {
|
||||
mDispatcher->preemptInputDispatch();
|
||||
}
|
||||
|
||||
void InputManager::getInputConfiguration(InputConfiguration* outConfiguration) const {
|
||||
mReader->getCurrentInputConfiguration(outConfiguration);
|
||||
void InputManager::getInputConfiguration(InputConfiguration* outConfiguration) {
|
||||
mReader->getInputConfiguration(outConfiguration);
|
||||
}
|
||||
|
||||
int32_t InputManager::getScanCodeState(int32_t deviceId, int32_t deviceClasses,
|
||||
int32_t scanCode) const {
|
||||
return mReader->getCurrentScanCodeState(deviceId, deviceClasses, scanCode);
|
||||
status_t InputManager::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
|
||||
return mReader->getInputDeviceInfo(deviceId, outDeviceInfo);
|
||||
}
|
||||
|
||||
int32_t InputManager::getKeyCodeState(int32_t deviceId, int32_t deviceClasses,
|
||||
int32_t keyCode) const {
|
||||
return mReader->getCurrentKeyCodeState(deviceId, deviceClasses, keyCode);
|
||||
void InputManager::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
|
||||
mReader->getInputDeviceIds(outDeviceIds);
|
||||
}
|
||||
|
||||
int32_t InputManager::getSwitchState(int32_t deviceId, int32_t deviceClasses, int32_t sw) const {
|
||||
return mReader->getCurrentSwitchState(deviceId, deviceClasses, sw);
|
||||
int32_t InputManager::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
|
||||
int32_t scanCode) {
|
||||
return mReader->getScanCodeState(deviceId, sourceMask, scanCode);
|
||||
}
|
||||
|
||||
bool InputManager::hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const {
|
||||
return mReader->hasKeys(numCodes, keyCodes, outFlags);
|
||||
int32_t InputManager::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
|
||||
int32_t keyCode) {
|
||||
return mReader->getKeyCodeState(deviceId, sourceMask, keyCode);
|
||||
}
|
||||
|
||||
int32_t InputManager::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t sw) {
|
||||
return mReader->getSwitchState(deviceId, sourceMask, sw);
|
||||
}
|
||||
|
||||
bool InputManager::hasKeys(int32_t deviceId, uint32_t sourceMask,
|
||||
size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
|
||||
return mReader->hasKeys(deviceId, sourceMask, numCodes, keyCodes, outFlags);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,14 +21,21 @@
|
||||
#include <ui/Input.h>
|
||||
#include <ui/InputTransport.h>
|
||||
#include <utils/PollLoop.h>
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/Vector.h>
|
||||
|
||||
#include <android_runtime/android_app_NativeActivity.h>
|
||||
|
||||
#include <poll.h>
|
||||
#include <errno.h>
|
||||
|
||||
using android::InputEvent;
|
||||
using android::KeyEvent;
|
||||
using android::MotionEvent;
|
||||
using android::InputDeviceInfo;
|
||||
using android::InputDeviceProxy;
|
||||
using android::sp;
|
||||
using android::Vector;
|
||||
|
||||
int32_t AInputEvent_getType(const AInputEvent* event) {
|
||||
return static_cast<const InputEvent*>(event)->getType();
|
||||
@@ -263,3 +270,74 @@ int32_t AInputQueue_preDispatchEvent(AInputQueue* queue, AInputEvent* event) {
|
||||
void AInputQueue_finishEvent(AInputQueue* queue, AInputEvent* event, int handled) {
|
||||
queue->finishEvent(event, handled != 0);
|
||||
}
|
||||
|
||||
|
||||
int32_t AInputDevice_getDeviceIds(int32_t* idBuf, size_t nMax, size_t* nActual) {
|
||||
Vector<int32_t> ids;
|
||||
InputDeviceProxy::getDeviceIds(ids);
|
||||
|
||||
if (nActual) {
|
||||
*nActual = ids.size();
|
||||
}
|
||||
|
||||
if (idBuf && ids.size() < nMax) {
|
||||
memcpy(idBuf, ids.array(), ids.size() * sizeof(int32_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
AInputDevice* AInputDevice_acquire(int32_t deviceId) {
|
||||
sp<InputDeviceProxy> proxy(InputDeviceProxy::getDevice(deviceId));
|
||||
if (proxy == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
proxy->incStrong((void*)AInputDevice_acquire);
|
||||
return static_cast<AInputDevice*>(proxy.get());
|
||||
}
|
||||
|
||||
void AInputDevice_release(AInputDevice* device) {
|
||||
if (device) {
|
||||
InputDeviceProxy* proxy = static_cast<InputDeviceProxy*>(device);
|
||||
proxy->decStrong((void*)AInputDevice_acquire);
|
||||
}
|
||||
}
|
||||
|
||||
const char* AInputDevice_getName(AInputDevice* device) {
|
||||
InputDeviceProxy* proxy = static_cast<InputDeviceProxy*>(device);
|
||||
return proxy->getInfo()->getName().string();
|
||||
}
|
||||
|
||||
uint32_t AInputDevice_getSources(AInputDevice* device) {
|
||||
InputDeviceProxy* proxy = static_cast<InputDeviceProxy*>(device);
|
||||
return proxy->getInfo()->getSources();
|
||||
}
|
||||
|
||||
int32_t AInputDevice_getKeyboardType(AInputDevice* device) {
|
||||
InputDeviceProxy* proxy = static_cast<InputDeviceProxy*>(device);
|
||||
return proxy->getInfo()->getKeyboardType();
|
||||
}
|
||||
|
||||
int32_t AInputDevice_getMotionRange(AInputDevice* device, int32_t rangeType,
|
||||
float* outMin, float* outMax, float* outFlat, float* outFuzz) {
|
||||
InputDeviceProxy* proxy = static_cast<InputDeviceProxy*>(device);
|
||||
const InputDeviceInfo::MotionRange* range = proxy->getInfo()->getMotionRange(rangeType);
|
||||
if (range) {
|
||||
if (outMin) {
|
||||
*outMin = range->min;
|
||||
}
|
||||
if (outMax) {
|
||||
*outMax = range->max;
|
||||
}
|
||||
if (outFlat) {
|
||||
*outFlat = range->flat;
|
||||
}
|
||||
if (outFuzz) {
|
||||
*outFuzz = range->fuzz;
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,7 +268,6 @@ enum {
|
||||
/*
|
||||
* Input sources.
|
||||
*
|
||||
* The appropriate interpretation for an input event depends on its source.
|
||||
* Refer to the documentation on android.view.InputDevice for more details about input sources
|
||||
* and their correct interpretation.
|
||||
*/
|
||||
@@ -296,6 +295,37 @@ enum {
|
||||
AINPUT_SOURCE_JOYSTICK_RIGHT = 0x02000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
|
||||
};
|
||||
|
||||
/*
|
||||
* Keyboard types.
|
||||
*
|
||||
* Refer to the documentation on android.view.InputDevice for more details.
|
||||
*/
|
||||
enum {
|
||||
AINPUT_KEYBOARD_TYPE_NONE = 0,
|
||||
AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC = 1,
|
||||
AINPUT_KEYBOARD_TYPE_ALPHABETIC = 2,
|
||||
};
|
||||
|
||||
/*
|
||||
* Constants used to retrieve information about the range of motion for a particular
|
||||
* coordinate of a motion event.
|
||||
*
|
||||
* Refer to the documentation on android.view.InputDevice for more details about input sources
|
||||
* and their correct interpretation.
|
||||
*/
|
||||
enum {
|
||||
AINPUT_MOTION_RANGE_X = 0,
|
||||
AINPUT_MOTION_RANGE_Y = 1,
|
||||
AINPUT_MOTION_RANGE_PRESSURE = 2,
|
||||
AINPUT_MOTION_RANGE_SIZE = 3,
|
||||
AINPUT_MOTION_RANGE_TOUCH_MAJOR = 4,
|
||||
AINPUT_MOTION_RANGE_TOUCH_MINOR = 5,
|
||||
AINPUT_MOTION_RANGE_TOOL_MAJOR = 6,
|
||||
AINPUT_MOTION_RANGE_TOOL_MINOR = 7,
|
||||
AINPUT_MOTION_RANGE_ORIENTATION = 8,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Input event accessors.
|
||||
*
|
||||
@@ -475,7 +505,7 @@ float AMotionEvent_getToolMinor(const AInputEvent* motion_event, size_t pointer_
|
||||
* upwards, is perfectly circular or is of unknown orientation. A positive angle
|
||||
* indicates that the major axis of contact is oriented to the right. A negative angle
|
||||
* indicates that the major axis of contact is oriented to the left.
|
||||
* The full range is from -PI/4 radians (finger pointing fully left) to PI/4 radians
|
||||
* The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians
|
||||
* (finger pointing fully right). */
|
||||
float AMotionEvent_getOrientation(const AInputEvent* motion_event, size_t pointer_index);
|
||||
|
||||
@@ -575,7 +605,7 @@ float AMotionEvent_getHistoricalToolMinor(const AInputEvent* motion_event, size_
|
||||
* upwards, is perfectly circular or is of unknown orientation. A positive angle
|
||||
* indicates that the major axis of contact is oriented to the right. A negative angle
|
||||
* indicates that the major axis of contact is oriented to the left.
|
||||
* The full range is from -PI/4 radians (finger pointing fully left) to PI/4 radians
|
||||
* The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians
|
||||
* (finger pointing fully right). */
|
||||
float AMotionEvent_getHistoricalOrientation(const AInputEvent* motion_event, size_t pointer_index,
|
||||
size_t history_index);
|
||||
@@ -631,6 +661,64 @@ int32_t AInputQueue_preDispatchEvent(AInputQueue* queue, AInputEvent* event);
|
||||
*/
|
||||
void AInputQueue_finishEvent(AInputQueue* queue, AInputEvent* event, int handled);
|
||||
|
||||
/*
|
||||
* Input devices.
|
||||
*
|
||||
* These functions provide a mechanism for querying the set of available input devices
|
||||
* and their characteristics and capabilities.
|
||||
*/
|
||||
struct AInputDevice;
|
||||
typedef struct AInputDevice AInputDevice;
|
||||
|
||||
/*
|
||||
* Populates the supplied array with the ids of all input devices in the system.
|
||||
* Sets nActual to the actual number of devices.
|
||||
* Returns zero if enumeration was successful.
|
||||
* Returns non-zero if the actual number of devices is greater than nMax, in which case the
|
||||
* client should call the method again with a larger id buffer.
|
||||
*/
|
||||
int32_t AInputDevice_getDeviceIds(int32_t* idBuf, size_t nMax, size_t* nActual);
|
||||
|
||||
/*
|
||||
* Acquires a device by id.
|
||||
* Returns NULL if the device was not found.
|
||||
*
|
||||
* Note: The returned object must be freed using AInputDevice_release when no longer needed.
|
||||
*/
|
||||
AInputDevice* AInputDevice_acquire(int32_t deviceId);
|
||||
|
||||
/*
|
||||
* Releases a device previously acquired by AInputDevice_acquire.
|
||||
* If device is NULL, this function does nothing.
|
||||
*/
|
||||
void AInputDevice_release(AInputDevice* device);
|
||||
|
||||
/*
|
||||
* Gets the name of an input device.
|
||||
*
|
||||
* Note: The caller should copy the name into a private buffer since the returned pointer
|
||||
* will become invalid when the device object is released.
|
||||
*/
|
||||
const char* AInputDevice_getName(AInputDevice* device);
|
||||
|
||||
/*
|
||||
* Gets the combination of input sources provided by the input device.
|
||||
*/
|
||||
uint32_t AInputDevice_getSources(AInputDevice* device);
|
||||
|
||||
/*
|
||||
* Gets the keyboard type.
|
||||
*/
|
||||
int32_t AInputDevice_getKeyboardType(AInputDevice* device);
|
||||
|
||||
/* Gets the minimum value, maximum value, flat position and error tolerance for a
|
||||
* particular motion coodinate.
|
||||
* Returns zero if the device supports the specified motion range. */
|
||||
int32_t AInputDevice_getMotionRange(AInputDevice* device, int32_t rangeType,
|
||||
float* outMin, float* outMax, float* outFlat, float* outFuzz);
|
||||
|
||||
//TODO hasKey, keymap stuff, etc...
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -66,13 +66,14 @@ public class InputManager {
|
||||
private static native void nativeSetDisplaySize(int displayId, int width, int height);
|
||||
private static native void nativeSetDisplayOrientation(int displayId, int rotation);
|
||||
|
||||
private static native int nativeGetScanCodeState(int deviceId, int deviceClasses,
|
||||
private static native int nativeGetScanCodeState(int deviceId, int sourceMask,
|
||||
int scanCode);
|
||||
private static native int nativeGetKeyCodeState(int deviceId, int deviceClasses,
|
||||
private static native int nativeGetKeyCodeState(int deviceId, int sourceMask,
|
||||
int keyCode);
|
||||
private static native int nativeGetSwitchState(int deviceId, int deviceClasses,
|
||||
private static native int nativeGetSwitchState(int deviceId, int sourceMask,
|
||||
int sw);
|
||||
private static native boolean nativeHasKeys(int[] keyCodes, boolean[] keyExists);
|
||||
private static native boolean nativeHasKeys(int deviceId, int sourceMask,
|
||||
int[] keyCodes, boolean[] keyExists);
|
||||
private static native void nativeRegisterInputChannel(InputChannel inputChannel);
|
||||
private static native void nativeUnregisterInputChannel(InputChannel inputChannel);
|
||||
private static native int nativeInjectKeyEvent(KeyEvent event,
|
||||
@@ -85,20 +86,28 @@ public class InputManager {
|
||||
private static native void nativePreemptInputDispatch();
|
||||
private static native String nativeDump();
|
||||
|
||||
// Device class as defined by EventHub.
|
||||
private static final int CLASS_KEYBOARD = 0x00000001;
|
||||
private static final int CLASS_ALPHAKEY = 0x00000002;
|
||||
private static final int CLASS_TOUCHSCREEN = 0x00000004;
|
||||
private static final int CLASS_TRACKBALL = 0x00000008;
|
||||
private static final int CLASS_TOUCHSCREEN_MT = 0x00000010;
|
||||
private static final int CLASS_DPAD = 0x00000020;
|
||||
|
||||
// Input event injection constants defined in InputDispatcher.h.
|
||||
static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
|
||||
static final int INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1;
|
||||
static final int INPUT_EVENT_INJECTION_FAILED = 2;
|
||||
static final int INPUT_EVENT_INJECTION_TIMED_OUT = 3;
|
||||
|
||||
// Key states (may be returned by queries about the current state of a
|
||||
// particular key code, scan code or switch).
|
||||
|
||||
/** The key state is unknown or the requested key itself is not supported. */
|
||||
public static final int KEY_STATE_UNKNOWN = -1;
|
||||
|
||||
/** The key is up. /*/
|
||||
public static final int KEY_STATE_UP = 0;
|
||||
|
||||
/** The key is down. */
|
||||
public static final int KEY_STATE_DOWN = 1;
|
||||
|
||||
/** The key is down but is a virtual key press that is being emulated by the system. */
|
||||
public static final int KEY_STATE_VIRTUAL = 2;
|
||||
|
||||
|
||||
public InputManager(Context context, WindowManagerService windowManagerService) {
|
||||
this.mContext = context;
|
||||
this.mWindowManagerService = windowManagerService;
|
||||
@@ -150,55 +159,67 @@ public class InputManager {
|
||||
config.navigation = mNavigationConfig;
|
||||
}
|
||||
|
||||
public int getScancodeState(int code) {
|
||||
return nativeGetScanCodeState(0, -1, code);
|
||||
/**
|
||||
* Gets the current state of a key or button by key code.
|
||||
* @param deviceId The input device id, or -1 to consult all devices.
|
||||
* @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
|
||||
* consider all input sources. An input device is consulted if at least one of its
|
||||
* non-class input source bits matches the specified source mask.
|
||||
* @param keyCode The key code to check.
|
||||
* @return The key state.
|
||||
*/
|
||||
public int getKeyCodeState(int deviceId, int sourceMask, int keyCode) {
|
||||
return nativeGetKeyCodeState(deviceId, sourceMask, keyCode);
|
||||
}
|
||||
|
||||
public int getScancodeState(int deviceId, int code) {
|
||||
return nativeGetScanCodeState(deviceId, -1, code);
|
||||
/**
|
||||
* Gets the current state of a key or button by scan code.
|
||||
* @param deviceId The input device id, or -1 to consult all devices.
|
||||
* @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
|
||||
* consider all input sources. An input device is consulted if at least one of its
|
||||
* non-class input source bits matches the specified source mask.
|
||||
* @param scanCode The scan code to check.
|
||||
* @return The key state.
|
||||
*/
|
||||
public int getScanCodeState(int deviceId, int sourceMask, int scanCode) {
|
||||
return nativeGetScanCodeState(deviceId, sourceMask, scanCode);
|
||||
}
|
||||
|
||||
public int getTrackballScancodeState(int code) {
|
||||
return nativeGetScanCodeState(-1, CLASS_TRACKBALL, code);
|
||||
}
|
||||
|
||||
public int getDPadScancodeState(int code) {
|
||||
return nativeGetScanCodeState(-1, CLASS_DPAD, code);
|
||||
}
|
||||
|
||||
public int getKeycodeState(int code) {
|
||||
return nativeGetKeyCodeState(0, -1, code);
|
||||
}
|
||||
|
||||
public int getKeycodeState(int deviceId, int code) {
|
||||
return nativeGetKeyCodeState(deviceId, -1, code);
|
||||
}
|
||||
|
||||
public int getTrackballKeycodeState(int code) {
|
||||
return nativeGetKeyCodeState(-1, CLASS_TRACKBALL, code);
|
||||
}
|
||||
|
||||
public int getDPadKeycodeState(int code) {
|
||||
return nativeGetKeyCodeState(-1, CLASS_DPAD, code);
|
||||
/**
|
||||
* Gets the current state of a switch by switch code.
|
||||
* @param deviceId The input device id, or -1 to consult all devices.
|
||||
* @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
|
||||
* consider all input sources. An input device is consulted if at least one of its
|
||||
* non-class input source bits matches the specified source mask.
|
||||
* @param switchCode The switch code to check.
|
||||
* @return The switch state.
|
||||
*/
|
||||
public int getSwitchState(int deviceId, int sourceMask, int switchCode) {
|
||||
return nativeGetSwitchState(deviceId, sourceMask, switchCode);
|
||||
}
|
||||
|
||||
public int getSwitchState(int sw) {
|
||||
return nativeGetSwitchState(-1, -1, sw);
|
||||
}
|
||||
|
||||
public int getSwitchState(int deviceId, int sw) {
|
||||
return nativeGetSwitchState(deviceId, -1, sw);
|
||||
}
|
||||
|
||||
public boolean hasKeys(int[] keyCodes, boolean[] keyExists) {
|
||||
/**
|
||||
* Determines whether the specified key codes are supported by a particular device.
|
||||
* @param deviceId The input device id, or -1 to consult all devices.
|
||||
* @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
|
||||
* consider all input sources. An input device is consulted if at least one of its
|
||||
* non-class input source bits matches the specified source mask.
|
||||
* @param keyCodes The array of key codes to check.
|
||||
* @param keyExists An array at least as large as keyCodes whose entries will be set
|
||||
* to true or false based on the presence or absence of support for the corresponding
|
||||
* key codes.
|
||||
* @return True if the lookup was successful, false otherwise.
|
||||
*/
|
||||
public boolean hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists) {
|
||||
if (keyCodes == null) {
|
||||
throw new IllegalArgumentException("keyCodes must not be null.");
|
||||
}
|
||||
if (keyExists == null) {
|
||||
throw new IllegalArgumentException("keyExists must not be null.");
|
||||
if (keyExists == null || keyExists.length < keyCodes.length) {
|
||||
throw new IllegalArgumentException("keyExists must not be null and must be at "
|
||||
+ "least as large as keyCodes.");
|
||||
}
|
||||
|
||||
return nativeHasKeys(keyCodes, keyExists);
|
||||
return nativeHasKeys(deviceId, sourceMask, keyCodes, keyExists);
|
||||
}
|
||||
|
||||
public void registerInputChannel(InputChannel inputChannel) {
|
||||
|
||||
@@ -4307,7 +4307,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
"getSwitchState()")) {
|
||||
throw new SecurityException("Requires READ_INPUT_STATE permission");
|
||||
}
|
||||
return mInputManager.getSwitchState(sw);
|
||||
return mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, sw);
|
||||
}
|
||||
|
||||
public int getSwitchStateForDevice(int devid, int sw) {
|
||||
@@ -4315,7 +4315,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
"getSwitchStateForDevice()")) {
|
||||
throw new SecurityException("Requires READ_INPUT_STATE permission");
|
||||
}
|
||||
return mInputManager.getSwitchState(devid, sw);
|
||||
return mInputManager.getSwitchState(devid, InputDevice.SOURCE_ANY, sw);
|
||||
}
|
||||
|
||||
public int getScancodeState(int sw) {
|
||||
@@ -4323,7 +4323,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
"getScancodeState()")) {
|
||||
throw new SecurityException("Requires READ_INPUT_STATE permission");
|
||||
}
|
||||
return mInputManager.getScancodeState(sw);
|
||||
return mInputManager.getScanCodeState(-1, InputDevice.SOURCE_ANY, sw);
|
||||
}
|
||||
|
||||
public int getScancodeStateForDevice(int devid, int sw) {
|
||||
@@ -4331,7 +4331,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
"getScancodeStateForDevice()")) {
|
||||
throw new SecurityException("Requires READ_INPUT_STATE permission");
|
||||
}
|
||||
return mInputManager.getScancodeState(devid, sw);
|
||||
return mInputManager.getScanCodeState(devid, InputDevice.SOURCE_ANY, sw);
|
||||
}
|
||||
|
||||
public int getTrackballScancodeState(int sw) {
|
||||
@@ -4339,7 +4339,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
"getTrackballScancodeState()")) {
|
||||
throw new SecurityException("Requires READ_INPUT_STATE permission");
|
||||
}
|
||||
return mInputManager.getTrackballScancodeState(sw);
|
||||
return mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, sw);
|
||||
}
|
||||
|
||||
public int getDPadScancodeState(int sw) {
|
||||
@@ -4347,7 +4347,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
"getDPadScancodeState()")) {
|
||||
throw new SecurityException("Requires READ_INPUT_STATE permission");
|
||||
}
|
||||
return mInputManager.getDPadScancodeState(sw);
|
||||
return mInputManager.getScanCodeState(-1, InputDevice.SOURCE_DPAD, sw);
|
||||
}
|
||||
|
||||
public int getKeycodeState(int sw) {
|
||||
@@ -4355,7 +4355,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
"getKeycodeState()")) {
|
||||
throw new SecurityException("Requires READ_INPUT_STATE permission");
|
||||
}
|
||||
return mInputManager.getKeycodeState(sw);
|
||||
return mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, sw);
|
||||
}
|
||||
|
||||
public int getKeycodeStateForDevice(int devid, int sw) {
|
||||
@@ -4363,7 +4363,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
"getKeycodeStateForDevice()")) {
|
||||
throw new SecurityException("Requires READ_INPUT_STATE permission");
|
||||
}
|
||||
return mInputManager.getKeycodeState(devid, sw);
|
||||
return mInputManager.getKeyCodeState(devid, InputDevice.SOURCE_ANY, sw);
|
||||
}
|
||||
|
||||
public int getTrackballKeycodeState(int sw) {
|
||||
@@ -4371,7 +4371,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
"getTrackballKeycodeState()")) {
|
||||
throw new SecurityException("Requires READ_INPUT_STATE permission");
|
||||
}
|
||||
return mInputManager.getTrackballKeycodeState(sw);
|
||||
return mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_TRACKBALL, sw);
|
||||
}
|
||||
|
||||
public int getDPadKeycodeState(int sw) {
|
||||
@@ -4379,11 +4379,11 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
"getDPadKeycodeState()")) {
|
||||
throw new SecurityException("Requires READ_INPUT_STATE permission");
|
||||
}
|
||||
return mInputManager.getDPadKeycodeState(sw);
|
||||
return mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, sw);
|
||||
}
|
||||
|
||||
public boolean hasKeys(int[] keycodes, boolean[] keyExists) {
|
||||
return mInputManager.hasKeys(keycodes, keyExists);
|
||||
return mInputManager.hasKeys(-1, InputDevice.SOURCE_ANY, keycodes, keyExists);
|
||||
}
|
||||
|
||||
public void enableScreenAfterBoot() {
|
||||
|
||||
@@ -219,11 +219,10 @@ public:
|
||||
int32_t* width, int32_t* height, int32_t* orientation);
|
||||
virtual void virtualKeyDownFeedback();
|
||||
virtual int32_t interceptKey(nsecs_t when, int32_t deviceId,
|
||||
bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags);
|
||||
virtual int32_t interceptTrackball(nsecs_t when, bool buttonChanged, bool buttonDown,
|
||||
bool rolled);
|
||||
virtual int32_t interceptTouch(nsecs_t when);
|
||||
virtual int32_t interceptSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue);
|
||||
bool down, int32_t keyCode, int32_t scanCode, uint32_t& policyFlags);
|
||||
virtual int32_t interceptSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
|
||||
uint32_t& policyFlags);
|
||||
virtual int32_t interceptGeneric(nsecs_t when, uint32_t& policyFlags);
|
||||
virtual bool filterTouchEvents();
|
||||
virtual bool filterJumpyTouchEvents();
|
||||
virtual void getVirtualKeyDefinitions(const String8& deviceName,
|
||||
@@ -343,6 +342,7 @@ private:
|
||||
InputApplication* mFocusedApplication;
|
||||
InputApplication mFocusedApplicationStorage; // preallocated storage for mFocusedApplication
|
||||
|
||||
void dumpDeviceInfo(String8& dump);
|
||||
void dumpDispatchStateLd(String8& dump);
|
||||
void logDispatchStateLd();
|
||||
|
||||
@@ -409,12 +409,16 @@ NativeInputManager::~NativeInputManager() {
|
||||
|
||||
String8 NativeInputManager::dump() {
|
||||
String8 dump;
|
||||
dump.append("Native Input Dispatcher State:\n");
|
||||
|
||||
{ // acquire lock
|
||||
AutoMutex _l(mDisplayLock);
|
||||
dump.append("Native Input Dispatcher State:\n");
|
||||
dumpDispatchStateLd(dump);
|
||||
dump.append("\n");
|
||||
} // release lock
|
||||
|
||||
dump.append("Input Devices:\n");
|
||||
dumpDeviceInfo(dump);
|
||||
|
||||
return dump;
|
||||
}
|
||||
|
||||
@@ -566,9 +570,15 @@ bool NativeInputManager::getDisplayInfo(int32_t displayId,
|
||||
AutoMutex _l(mDisplayLock);
|
||||
|
||||
if (mDisplayWidth > 0) {
|
||||
*width = mDisplayWidth;
|
||||
*height = mDisplayHeight;
|
||||
*orientation = mDisplayOrientation;
|
||||
if (width) {
|
||||
*width = mDisplayWidth;
|
||||
}
|
||||
if (height) {
|
||||
*height = mDisplayHeight;
|
||||
}
|
||||
if (orientation) {
|
||||
*orientation = mDisplayOrientation;
|
||||
}
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
@@ -595,7 +605,7 @@ void NativeInputManager::virtualKeyDownFeedback() {
|
||||
}
|
||||
|
||||
int32_t NativeInputManager::interceptKey(nsecs_t when,
|
||||
int32_t deviceId, bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) {
|
||||
int32_t deviceId, bool down, int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) {
|
||||
#if DEBUG_INPUT_READER_POLICY
|
||||
LOGD("interceptKey - when=%lld, deviceId=%d, down=%d, keyCode=%d, scanCode=%d, "
|
||||
"policyFlags=0x%x",
|
||||
@@ -626,12 +636,12 @@ int32_t NativeInputManager::interceptKey(nsecs_t when,
|
||||
int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
|
||||
if (! isScreenOn) {
|
||||
// Key presses and releases wake the device.
|
||||
actions |= InputReaderPolicyInterface::ACTION_WOKE_HERE;
|
||||
policyFlags |= POLICY_FLAG_WOKE_HERE;
|
||||
}
|
||||
|
||||
if (! isScreenBright) {
|
||||
// Key presses and releases brighten the screen if dimmed.
|
||||
actions |= InputReaderPolicyInterface::ACTION_BRIGHT_HERE;
|
||||
policyFlags |= POLICY_FLAG_BRIGHT_HERE;
|
||||
}
|
||||
|
||||
if (wmActions & WM_ACTION_GO_TO_SLEEP) {
|
||||
@@ -658,42 +668,20 @@ int32_t NativeInputManager::interceptKey(nsecs_t when,
|
||||
return actions;
|
||||
}
|
||||
|
||||
int32_t NativeInputManager::interceptTouch(nsecs_t when) {
|
||||
int32_t NativeInputManager::interceptGeneric(nsecs_t when, uint32_t& policyFlags) {
|
||||
#if DEBUG_INPUT_READER_POLICY
|
||||
LOGD("interceptTouch - when=%lld", when);
|
||||
LOGD("interceptGeneric - when=%lld, policyFlags=0x%x", when, policyFlags);
|
||||
#endif
|
||||
|
||||
int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
|
||||
if (isScreenOn()) {
|
||||
// Only dispatch touch events when the device is awake.
|
||||
// Only dispatch events when the device is awake.
|
||||
// Do not wake the device.
|
||||
actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
|
||||
|
||||
if (! isScreenBright()) {
|
||||
// Brighten the screen if dimmed.
|
||||
actions |= InputReaderPolicyInterface::ACTION_BRIGHT_HERE;
|
||||
}
|
||||
}
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
int32_t NativeInputManager::interceptTrackball(nsecs_t when,
|
||||
bool buttonChanged, bool buttonDown, bool rolled) {
|
||||
#if DEBUG_INPUT_READER_POLICY
|
||||
LOGD("interceptTrackball - when=%lld, buttonChanged=%d, buttonDown=%d, rolled=%d",
|
||||
when, buttonChanged, buttonDown, rolled);
|
||||
#endif
|
||||
|
||||
int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
|
||||
if (isScreenOn()) {
|
||||
// Only dispatch trackball events when the device is awake.
|
||||
// Do not wake the device.
|
||||
actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
|
||||
|
||||
if (! isScreenBright()) {
|
||||
// Brighten the screen if dimmed.
|
||||
actions |= InputReaderPolicyInterface::ACTION_BRIGHT_HERE;
|
||||
policyFlags |= POLICY_FLAG_BRIGHT_HERE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -701,10 +689,10 @@ int32_t NativeInputManager::interceptTrackball(nsecs_t when,
|
||||
}
|
||||
|
||||
int32_t NativeInputManager::interceptSwitch(nsecs_t when, int32_t switchCode,
|
||||
int32_t switchValue) {
|
||||
int32_t switchValue, uint32_t& policyFlags) {
|
||||
#if DEBUG_INPUT_READER_POLICY
|
||||
LOGD("interceptSwitch - when=%lld, switchCode=%d, switchValue=%d",
|
||||
when, switchCode, switchValue);
|
||||
LOGD("interceptSwitch - when=%lld, switchCode=%d, switchValue=%d, policyFlags=0x%x",
|
||||
when, switchCode, switchValue, policyFlags);
|
||||
#endif
|
||||
|
||||
JNIEnv* env = jniEnv();
|
||||
@@ -1718,6 +1706,56 @@ void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType)
|
||||
android_server_PowerManagerService_userActivity(eventTime, eventType);
|
||||
}
|
||||
|
||||
static void dumpMotionRange(String8& dump,
|
||||
const char* name, const InputDeviceInfo::MotionRange* range) {
|
||||
if (range) {
|
||||
dump.appendFormat(" %s = { min: %0.3f, max: %0.3f, flat: %0.3f, fuzz: %0.3f }\n",
|
||||
name, range->min, range->max, range->flat, range->fuzz);
|
||||
}
|
||||
}
|
||||
|
||||
#define DUMP_MOTION_RANGE(range) \
|
||||
dumpMotionRange(dump, #range, deviceInfo.getMotionRange(AINPUT_MOTION_RANGE_##range));
|
||||
|
||||
void NativeInputManager::dumpDeviceInfo(String8& dump) {
|
||||
Vector<int32_t> deviceIds;
|
||||
mInputManager->getInputDeviceIds(deviceIds);
|
||||
|
||||
InputDeviceInfo deviceInfo;
|
||||
for (size_t i = 0; i < deviceIds.size(); i++) {
|
||||
int32_t deviceId = deviceIds[i];
|
||||
|
||||
status_t result = mInputManager->getInputDeviceInfo(deviceId, & deviceInfo);
|
||||
if (result == NAME_NOT_FOUND) {
|
||||
continue;
|
||||
} else if (result != OK) {
|
||||
dump.appendFormat(" ** Unexpected error %d getting information about input devices.\n",
|
||||
result);
|
||||
continue;
|
||||
}
|
||||
|
||||
dump.appendFormat(" Device %d: '%s'\n",
|
||||
deviceInfo.getId(), deviceInfo.getName().string());
|
||||
dump.appendFormat(" sources = 0x%08x\n",
|
||||
deviceInfo.getSources());
|
||||
dump.appendFormat(" keyboardType = %d\n",
|
||||
deviceInfo.getKeyboardType());
|
||||
|
||||
dump.append(" motion ranges:\n");
|
||||
DUMP_MOTION_RANGE(X);
|
||||
DUMP_MOTION_RANGE(Y);
|
||||
DUMP_MOTION_RANGE(PRESSURE);
|
||||
DUMP_MOTION_RANGE(SIZE);
|
||||
DUMP_MOTION_RANGE(TOUCH_MAJOR);
|
||||
DUMP_MOTION_RANGE(TOUCH_MINOR);
|
||||
DUMP_MOTION_RANGE(TOOL_MAJOR);
|
||||
DUMP_MOTION_RANGE(TOOL_MINOR);
|
||||
DUMP_MOTION_RANGE(ORIENTATION);
|
||||
}
|
||||
}
|
||||
|
||||
#undef DUMP_MOTION_RANGE
|
||||
|
||||
void NativeInputManager::logDispatchStateLd() {
|
||||
String8 dump;
|
||||
dumpDispatchStateLd(dump);
|
||||
@@ -1899,36 +1937,37 @@ static void android_server_InputManager_nativeSetDisplayOrientation(JNIEnv* env,
|
||||
}
|
||||
|
||||
static jint android_server_InputManager_nativeGetScanCodeState(JNIEnv* env, jclass clazz,
|
||||
jint deviceId, jint deviceClasses, jint scanCode) {
|
||||
jint deviceId, jint sourceMask, jint scanCode) {
|
||||
if (checkInputManagerUnitialized(env)) {
|
||||
return AKEY_STATE_UNKNOWN;
|
||||
}
|
||||
|
||||
return gNativeInputManager->getInputManager()->getScanCodeState(
|
||||
deviceId, deviceClasses, scanCode);
|
||||
deviceId, uint32_t(sourceMask), scanCode);
|
||||
}
|
||||
|
||||
static jint android_server_InputManager_nativeGetKeyCodeState(JNIEnv* env, jclass clazz,
|
||||
jint deviceId, jint deviceClasses, jint keyCode) {
|
||||
jint deviceId, jint sourceMask, jint keyCode) {
|
||||
if (checkInputManagerUnitialized(env)) {
|
||||
return AKEY_STATE_UNKNOWN;
|
||||
}
|
||||
|
||||
return gNativeInputManager->getInputManager()->getKeyCodeState(
|
||||
deviceId, deviceClasses, keyCode);
|
||||
deviceId, uint32_t(sourceMask), keyCode);
|
||||
}
|
||||
|
||||
static jint android_server_InputManager_nativeGetSwitchState(JNIEnv* env, jclass clazz,
|
||||
jint deviceId, jint deviceClasses, jint sw) {
|
||||
jint deviceId, jint sourceMask, jint sw) {
|
||||
if (checkInputManagerUnitialized(env)) {
|
||||
return AKEY_STATE_UNKNOWN;
|
||||
}
|
||||
|
||||
return gNativeInputManager->getInputManager()->getSwitchState(deviceId, deviceClasses, sw);
|
||||
return gNativeInputManager->getInputManager()->getSwitchState(
|
||||
deviceId, uint32_t(sourceMask), sw);
|
||||
}
|
||||
|
||||
static jboolean android_server_InputManager_nativeHasKeys(JNIEnv* env, jclass clazz,
|
||||
jintArray keyCodes, jbooleanArray outFlags) {
|
||||
jint deviceId, jint sourceMask, jintArray keyCodes, jbooleanArray outFlags) {
|
||||
if (checkInputManagerUnitialized(env)) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
@@ -1937,8 +1976,9 @@ static jboolean android_server_InputManager_nativeHasKeys(JNIEnv* env, jclass cl
|
||||
uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL);
|
||||
jsize numCodes = env->GetArrayLength(keyCodes);
|
||||
jboolean result;
|
||||
if (numCodes == env->GetArrayLength(outFlags)) {
|
||||
result = gNativeInputManager->getInputManager()->hasKeys(numCodes, codes, flags);
|
||||
if (numCodes == env->GetArrayLength(keyCodes)) {
|
||||
result = gNativeInputManager->getInputManager()->hasKeys(
|
||||
deviceId, uint32_t(sourceMask), numCodes, codes, flags);
|
||||
} else {
|
||||
result = JNI_FALSE;
|
||||
}
|
||||
@@ -2102,7 +2142,7 @@ static JNINativeMethod gInputManagerMethods[] = {
|
||||
(void*) android_server_InputManager_nativeGetKeyCodeState },
|
||||
{ "nativeGetSwitchState", "(III)I",
|
||||
(void*) android_server_InputManager_nativeGetSwitchState },
|
||||
{ "nativeHasKeys", "([I[Z)Z",
|
||||
{ "nativeHasKeys", "(II[I[Z)Z",
|
||||
(void*) android_server_InputManager_nativeHasKeys },
|
||||
{ "nativeRegisterInputChannel", "(Landroid/view/InputChannel;)V",
|
||||
(void*) android_server_InputManager_nativeRegisterInputChannel },
|
||||
|
||||
Reference in New Issue
Block a user