Mouse pointer integration.

Added support for loading the pointer icon from a resource.

Moved the system server related bits of the input manager out
of libui and into libinput since they do not need to be linked into
applications.

Change-Id: Iec11e0725b3add2b905c51f8ea2c3b4b0d1a2d67
This commit is contained in:
Jeff Brown 2011-01-02 16:37:43 -08:00
parent d95aaf3982
commit 4125036157
14 changed files with 9 additions and 14933 deletions

View File

@ -37,6 +37,15 @@ struct DisplayInfo {
float ydpi;
};
/* Display orientations as defined in Surface.java and ISurfaceComposer.h. */
enum {
DISPLAY_ORIENTATION_0 = 0,
DISPLAY_ORIENTATION_90 = 1,
DISPLAY_ORIENTATION_180 = 2,
DISPLAY_ORIENTATION_270 = 3
};
}; // namespace android
#endif // ANDROID_COMPOSER_DISPLAY_INFO_H

View File

@ -1,327 +0,0 @@
/*
* Copyright (C) 2005 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 _RUNTIME_EVENT_HUB_H
#define _RUNTIME_EVENT_HUB_H
#include <ui/Input.h>
#include <ui/Keyboard.h>
#include <ui/KeyLayoutMap.h>
#include <ui/KeyCharacterMap.h>
#include <ui/VirtualKeyMap.h>
#include <utils/String8.h>
#include <utils/threads.h>
#include <utils/Log.h>
#include <utils/threads.h>
#include <utils/List.h>
#include <utils/Errors.h>
#include <utils/PropertyMap.h>
#include <utils/Vector.h>
#include <linux/input.h>
/* These constants are not defined in linux/input.h but they are part of the multitouch
* input protocol. */
#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */
#define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */
#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */
#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device (finger, pen, ...) */
#define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */
#define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */
#define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */
#define MT_TOOL_FINGER 0 /* Identifies a finger */
#define MT_TOOL_PEN 1 /* Identifies a pen */
#define SYN_MT_REPORT 2
/* Convenience constants. */
#define BTN_FIRST 0x100 // first button scancode
#define BTN_LAST 0x15f // last button scancode
struct pollfd;
namespace android {
/*
* 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; }
inline void clear() {
valid = false;
minValue = 0;
maxValue = 0;
flat = 0;
fuzz = 0;
}
};
/*
* Input device classes.
*/
enum {
/* The input device is a keyboard. */
INPUT_DEVICE_CLASS_KEYBOARD = 0x00000001,
/* The input device is an alpha-numeric keyboard (not just a dial pad). */
INPUT_DEVICE_CLASS_ALPHAKEY = 0x00000002,
/* The input device is a touchscreen (either single-touch or multi-touch). */
INPUT_DEVICE_CLASS_TOUCHSCREEN = 0x00000004,
/* The input device is a cursor device such as a trackball or mouse. */
INPUT_DEVICE_CLASS_CURSOR = 0x00000008,
/* The input device is a multi-touch touchscreen. */
INPUT_DEVICE_CLASS_TOUCHSCREEN_MT= 0x00000010,
/* The input device is a directional pad (implies keyboard, has DPAD keys). */
INPUT_DEVICE_CLASS_DPAD = 0x00000020,
/* The input device is a gamepad (implies keyboard, has BUTTON keys). */
INPUT_DEVICE_CLASS_GAMEPAD = 0x00000040,
/* The input device has switches. */
INPUT_DEVICE_CLASS_SWITCH = 0x00000080,
};
/*
* Grand Central Station for events.
*
* The event hub aggregates input events received across all known input
* devices on the system, including devices that may be emulated by the simulator
* environment. In addition, the event hub generates fake input events to indicate
* when devices are added or removed.
*
* The event hub provies a stream of input events (via the getEvent function).
* It also supports querying the current actual state of input devices such as identifying
* which keys are currently down. Finally, the event hub keeps track of the capabilities of
* individual input devices, such as their class and the set of key codes that they support.
*/
class EventHubInterface : public virtual RefBase {
protected:
EventHubInterface() { }
virtual ~EventHubInterface() { }
public:
// Synthetic raw event type codes produced when devices are added or removed.
enum {
// Sent when a device is added.
DEVICE_ADDED = 0x10000000,
// Sent when a device is removed.
DEVICE_REMOVED = 0x20000000,
// Sent when all added/removed devices from the most recent scan have been reported.
// This event is always sent at least once.
FINISHED_DEVICE_SCAN = 0x30000000,
};
virtual uint32_t getDeviceClasses(int32_t deviceId) const = 0;
virtual String8 getDeviceName(int32_t deviceId) const = 0;
virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) 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;
// exclude a particular device from opening
// this can be used to ignore input devices for sensors
virtual void addExcludedDevice(const char* deviceName) = 0;
/*
* Wait for the next event to become available and return it.
* After returning, the EventHub holds onto a wake lock until the next call to getEvent.
* This ensures that the device will not go to sleep while the event is being processed.
* If the device needs to remain awake longer than that, then the caller is responsible
* for taking care of it (say, by poking the power manager user activity timer).
*/
virtual bool getEvent(RawEvent* outEvent) = 0;
/*
* Query current input state.
*/
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 markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
uint8_t* outFlags) const = 0;
virtual bool hasLed(int32_t deviceId, int32_t led) const = 0;
virtual void setLedState(int32_t deviceId, int32_t led, bool on) = 0;
virtual void getVirtualKeyDefinitions(int32_t deviceId,
Vector<VirtualKeyDefinition>& outVirtualKeys) const = 0;
virtual void dump(String8& dump) = 0;
};
class EventHub : public EventHubInterface
{
public:
EventHub();
status_t errorCheck() const;
virtual uint32_t getDeviceClasses(int32_t deviceId) const;
virtual String8 getDeviceName(int32_t deviceId) const;
virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) 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 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 markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
const int32_t* keyCodes, uint8_t* outFlags) const;
virtual bool getEvent(RawEvent* outEvent);
virtual bool hasLed(int32_t deviceId, int32_t led) const;
virtual void setLedState(int32_t deviceId, int32_t led, bool on);
virtual void getVirtualKeyDefinitions(int32_t deviceId,
Vector<VirtualKeyDefinition>& outVirtualKeys) const;
virtual void dump(String8& dump);
protected:
virtual ~EventHub();
private:
bool openPlatformInput(void);
int openDevice(const char *devicePath);
int closeDevice(const char *devicePath);
int scanDir(const char *dirname);
int readNotify(int nfd);
status_t mError;
struct Device {
Device* next;
int fd;
const int32_t id;
const String8 path;
const InputDeviceIdentifier identifier;
uint32_t classes;
uint8_t* keyBitmask;
String8 configurationFile;
PropertyMap* configuration;
VirtualKeyMap* virtualKeyMap;
KeyMap keyMap;
Device(int fd, int32_t id, const String8& path, const InputDeviceIdentifier& identifier);
~Device();
void close();
};
Device* getDeviceLocked(int32_t deviceId) const;
bool hasKeycodeLocked(Device* device, int keycode) const;
int32_t getScanCodeStateLocked(Device* device, int32_t scanCode) const;
int32_t getKeyCodeStateLocked(Device* device, int32_t keyCode) const;
int32_t getSwitchStateLocked(Device* device, int32_t sw) const;
bool markSupportedKeyCodesLocked(Device* device, size_t numCodes,
const int32_t* keyCodes, uint8_t* outFlags) const;
void loadConfiguration(Device* device);
status_t loadVirtualKeyMap(Device* device);
status_t loadKeyMap(Device* device);
void setKeyboardProperties(Device* device, bool builtInKeyboard);
void clearKeyboardProperties(Device* device, bool builtInKeyboard);
// Protect all internal state.
mutable Mutex mLock;
// The actual id of the built-in keyboard, or -1 if none.
// EventHub remaps the built-in keyboard to id 0 externally as required by the API.
int32_t mBuiltInKeyboardId;
int32_t mNextDeviceId;
// Parallel arrays of fds and devices.
// First index is reserved for inotify.
Vector<struct pollfd> mFds;
Vector<Device*> mDevices;
Device *mOpeningDevices;
Device *mClosingDevices;
bool mOpened;
bool mNeedToSendFinishedDeviceScan;
List<String8> mExcludedDevices;
// device ids that report particular switches.
#ifdef EV_SW
int32_t mSwitches[SW_MAX + 1];
#endif
static const int INPUT_BUFFER_SIZE = 64;
struct input_event mInputBufferData[INPUT_BUFFER_SIZE];
size_t mInputBufferIndex;
size_t mInputBufferCount;
size_t mInputFdIndex;
};
}; // namespace android
#endif // _RUNTIME_EVENT_HUB_H

