summaryrefslogtreecommitdiffstats
path: root/services/input
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2012-04-06 14:51:01 -0700
committerJeff Brown <jeffbrown@google.com>2012-04-06 14:57:19 -0700
commite38fdfae9196afd1bdc14c5ec6c12793af1e2550 (patch)
tree54523ccf3fc36a1b50410e2cb6e6d1f7230c40cf /services/input
parentdc0dbbd4a005f16624978b95817b33156acac526 (diff)
downloadframeworks_base-e38fdfae9196afd1bdc14c5ec6c12793af1e2550.zip
frameworks_base-e38fdfae9196afd1bdc14c5ec6c12793af1e2550.tar.gz
frameworks_base-e38fdfae9196afd1bdc14c5ec6c12793af1e2550.tar.bz2
Add a unique input device descriptor.
The purpose of the input device descriptor is to make it possible to associate persistent settings for each input device, such as the keyboard layout. The descriptor is a hash of the information we have about the device, such as its vendor id, product id, unique id, name, or location. Bug: 6110399 Change-Id: Idb80f946819b3f0dbf4e661bb0a753dbc2b60981
Diffstat (limited to 'services/input')
-rw-r--r--services/input/EventHub.cpp67
-rw-r--r--services/input/EventHub.h4
-rw-r--r--services/input/InputReader.cpp25
-rw-r--r--services/input/InputReader.h9
-rw-r--r--services/input/tests/InputReader_test.cpp29
5 files changed, 91 insertions, 43 deletions
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index 1b74aa6..665d711 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -40,6 +40,7 @@
#include <androidfw/KeyCharacterMap.h>
#include <androidfw/VirtualKeyMap.h>
+#include <sha1.h>
#include <string.h>
#include <stdint.h>
#include <dirent.h>
@@ -78,6 +79,20 @@ static inline const char* toString(bool value) {
return value ? "true" : "false";
}
+static String8 sha1(const String8& in) {
+ SHA1_CTX ctx;
+ SHA1Init(&ctx);
+ SHA1Update(&ctx, reinterpret_cast<const u_char*>(in.string()), in.size());
+ u_char digest[SHA1_DIGEST_LENGTH];
+ SHA1Final(digest, &ctx);
+
+ String8 out;
+ for (size_t i = 0; i < SHA1_DIGEST_LENGTH; i++) {
+ out.appendFormat("%02x", digest[i]);
+ }
+ return out;
+}
+
// --- Global Functions ---
uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses) {
@@ -209,11 +224,11 @@ EventHub::~EventHub(void) {
release_wake_lock(WAKE_LOCK_ID);
}
-String8 EventHub::getDeviceName(int32_t deviceId) const {
+InputDeviceIdentifier EventHub::getDeviceIdentifier(int32_t deviceId) const {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device == NULL) return String8();
- return device->identifier.name;
+ if (device == NULL) return InputDeviceIdentifier();
+ return device->identifier;
}
uint32_t EventHub::getDeviceClasses(int32_t deviceId) const {
@@ -893,6 +908,30 @@ status_t EventHub::openDeviceLocked(const char *devicePath) {
identifier.uniqueId.setTo(buffer);
}
+ // Compute a device descriptor that uniquely identifies the device.
+ // The descriptor is assumed to be a stable identifier. Its value should not
+ // change between reboots, reconnections, firmware updates or new releases of Android.
+ // Ideally, we also want the descriptor to be short and relatively opaque.
+ String8 rawDescriptor;
+ rawDescriptor.appendFormat(":%04x:%04x:", identifier.vendor, identifier.product);
+ if (!identifier.uniqueId.isEmpty()) {
+ rawDescriptor.append("uniqueId:");
+ rawDescriptor.append(identifier.uniqueId);
+ } if (identifier.vendor == 0 && identifier.product == 0) {
+ // If we don't know the vendor and product id, then the device is probably
+ // built-in so we need to rely on other information to uniquely identify
+ // the input device. Usually we try to avoid relying on the device name or
+ // location but for built-in input device, they are unlikely to ever change.
+ if (!identifier.name.isEmpty()) {
+ rawDescriptor.append("name:");
+ rawDescriptor.append(identifier.name);
+ } else if (!identifier.location.isEmpty()) {
+ rawDescriptor.append("location:");
+ rawDescriptor.append(identifier.location);
+ }
+ }
+ identifier.descriptor = sha1(rawDescriptor);
+
// Make file descriptor non-blocking for use with poll().
if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
ALOGE("Error %d making device file descriptor non-blocking.", errno);
@@ -904,19 +943,18 @@ status_t EventHub::openDeviceLocked(const char *devicePath) {
int32_t deviceId = mNextDeviceId++;
Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
-#if 0
- ALOGI("add device %d: %s\n", deviceId, devicePath);
- ALOGI(" bus: %04x\n"
- " vendor %04x\n"
- " product %04x\n"
- " version %04x\n",
+ ALOGV("add device %d: %s\n", deviceId, devicePath);
+ ALOGV(" bus: %04x\n"
+ " vendor %04x\n"
+ " product %04x\n"
+ " version %04x\n",
identifier.bus, identifier.vendor, identifier.product, identifier.version);
- ALOGI(" name: \"%s\"\n", identifier.name.string());
- ALOGI(" location: \"%s\"\n", identifier.location.string());
- ALOGI(" unique id: \"%s\"\n", identifier.uniqueId.string());
- ALOGI(" driver: v%d.%d.%d\n",
+ ALOGV(" name: \"%s\"\n", identifier.name.string());
+ ALOGV(" location: \"%s\"\n", identifier.location.string());
+ ALOGV(" unique id: \"%s\"\n", identifier.uniqueId.string());
+ ALOGV(" descriptor: \"%s\" (%s)\n", identifier.descriptor.string(), rawDescriptor.string());
+ ALOGV(" driver: v%d.%d.%d\n",
driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff);
-#endif
// Load the configuration file for the device.
loadConfigurationLocked(device);
@@ -1303,6 +1341,7 @@ void EventHub::dump(String8& dump) {
}
dump.appendFormat(INDENT3 "Classes: 0x%08x\n", device->classes);
dump.appendFormat(INDENT3 "Path: %s\n", device->path.string());
+ dump.appendFormat(INDENT3 "Descriptor: %s\n", device->identifier.descriptor.string());
dump.appendFormat(INDENT3 "Location: %s\n", device->identifier.location.string());
dump.appendFormat(INDENT3 "UniqueId: %s\n", device->identifier.uniqueId.string());
dump.appendFormat(INDENT3 "Identifier: bus=0x%04x, vendor=0x%04x, "
diff --git a/services/input/EventHub.h b/services/input/EventHub.h
index 4eb47c6..bd21a3d 100644
--- a/services/input/EventHub.h
+++ b/services/input/EventHub.h
@@ -151,7 +151,7 @@ public:
virtual uint32_t getDeviceClasses(int32_t deviceId) const = 0;
- virtual String8 getDeviceName(int32_t deviceId) const = 0;
+ virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const = 0;
virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const = 0;
@@ -230,7 +230,7 @@ public:
virtual uint32_t getDeviceClasses(int32_t deviceId) const;
- virtual String8 getDeviceName(int32_t deviceId) const;
+ virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const;
virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const;
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index eccce29..ddd870d 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -344,18 +344,19 @@ void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
}
void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
- String8 name = mEventHub->getDeviceName(deviceId);
+ InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
uint32_t classes = mEventHub->getDeviceClasses(deviceId);
- InputDevice* device = createDeviceLocked(deviceId, name, classes);
+ InputDevice* device = createDeviceLocked(deviceId, identifier, classes);
device->configure(when, &mConfig, 0);
device->reset(when);
if (device->isIgnored()) {
- ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
+ ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
+ identifier.name.string());
} else {
- ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, name.string(),
- device->getSources());
+ ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,
+ identifier.name.string(), device->getSources());
}
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
@@ -392,8 +393,8 @@ void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
}
InputDevice* InputReader::createDeviceLocked(int32_t deviceId,
- const String8& name, uint32_t classes) {
- InputDevice* device = new InputDevice(&mContext, deviceId, name, classes);
+ const InputDeviceIdentifier& identifier, uint32_t classes) {
+ InputDevice* device = new InputDevice(&mContext, deviceId, identifier, classes);
// External devices.
if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
@@ -851,9 +852,9 @@ bool InputReaderThread::threadLoop() {
// --- InputDevice ---
-InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name,
- uint32_t classes) :
- mContext(context), mId(id), mName(name), mClasses(classes),
+InputDevice::InputDevice(InputReaderContext* context, int32_t id,
+ const InputDeviceIdentifier& identifier, uint32_t classes) :
+ mContext(context), mId(id), mIdentifier(identifier), mClasses(classes),
mSources(0), mIsExternal(false), mDropUntilNextSync(false) {
}
@@ -961,7 +962,7 @@ void InputDevice::process(const RawEvent* rawEvents, size_t count) {
#endif
}
} else if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_DROPPED) {
- ALOGI("Detected input event buffer overrun for device %s.", mName.string());
+ ALOGI("Detected input event buffer overrun for device %s.", getName().string());
mDropUntilNextSync = true;
reset(rawEvent->when);
} else {
@@ -982,7 +983,7 @@ void InputDevice::timeoutExpired(nsecs_t when) {
}
void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
- outDeviceInfo->initialize(mId, mName);
+ outDeviceInfo->initialize(mId, mIdentifier.name, mIdentifier.descriptor);
size_t numMappers = mMappers.size();
for (size_t i = 0; i < numMappers; i++) {
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index 9bbe49c..8520a75 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -338,7 +338,7 @@ public:
protected:
// These members are protected so they can be instrumented by test cases.
virtual InputDevice* createDeviceLocked(int32_t deviceId,
- const String8& name, uint32_t classes);
+ const InputDeviceIdentifier& identifier, uint32_t classes);
class ContextImpl : public InputReaderContext {
InputReader* mReader;
@@ -432,12 +432,13 @@ private:
/* Represents the state of a single input device. */
class InputDevice {
public:
- InputDevice(InputReaderContext* context, int32_t id, const String8& name, uint32_t classes);
+ InputDevice(InputReaderContext* context, int32_t id,
+ const InputDeviceIdentifier& identifier, uint32_t classes);
~InputDevice();
inline InputReaderContext* getContext() { return mContext; }
inline int32_t getId() { return mId; }
- inline const String8& getName() { return mName; }
+ inline const String8& getName() { return mIdentifier.name; }
inline uint32_t getClasses() { return mClasses; }
inline uint32_t getSources() { return mSources; }
@@ -486,7 +487,7 @@ public:
private:
InputReaderContext* mContext;
int32_t mId;
- String8 mName;
+ InputDeviceIdentifier mIdentifier;
uint32_t mClasses;
Vector<InputMapper*> mMappers;
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 08efe7d..2cccf9f 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -274,7 +274,7 @@ class FakeEventHub : public EventHubInterface {
};
struct Device {
- String8 name;
+ InputDeviceIdentifier identifier;
uint32_t classes;
PropertyMap configuration;
KeyedVector<int, RawAbsoluteAxisInfo> absoluteAxes;
@@ -287,8 +287,8 @@ class FakeEventHub : public EventHubInterface {
KeyedVector<int32_t, bool> leds;
Vector<VirtualKeyDefinition> virtualKeys;
- Device(const String8& name, uint32_t classes) :
- name(name), classes(classes) {
+ Device(uint32_t classes) :
+ classes(classes) {
}
};
@@ -307,7 +307,8 @@ public:
FakeEventHub() { }
void addDevice(int32_t deviceId, const String8& name, uint32_t classes) {
- Device* device = new Device(name, classes);
+ Device* device = new Device(classes);
+ device->identifier.name = name;
mDevices.add(deviceId, device);
enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_ADDED, 0, 0, 0, 0);
@@ -433,9 +434,9 @@ private:
return device ? device->classes : 0;
}
- virtual String8 getDeviceName(int32_t deviceId) const {
+ virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const {
Device* device = getDevice(deviceId);
- return device ? device->name : String8("unknown");
+ return device ? device->identifier : InputDeviceIdentifier();
}
virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const {
@@ -857,18 +858,20 @@ public:
}
InputDevice* newDevice(int32_t deviceId, const String8& name, uint32_t classes) {
- return new InputDevice(&mContext, deviceId, name, classes);
+ InputDeviceIdentifier identifier;
+ identifier.name = name;
+ return new InputDevice(&mContext, deviceId, identifier, classes);
}
protected:
virtual InputDevice* createDeviceLocked(int32_t deviceId,
- const String8& name, uint32_t classes) {
+ const InputDeviceIdentifier& identifier, uint32_t classes) {
if (mNextDevice) {
InputDevice* device = mNextDevice;
mNextDevice = NULL;
return device;
}
- return InputReader::createDeviceLocked(deviceId, name, classes);
+ return InputReader::createDeviceLocked(deviceId, identifier, classes);
}
friend class InputReaderTest;
@@ -1231,7 +1234,9 @@ protected:
mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeListener);
mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
- mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME), DEVICE_CLASSES);
+ InputDeviceIdentifier identifier;
+ identifier.name = DEVICE_NAME;
+ mDevice = new InputDevice(mFakeContext, DEVICE_ID, identifier, DEVICE_CLASSES);
}
virtual void TearDown() {
@@ -1411,7 +1416,9 @@ protected:
mFakePolicy = new FakeInputReaderPolicy();
mFakeListener = new FakeInputListener();
mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeListener);
- mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME), DEVICE_CLASSES);
+ InputDeviceIdentifier identifier;
+ identifier.name = DEVICE_NAME;
+ mDevice = new InputDevice(mFakeContext, DEVICE_ID, identifier, DEVICE_CLASSES);
mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
}