File diff suppressed because it is too large Load Diff

View File

@ -1,115 +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_MANAGER_H
#define _UI_INPUT_MANAGER_H
/**
* Native input manager.
*/
#include <ui/EventHub.h>
#include <ui/Input.h>
#include <utils/Errors.h>
#include <utils/Vector.h>
#include <utils/Timers.h>
#include <utils/RefBase.h>
#include <utils/String8.h>
namespace android {
class InputChannel;
class InputReaderInterface;
class InputReaderPolicyInterface;
class InputReaderThread;
class InputDispatcherInterface;
class InputDispatcherPolicyInterface;
class InputDispatcherThread;
/*
* The input manager is the core of the system event processing.
*
* The input manager uses two threads.
*
* 1. The InputReaderThread (called "InputReader") reads and preprocesses raw input events,
* applies policy, and posts messages to a queue managed by the DispatcherThread.
* 2. The InputDispatcherThread (called "InputDispatcher") thread waits for new events on the
* queue and asynchronously dispatches them to applications.
*
* By design, the InputReaderThread class and InputDispatcherThread class do not share any
* internal state. Moreover, all communication is done one way from the InputReaderThread
* into the InputDispatcherThread and never the reverse. Both classes may interact with the
* InputDispatchPolicy, however.
*
* The InputManager class never makes any calls into Java itself. Instead, the
* InputDispatchPolicy is responsible for performing all external interactions with the
* system, including calling DVM services.
*/
class InputManagerInterface : public virtual RefBase {
protected:
InputManagerInterface() { }
virtual ~InputManagerInterface() { }
public:
/* Starts the input manager threads. */
virtual status_t start() = 0;
/* Stops the input manager threads and waits for them to exit. */
virtual status_t stop() = 0;
/* Gets the input reader. */
virtual sp<InputReaderInterface> getReader() = 0;
/* Gets the input dispatcher. */
virtual sp<InputDispatcherInterface> getDispatcher() = 0;
};
class InputManager : public InputManagerInterface {
protected:
virtual ~InputManager();
public:
InputManager(
const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy);
// (used for testing purposes)
InputManager(
const sp<InputReaderInterface>& reader,
const sp<InputDispatcherInterface>& dispatcher);
virtual status_t start();
virtual status_t stop();
virtual sp<InputReaderInterface> getReader();
virtual sp<InputDispatcherInterface> getDispatcher();
private:
sp<InputReaderInterface> mReader;
sp<InputReaderThread> mReaderThread;
sp<InputDispatcherInterface> mDispatcher;
sp<InputDispatcherThread> mDispatcherThread;
void initialize();
};
} // namespace android
#endif // _UI_INPUT_MANAGER_H

View File

@ -1,953 +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_READER_H
#define _UI_INPUT_READER_H
#include <ui/EventHub.h>
#include <ui/Input.h>
#include <ui/InputDispatcher.h>
#include <ui/PointerController.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>
namespace android {
class InputDevice;
class InputMapper;
/*
* Input reader policy interface.
*
* The input reader policy is used by the input reader to interact with the Window Manager
* and other system components.
*
* The actual implementation is partially supported by callbacks into the DVM
* via JNI. This interface is also mocked in the unit tests.
*/
class InputReaderPolicyInterface : public virtual RefBase {
protected:
InputReaderPolicyInterface() { }
virtual ~InputReaderPolicyInterface() { }
public:
/* Display orientations. */
enum {
ROTATION_0 = 0,
ROTATION_90 = 1,
ROTATION_180 = 2,
ROTATION_270 = 3
};
/* Gets information about the display with the specified id.
* Returns true if the display info is available, false otherwise.
*/
virtual bool getDisplayInfo(int32_t displayId,
int32_t* width, int32_t* height, int32_t* orientation) = 0;
/* Determines whether to turn on some hacks we have to improve the touch interaction with a
* certain device whose screen currently is not all that good.
*/
virtual bool filterTouchEvents() = 0;
/* Determines whether to turn on some hacks to improve touch interaction with another device
* where touch coordinate data can get corrupted.
*/
virtual bool filterJumpyTouchEvents() = 0;
/* Gets the excluded device names for the platform. */
virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) = 0;
/* Gets a pointer controller associated with the specified cursor device (ie. a mouse). */
virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) = 0;
};
/* Processes raw input events and sends cooked event data to an input dispatcher. */
class InputReaderInterface : public virtual RefBase {
protected:
InputReaderInterface() { }
virtual ~InputReaderInterface() { }
public:
/* Dumps the state of the input reader.
*
* This method may be called on any thread (usually by the input manager). */
virtual void dump(String8& dump) = 0;
/* Runs a single iteration of the processing loop.
* Nominally reads and processes one incoming message from the EventHub.
*
* This method should be called on the input reader thread.
*/
virtual void loopOnce() = 0;
/* Gets the current input device configuration.
*
* This method may be called on any thread (usually by the input manager).
*/
virtual void getInputConfiguration(InputConfiguration* outConfiguration) = 0;
/* 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 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(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 {
public:
InputReaderContext() { }
virtual ~InputReaderContext() { }
virtual void updateGlobalMetaState() = 0;
virtual int32_t getGlobalMetaState() = 0;
virtual InputReaderPolicyInterface* getPolicy() = 0;
virtual InputDispatcherInterface* getDispatcher() = 0;
virtual EventHubInterface* getEventHub() = 0;
};
/* The input reader reads raw event data from the event hub and processes it into input events
* that it sends to the input dispatcher. Some functions of the input reader, such as early
* event filtering in low power states, are controlled by a separate policy object.
*
* IMPORTANT INVARIANT:
* Because the policy 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 whenever re-entrance can happen.
*/
class InputReader : public InputReaderInterface, protected InputReaderContext {
public:
InputReader(const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& policy,
const sp<InputDispatcherInterface>& dispatcher);
virtual ~InputReader();
virtual void dump(String8& dump);
virtual void loopOnce();
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);
protected:
// These methods are protected virtual so they can be overridden and instrumented
// by test cases.
virtual InputDevice* createDevice(int32_t deviceId, const String8& name, uint32_t classes);
private:
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;
// low-level input event decoding and device management
void process(const RawEvent* rawEvent);
void addDevice(int32_t deviceId);
void removeDevice(int32_t deviceId);
void configureExcludedDevices();
void consumeEvent(const RawEvent* rawEvent);
void handleConfigurationChanged(nsecs_t when);
// 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);
};
/* Reads raw events from the event hub and processes them, endlessly. */
class InputReaderThread : public Thread {
public:
InputReaderThread(const sp<InputReaderInterface>& reader);
virtual ~InputReaderThread();
private:
sp<InputReaderInterface> mReader;
virtual bool threadLoop();
};
/* 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 dump(String8& dump);
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();
inline const PropertyMap& getConfiguration() {
return mConfiguration;
}
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);
PropertyMap mConfiguration;
};
/* 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 dump(String8& dump);
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;
};
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, uint32_t sources, int32_t keyboardType);
virtual ~KeyboardInputMapper();
virtual uint32_t getSources();
virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
virtual void dump(String8& dump);
virtual void configure();
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:
Mutex mLock;
struct KeyDown {
int32_t keyCode;
int32_t scanCode;
};
uint32_t mSources;
int32_t mKeyboardType;
// Immutable configuration parameters.
struct Parameters {
int32_t associatedDisplayId;
bool orientationAware;
} mParameters;
struct LockedState {
Vector<KeyDown> keyDowns; // keys that are down
int32_t metaState;
nsecs_t downTime; // time of most recent key down
struct LedState {
bool avail; // led is available
bool on; // we think the led is currently on
};
LedState capsLockLedState;
LedState numLockLedState;
LedState scrollLockLedState;
} mLocked;
void initializeLocked();
void configureParameters();
void dumpParameters(String8& dump);
bool isKeyboardOrGamepadKey(int32_t scanCode);
void processKey(nsecs_t when, bool down, int32_t keyCode, int32_t scanCode,
uint32_t policyFlags);
ssize_t findKeyDownLocked(int32_t scanCode);
void resetLedStateLocked();
void initializeLedStateLocked(LockedState::LedState& ledState, int32_t led);
void updateLedStateLocked(bool reset);
void updateLedStateForModifierLocked(LockedState::LedState& ledState, int32_t led,
int32_t modifier, bool reset);
};
class CursorInputMapper : public InputMapper {
public:
CursorInputMapper(InputDevice* device);
virtual ~CursorInputMapper();
virtual uint32_t getSources();
virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
virtual void dump(String8& dump);
virtual void configure();
virtual void reset();
virtual void process(const RawEvent* rawEvent);
virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
private:
// Amount that trackball needs to move in order to generate a key event.
static const int32_t TRACKBALL_MOVEMENT_THRESHOLD = 6;
Mutex mLock;
// Immutable configuration parameters.
struct Parameters {
enum Mode {
MODE_POINTER,
MODE_NAVIGATION,
};
Mode mode;
int32_t associatedDisplayId;
bool orientationAware;
} mParameters;
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;
}
} mAccumulator;
int32_t mSources;
float mXScale;
float mYScale;
float mXPrecision;
float mYPrecision;
sp<PointerControllerInterface> mPointerController;
struct LockedState {
bool down;
nsecs_t downTime;
} mLocked;
void initializeLocked();
void configureParameters();
void dumpParameters(String8& dump);
void sync(nsecs_t when);
};
class TouchInputMapper : public InputMapper {
public:
TouchInputMapper(InputDevice* device);
virtual ~TouchInputMapper();
virtual uint32_t getSources();
virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
virtual void dump(String8& dump);
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:
Mutex mLock;
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;
}
};
// Raw data for a single pointer.
struct PointerData {
uint32_t id;
int32_t x;
int32_t y;
int32_t pressure;
int32_t touchMajor;
int32_t touchMinor;
int32_t toolMajor;
int32_t toolMinor;
int32_t orientation;
inline bool operator== (const PointerData& other) const {
return id == other.id
&& x == other.x
&& y == other.y
&& pressure == other.pressure
&& touchMajor == other.touchMajor
&& touchMinor == other.touchMinor
&& toolMajor == other.toolMajor
&& toolMinor == other.toolMinor
&& orientation == other.orientation;
}
inline bool operator!= (const PointerData& other) const {
return !(*this == other);
}
};
// Raw data for a collection of pointers including a pointer id mapping table.
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];
int id = pointers[i].id;
idToIndex[id] = other.idToIndex[id];
}
}
inline void clear() {
pointerCount = 0;
idBits.clear();
}
};
// Input sources supported by the device.
int32_t mSources;
// Immutable configuration parameters.
struct Parameters {
enum DeviceType {
DEVICE_TYPE_TOUCH_SCREEN,
DEVICE_TYPE_TOUCH_PAD,
};
DeviceType deviceType;
int32_t associatedDisplayId;
bool orientationAware;
bool useBadTouchFilter;
bool useJumpyTouchFilter;
bool useAveragingTouchFilter;
} mParameters;
// Immutable calibration parameters in parsed form.
struct Calibration {
// Position
bool haveXOrigin;
int32_t xOrigin;
bool haveYOrigin;
int32_t yOrigin;
bool haveXScale;
float xScale;
bool haveYScale;
float yScale;
// Touch Size
enum TouchSizeCalibration {
TOUCH_SIZE_CALIBRATION_DEFAULT,
TOUCH_SIZE_CALIBRATION_NONE,
TOUCH_SIZE_CALIBRATION_GEOMETRIC,
TOUCH_SIZE_CALIBRATION_PRESSURE,
};
TouchSizeCalibration touchSizeCalibration;
// Tool Size
enum ToolSizeCalibration {
TOOL_SIZE_CALIBRATION_DEFAULT,
TOOL_SIZE_CALIBRATION_NONE,
TOOL_SIZE_CALIBRATION_GEOMETRIC,
TOOL_SIZE_CALIBRATION_LINEAR,
TOOL_SIZE_CALIBRATION_AREA,
};
ToolSizeCalibration toolSizeCalibration;
bool haveToolSizeLinearScale;
float toolSizeLinearScale;
bool haveToolSizeLinearBias;
float toolSizeLinearBias;
bool haveToolSizeAreaScale;
float toolSizeAreaScale;
bool haveToolSizeAreaBias;
float toolSizeAreaBias;
bool haveToolSizeIsSummed;
bool toolSizeIsSummed;
// Pressure
enum PressureCalibration {
PRESSURE_CALIBRATION_DEFAULT,
PRESSURE_CALIBRATION_NONE,
PRESSURE_CALIBRATION_PHYSICAL,
PRESSURE_CALIBRATION_AMPLITUDE,
};
enum PressureSource {
PRESSURE_SOURCE_DEFAULT,
PRESSURE_SOURCE_PRESSURE,
PRESSURE_SOURCE_TOUCH,
};
PressureCalibration pressureCalibration;
PressureSource pressureSource;
bool havePressureScale;
float pressureScale;
// Size
enum SizeCalibration {
SIZE_CALIBRATION_DEFAULT,
SIZE_CALIBRATION_NONE,
SIZE_CALIBRATION_NORMALIZED,
};
SizeCalibration sizeCalibration;
// Orientation
enum OrientationCalibration {
ORIENTATION_CALIBRATION_DEFAULT,
ORIENTATION_CALIBRATION_NONE,
ORIENTATION_CALIBRATION_INTERPOLATED,
};
OrientationCalibration orientationCalibration;
} mCalibration;
// Raw axis information from the driver.
struct RawAxes {
RawAbsoluteAxisInfo x;
RawAbsoluteAxisInfo y;
RawAbsoluteAxisInfo pressure;
RawAbsoluteAxisInfo touchMajor;
RawAbsoluteAxisInfo touchMinor;
RawAbsoluteAxisInfo toolMajor;
RawAbsoluteAxisInfo toolMinor;
RawAbsoluteAxisInfo orientation;
} mRawAxes;
// Current and previous touch sample data.
TouchData mCurrentTouch;
TouchData mLastTouch;
// The time the primary pointer last went down.
nsecs_t mDownTime;
struct LockedState {
Vector<VirtualKey> virtualKeys;
// The surface orientation and width and height set by configureSurfaceLocked().
int32_t surfaceOrientation;
int32_t surfaceWidth, surfaceHeight;
// Translation and scaling factors, orientation-independent.
int32_t xOrigin;
float xScale;
float xPrecision;
int32_t yOrigin;
float yScale;
float yPrecision;
float geometricScale;
float toolSizeLinearScale;
float toolSizeLinearBias;
float toolSizeAreaScale;
float toolSizeAreaBias;
float pressureScale;
float sizeScale;
float orientationScale;
// Oriented motion ranges for input device info.
struct OrientedRanges {
InputDeviceInfo::MotionRange x;
InputDeviceInfo::MotionRange y;
bool havePressure;
InputDeviceInfo::MotionRange pressure;
bool haveSize;
InputDeviceInfo::MotionRange size;
bool haveTouchSize;
InputDeviceInfo::MotionRange touchMajor;
InputDeviceInfo::MotionRange touchMinor;
bool haveToolSize;
InputDeviceInfo::MotionRange toolMajor;
InputDeviceInfo::MotionRange toolMinor;
bool haveOrientation;
InputDeviceInfo::MotionRange orientation;
} orientedRanges;
// Oriented dimensions and precision.
float orientedSurfaceWidth, orientedSurfaceHeight;
float orientedXPrecision, orientedYPrecision;
struct CurrentVirtualKeyState {
bool down;
nsecs_t downTime;
int32_t keyCode;
int32_t scanCode;
} currentVirtualKey;
} mLocked;
virtual void configureParameters();
virtual void dumpParameters(String8& dump);
virtual void configureRawAxes();
virtual void dumpRawAxes(String8& dump);
virtual bool configureSurfaceLocked();
virtual void dumpSurfaceLocked(String8& dump);
virtual void configureVirtualKeysLocked();
virtual void dumpVirtualKeysLocked(String8& dump);
virtual void parseCalibration();
virtual void resolveCalibration();
virtual void dumpCalibration(String8& dump);
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 JumpyTouchFilterState {
uint32_t jumpyPointsDropped;
} mJumpyTouchFilter;
struct PointerDistanceHeapElement {
uint32_t currentPointerIndex : 8;
uint32_t lastPointerIndex : 8;
uint64_t distance : 48; // squared distance
};
void initializeLocked();
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, uint32_t pointerCount,
int32_t motionEventAction);
bool isPointInsideSurfaceLocked(int32_t x, int32_t y);
const VirtualKey* findVirtualKeyHitLocked(int32_t x, int32_t y);
bool applyBadTouchFilter();
bool applyJumpyTouchFilter();
void applyAveragingTouchFilter();
void calculatePointerIds();
};
class SingleTouchInputMapper : public TouchInputMapper {
public:
SingleTouchInputMapper(InputDevice* device);
virtual ~SingleTouchInputMapper();
virtual void reset();
virtual void process(const RawEvent* rawEvent);
protected:
virtual void configureRawAxes();
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;
}
} mAccumulator;
bool mDown;
int32_t mX;
int32_t mY;
int32_t mPressure;
int32_t mToolWidth;
void initialize();
void sync(nsecs_t when);
};
class MultiTouchInputMapper : public TouchInputMapper {
public:
MultiTouchInputMapper(InputDevice* device);
virtual ~MultiTouchInputMapper();
virtual void reset();
virtual void process(const RawEvent* rawEvent);
protected:
virtual void configureRawAxes();
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,
FIELD_ABS_MT_PRESSURE = 256,
};
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;
int32_t absMTPressure;
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();
}
} mAccumulator;
void initialize();
void sync(nsecs_t when);
};
} // namespace android
#endif // _UI_INPUT_READER_H

View File

@ -1,63 +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_POINTER_CONTROLLER_H
#define _UI_POINTER_CONTROLLER_H
#include <utils/RefBase.h>
namespace android {
enum {
POINTER_BUTTON_1 = 1 << 0,
};
/**
* Interface for tracking a single (mouse) pointer.
*
* The pointer controller is responsible for providing synchronization and for tracking
* display orientation changes if needed.
*/
class PointerControllerInterface : public virtual RefBase {
protected:
PointerControllerInterface() { }
virtual ~PointerControllerInterface() { }
public:
/* Gets the bounds of the region that the pointer can traverse.
* Returns true if the bounds are available. */
virtual bool getBounds(float* outMinX, float* outMinY,
float* outMaxX, float* outMaxY) const = 0;
/* Move the pointer. */
virtual void move(float deltaX, float deltaY) = 0;
/* Sets a mask that indicates which buttons are pressed. */
virtual void setButtonState(uint32_t buttonState) = 0;
/* Gets a mask that indicates which buttons are pressed. */
virtual uint32_t getButtonState() const = 0;
/* Sets the absolute location of the pointer. */
virtual void setPosition(float x, float y) = 0;
/* Gets the absolute location of the pointer. */
virtual void getPosition(float* outX, float* outY) const = 0;
};
} // namespace android
#endif // _UI_POINTER_CONTROLLER_H

View File

@ -43,16 +43,12 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
$(commonSources) \
EGLUtils.cpp \
EventHub.cpp \
EventRecurrence.cpp \
FramebufferNativeWindow.cpp \
GraphicBuffer.cpp \
GraphicBufferAllocator.cpp \
GraphicBufferMapper.cpp \
GraphicLog.cpp \
InputDispatcher.cpp \
InputManager.cpp \
InputReader.cpp \
InputTransport.cpp \
PixelFormat.cpp \
Rect.cpp \

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,83 +0,0 @@
//
// Copyright 2010 The Android Open Source Project
//
// The input manager.
//
#define LOG_TAG "InputManager"
//#define LOG_NDEBUG 0
#include <cutils/log.h>
#include <ui/InputManager.h>
#include <ui/InputReader.h>
#include <ui/InputDispatcher.h>
namespace android {
InputManager::InputManager(
const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
mDispatcher = new InputDispatcher(dispatcherPolicy);
mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
initialize();
}
InputManager::InputManager(
const sp<InputReaderInterface>& reader,
const sp<InputDispatcherInterface>& dispatcher) :
mReader(reader),
mDispatcher(dispatcher) {
initialize();
}
InputManager::~InputManager() {
stop();
}
void InputManager::initialize() {
mReaderThread = new InputReaderThread(mReader);
mDispatcherThread = new InputDispatcherThread(mDispatcher);
}
status_t InputManager::start() {
status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
if (result) {
LOGE("Could not start InputDispatcher thread due to error %d.", result);
return result;
}
result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
if (result) {
LOGE("Could not start InputReader thread due to error %d.", result);
mDispatcherThread->requestExit();
return result;
}
return OK;
}
status_t InputManager::stop() {
status_t result = mReaderThread->requestExitAndWait();
if (result) {
LOGW("Could not stop InputReader thread due to error %d.", result);
}
result = mDispatcherThread->requestExitAndWait();
if (result) {
LOGW("Could not stop InputDispatcher thread due to error %d.", result);
}
return OK;
}
sp<InputReaderInterface> InputManager::getReader() {
return mReader;
}
sp<InputDispatcherInterface> InputManager::getDispatcher() {
return mDispatcher;
}
} // namespace android

File diff suppressed because it is too large Load Diff

View File

@ -7,8 +7,6 @@ ifneq ($(TARGET_SIMULATOR),true)
# Build the unit tests.
test_src_files := \
InputChannel_test.cpp \
InputReader_test.cpp \
InputDispatcher_test.cpp \
InputPublisherAndConsumer_test.cpp
shared_libraries := \

View File

@ -1,229 +0,0 @@
//
// Copyright 2010 The Android Open Source Project
//
#include <ui/InputDispatcher.h>
#include <gtest/gtest.h>
#include <linux/input.h>
namespace android {
// An arbitrary time value.
static const nsecs_t ARBITRARY_TIME = 1234;
// An arbitrary device id.
static const int32_t DEVICE_ID = 1;
// An arbitrary injector pid / uid pair that has permission to inject events.
static const int32_t INJECTOR_PID = 999;
static const int32_t INJECTOR_UID = 1001;
// --- FakeInputDispatcherPolicy ---
class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
protected:
virtual ~FakeInputDispatcherPolicy() {
}
public:
FakeInputDispatcherPolicy() {
}
private:
virtual void notifyConfigurationChanged(nsecs_t when) {
}
virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
const sp<InputChannel>& inputChannel) {
return 0;
}
virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
}
virtual nsecs_t getKeyRepeatTimeout() {
return 500 * 1000000LL;
}
virtual nsecs_t getKeyRepeatDelay() {
return 50 * 1000000LL;
}
virtual int32_t getMaxEventsPerSecond() {
return 60;
}
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
}
virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
}
virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
const KeyEvent* keyEvent, uint32_t policyFlags) {
return false;
}
virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
return false;
}
virtual void notifySwitch(nsecs_t when,
int32_t switchCode, int32_t switchValue, uint32_t policyFlags) {
}
virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
}
virtual bool checkInjectEventsPermissionNonReentrant(
int32_t injectorPid, int32_t injectorUid) {
return false;
}
};
// --- InputDispatcherTest ---
class InputDispatcherTest : public testing::Test {
protected:
sp<FakeInputDispatcherPolicy> mFakePolicy;
sp<InputDispatcher> mDispatcher;
virtual void SetUp() {
mFakePolicy = new FakeInputDispatcherPolicy();
mDispatcher = new InputDispatcher(mFakePolicy);
}
virtual void TearDown() {
mFakePolicy.clear();
mDispatcher.clear();
}
};
TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
KeyEvent event;
// Rejects undefined key actions.
event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
/*action*/ -1, 0,
AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
<< "Should reject key events with undefined action.";
// Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
AKEY_EVENT_ACTION_MULTIPLE, 0,
AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
<< "Should reject key events with ACTION_MULTIPLE.";
}
TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
MotionEvent event;
int32_t pointerIds[MAX_POINTERS + 1];
PointerCoords pointerCoords[MAX_POINTERS + 1];
for (int i = 0; i <= MAX_POINTERS; i++) {
pointerIds[i] = i;
}
// Rejects undefined motion actions.
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
/*action*/ -1, 0, 0, AMETA_NONE, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerIds, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
<< "Should reject motion events with undefined action.";
// Rejects pointer down with invalid index.
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
0, 0, AMETA_NONE, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerIds, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
<< "Should reject motion events with pointer down index too large.";
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
AMOTION_EVENT_ACTION_POINTER_DOWN | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
0, 0, AMETA_NONE, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerIds, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
<< "Should reject motion events with pointer down index too small.";
// Rejects pointer up with invalid index.
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
0, 0, AMETA_NONE, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerIds, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
<< "Should reject motion events with pointer up index too large.";
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
AMOTION_EVENT_ACTION_POINTER_UP | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
0, 0, AMETA_NONE, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerIds, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
<< "Should reject motion events with pointer up index too small.";
// Rejects motion events with invalid number of pointers.
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 0, pointerIds, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
<< "Should reject motion events with 0 pointers.";
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ MAX_POINTERS + 1, pointerIds, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
<< "Should reject motion events with more than MAX_POINTERS pointers.";
// Rejects motion events with invalid pointer ids.
pointerIds[0] = -1;
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerIds, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
<< "Should reject motion events with pointer ids less than 0.";
pointerIds[0] = MAX_POINTER_ID + 1;
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerIds, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
<< "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
// Rejects motion events with duplicate pointer ids.
pointerIds[0] = 1;
pointerIds[1] = 1;
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 2, pointerIds, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
<< "Should reject motion events with duplicate pointer ids.";
}
} // namespace android

File diff suppressed because it is too large Load Diff