Skip to content

Commit e38fdfa

Browse files
author
Jeff Brown
committed
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
1 parent dc0dbbd commit e38fdfa

File tree

10 files changed

+155
-71
lines changed

10 files changed

+155
-71
lines changed

core/java/android/hardware/input/InputManager.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,9 @@
3939
import android.provider.Settings;
4040
import android.provider.Settings.SettingNotFoundException;
4141
import android.util.Log;
42-
import android.view.Display;
43-
import android.view.IWindowManager;
4442
import android.view.InputDevice;
4543
import android.view.InputEvent;
4644
import android.view.KeyCharacterMap;
47-
import android.view.WindowManagerPolicy;
4845
import android.view.KeyCharacterMap.UnavailableException;
4946

5047
import java.util.ArrayList;

core/java/android/view/InputDevice.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
public final class InputDevice implements Parcelable {
4242
private int mId;
4343
private String mName;
44+
private String mDescriptor;
4445
private int mSources;
4546
private int mKeyboardType;
4647
private String mKeyCharacterMapFile;
@@ -334,12 +335,24 @@ public int getId() {
334335
* An input device descriptor uniquely identifies an input device. Its value
335336
* is intended to be persistent across system restarts, and should not change even
336337
* if the input device is disconnected, reconnected or reconfigured at any time.
338+
* </p><p>
339+
* It is possible for there to be multiple {@link InputDevice} instances that have the
340+
* same input device descriptor. This might happen in situations where a single
341+
* human input device registers multiple {@link InputDevice} instances (HID collections)
342+
* that describe separate features of the device, such as a keyboard that also
343+
* has a trackpad. Alternately, it may be that the input devices are simply
344+
* indistinguishable, such as two keyboards made by the same manufacturer.
345+
* </p><p>
346+
* The input device descriptor returned by {@link #getDescriptor} should only bt
347+
* used when an application needs to remember settings associated with a particular
348+
* input device. For all other purposes when referring to a logical
349+
* {@link InputDevice} instance at runtime use the id returned by {@link #getId()}.
337350
* </p>
338351
*
339352
* @return The input device descriptor.
340353
*/
341354
public String getDescriptor() {
342-
return "PLACEHOLDER"; // TODO: implement for real
355+
return mDescriptor;
343356
}
344357

345358
/**
@@ -548,6 +561,7 @@ public InputDevice[] newArray(int size) {
548561
private void readFromParcel(Parcel in) {
549562
mId = in.readInt();
550563
mName = in.readString();
564+
mDescriptor = in.readString();
551565
mSources = in.readInt();
552566
mKeyboardType = in.readInt();
553567
mKeyCharacterMapFile = in.readString();
@@ -566,6 +580,7 @@ private void readFromParcel(Parcel in) {
566580
public void writeToParcel(Parcel out, int flags) {
567581
out.writeInt(mId);
568582
out.writeString(mName);
583+
out.writeString(mDescriptor);
569584
out.writeInt(mSources);
570585
out.writeInt(mKeyboardType);
571586
out.writeString(mKeyCharacterMapFile);
@@ -592,7 +607,8 @@ public int describeContents() {
592607
public String toString() {
593608
StringBuilder description = new StringBuilder();
594609
description.append("Input Device ").append(mId).append(": ").append(mName).append("\n");
595-
610+
description.append(" Descriptor: ").append(mDescriptor).append("\n");
611+
596612
description.append(" Keyboard Type: ");
597613
switch (mKeyboardType) {
598614
case KEYBOARD_TYPE_NONE:

include/androidfw/Input.h

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,31 @@ class VelocityControl {
811811
VelocityTracker mVelocityTracker;
812812
};
813813

814+
/*
815+
* Identifies a device.
816+
*/
817+
struct InputDeviceIdentifier {
818+
inline InputDeviceIdentifier() :
819+
bus(0), vendor(0), product(0), version(0) {
820+
}
821+
822+
// Information provided by the kernel.
823+
String8 name;
824+
String8 location;
825+
String8 uniqueId;
826+
uint16_t bus;
827+
uint16_t vendor;
828+
uint16_t product;
829+
uint16_t version;
830+
831+
// A composite input device descriptor string that uniquely identifies the device
832+
// even across reboots or reconnections. The value of this field is used by
833+
// upper layers of the input system to associate settings with individual devices.
834+
// It is hashed from whatever kernel provided information is available.
835+
// Ideally, the way this value is computed should not change between Android releases
836+
// because that would invalidate persistent settings that rely on it.
837+
String8 descriptor;
838+
};
814839

815840
/*
816841
* Describes the characteristics and capabilities of an input device.
@@ -830,10 +855,11 @@ class InputDeviceInfo {
830855
float fuzz;
831856
};
832857

833-
void initialize(int32_t id, const String8& name);
858+
void initialize(int32_t id, const String8& name, const String8& descriptor);
834859

835860
inline int32_t getId() const { return mId; }
836861
inline const String8 getName() const { return mName; }
862+
inline const String8 getDescriptor() const { return mDescriptor; }
837863
inline uint32_t getSources() const { return mSources; }
838864

839865
const MotionRange* getMotionRange(int32_t axis, uint32_t source) const;
@@ -856,30 +882,14 @@ class InputDeviceInfo {
856882
private:
857883
int32_t mId;
858884
String8 mName;
885+
String8 mDescriptor;
859886
uint32_t mSources;
860887
int32_t mKeyboardType;
861888
String8 mKeyCharacterMapFile;
862889

863890
Vector<MotionRange> mMotionRanges;
864891
};
865892

866-
/*
867-
* Identifies a device.
868-
*/
869-
struct InputDeviceIdentifier {
870-
inline InputDeviceIdentifier() :
871-
bus(0), vendor(0), product(0), version(0) {
872-
}
873-
874-
String8 name;
875-
String8 location;
876-
String8 uniqueId;
877-
uint16_t bus;
878-
uint16_t vendor;
879-
uint16_t product;
880-
uint16_t version;
881-
};
882-
883893
/* Types of input device configuration files. */
884894
enum InputDeviceConfigurationFileType {
885895
INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION = 0, /* .idc file */

libs/androidfw/Input.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,21 +1226,24 @@ void VelocityControl::move(nsecs_t eventTime, float* deltaX, float* deltaY) {
12261226
// --- InputDeviceInfo ---
12271227

12281228
InputDeviceInfo::InputDeviceInfo() {
1229-
initialize(-1, String8("uninitialized device info"));
1229+
initialize(-1, String8("uninitialized device info"), String8("unknown"));
12301230
}
12311231

12321232
InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) :
1233-
mId(other.mId), mName(other.mName), mSources(other.mSources),
1233+
mId(other.mId), mName(other.mName), mDescriptor(other.mDescriptor),
1234+
mSources(other.mSources),
12341235
mKeyboardType(other.mKeyboardType),
1236+
mKeyCharacterMapFile(other.mKeyCharacterMapFile),
12351237
mMotionRanges(other.mMotionRanges) {
12361238
}
12371239

12381240
InputDeviceInfo::~InputDeviceInfo() {
12391241
}
12401242

1241-
void InputDeviceInfo::initialize(int32_t id, const String8& name) {
1243+
void InputDeviceInfo::initialize(int32_t id, const String8& name, const String8& descriptor) {
12421244
mId = id;
12431245
mName = name;
1246+
mDescriptor = descriptor;
12441247
mSources = 0;
12451248
mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
12461249
mMotionRanges.clear();

services/input/EventHub.cpp

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <androidfw/KeyCharacterMap.h>
4141
#include <androidfw/VirtualKeyMap.h>
4242

43+
#include <sha1.h>
4344
#include <string.h>
4445
#include <stdint.h>
4546
#include <dirent.h>
@@ -78,6 +79,20 @@ static inline const char* toString(bool value) {
7879
return value ? "true" : "false";
7980
}
8081

82+
static String8 sha1(const String8& in) {
83+
SHA1_CTX ctx;
84+
SHA1Init(&ctx);
85+
SHA1Update(&ctx, reinterpret_cast<const u_char*>(in.string()), in.size());
86+
u_char digest[SHA1_DIGEST_LENGTH];
87+
SHA1Final(digest, &ctx);
88+
89+
String8 out;
90+
for (size_t i = 0; i < SHA1_DIGEST_LENGTH; i++) {
91+
out.appendFormat("%02x", digest[i]);
92+
}
93+
return out;
94+
}
95+
8196
// --- Global Functions ---
8297

8398
uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses) {
@@ -209,11 +224,11 @@ EventHub::~EventHub(void) {
209224
release_wake_lock(WAKE_LOCK_ID);
210225
}
211226

212-
String8 EventHub::getDeviceName(int32_t deviceId) const {
227+
InputDeviceIdentifier EventHub::getDeviceIdentifier(int32_t deviceId) const {
213228
AutoMutex _l(mLock);
214229
Device* device = getDeviceLocked(deviceId);
215-
if (device == NULL) return String8();
216-
return device->identifier.name;
230+
if (device == NULL) return InputDeviceIdentifier();
231+
return device->identifier;
217232
}
218233

219234
uint32_t EventHub::getDeviceClasses(int32_t deviceId) const {
@@ -893,6 +908,30 @@ status_t EventHub::openDeviceLocked(const char *devicePath) {
893908
identifier.uniqueId.setTo(buffer);
894909
}
895910

911+
// Compute a device descriptor that uniquely identifies the device.
912+
// The descriptor is assumed to be a stable identifier. Its value should not
913+
// change between reboots, reconnections, firmware updates or new releases of Android.
914+
// Ideally, we also want the descriptor to be short and relatively opaque.
915+
String8 rawDescriptor;
916+
rawDescriptor.appendFormat(":%04x:%04x:", identifier.vendor, identifier.product);
917+
if (!identifier.uniqueId.isEmpty()) {
918+
rawDescriptor.append("uniqueId:");
919+
rawDescriptor.append(identifier.uniqueId);
920+
} if (identifier.vendor == 0 && identifier.product == 0) {
921+
// If we don't know the vendor and product id, then the device is probably
922+
// built-in so we need to rely on other information to uniquely identify
923+
// the input device. Usually we try to avoid relying on the device name or
924+
// location but for built-in input device, they are unlikely to ever change.
925+
if (!identifier.name.isEmpty()) {
926+
rawDescriptor.append("name:");
927+
rawDescriptor.append(identifier.name);
928+
} else if (!identifier.location.isEmpty()) {
929+
rawDescriptor.append("location:");
930+
rawDescriptor.append(identifier.location);
931+
}
932+
}
933+
identifier.descriptor = sha1(rawDescriptor);
934+
896935
// Make file descriptor non-blocking for use with poll().
897936
if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
898937
ALOGE("Error %d making device file descriptor non-blocking.", errno);
@@ -904,19 +943,18 @@ status_t EventHub::openDeviceLocked(const char *devicePath) {
904943
int32_t deviceId = mNextDeviceId++;
905944
Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
906945

907-
#if 0
908-
ALOGI("add device %d: %s\n", deviceId, devicePath);
909-
ALOGI(" bus: %04x\n"
910-
" vendor %04x\n"
911-
" product %04x\n"
912-
" version %04x\n",
946+
ALOGV("add device %d: %s\n", deviceId, devicePath);
947+
ALOGV(" bus: %04x\n"
948+
" vendor %04x\n"
949+
" product %04x\n"
950+
" version %04x\n",
913951
identifier.bus, identifier.vendor, identifier.product, identifier.version);
914-
ALOGI(" name: \"%s\"\n", identifier.name.string());
915-
ALOGI(" location: \"%s\"\n", identifier.location.string());
916-
ALOGI(" unique id: \"%s\"\n", identifier.uniqueId.string());
917-
ALOGI(" driver: v%d.%d.%d\n",
952+
ALOGV(" name: \"%s\"\n", identifier.name.string());
953+
ALOGV(" location: \"%s\"\n", identifier.location.string());
954+
ALOGV(" unique id: \"%s\"\n", identifier.uniqueId.string());
955+
ALOGV(" descriptor: \"%s\" (%s)\n", identifier.descriptor.string(), rawDescriptor.string());
956+
ALOGV(" driver: v%d.%d.%d\n",
918957
driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff);
919-
#endif
920958

921959
// Load the configuration file for the device.
922960
loadConfigurationLocked(device);
@@ -1303,6 +1341,7 @@ void EventHub::dump(String8& dump) {
13031341
}
13041342
dump.appendFormat(INDENT3 "Classes: 0x%08x\n", device->classes);
13051343
dump.appendFormat(INDENT3 "Path: %s\n", device->path.string());
1344+
dump.appendFormat(INDENT3 "Descriptor: %s\n", device->identifier.descriptor.string());
13061345
dump.appendFormat(INDENT3 "Location: %s\n", device->identifier.location.string());
13071346
dump.appendFormat(INDENT3 "UniqueId: %s\n", device->identifier.uniqueId.string());
13081347
dump.appendFormat(INDENT3 "Identifier: bus=0x%04x, vendor=0x%04x, "

services/input/EventHub.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ class EventHubInterface : public virtual RefBase {
151151

152152
virtual uint32_t getDeviceClasses(int32_t deviceId) const = 0;
153153

154-
virtual String8 getDeviceName(int32_t deviceId) const = 0;
154+
virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const = 0;
155155

156156
virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const = 0;
157157

@@ -230,7 +230,7 @@ class EventHub : public EventHubInterface
230230

231231
virtual uint32_t getDeviceClasses(int32_t deviceId) const;
232232

233-
virtual String8 getDeviceName(int32_t deviceId) const;
233+
virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const;
234234

235235
virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const;
236236

services/input/InputReader.cpp

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -344,18 +344,19 @@ void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
344344
}
345345

346346
void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
347-
String8 name = mEventHub->getDeviceName(deviceId);
347+
InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
348348
uint32_t classes = mEventHub->getDeviceClasses(deviceId);
349349

350-
InputDevice* device = createDeviceLocked(deviceId, name, classes);
350+
InputDevice* device = createDeviceLocked(deviceId, identifier, classes);
351351
device->configure(when, &mConfig, 0);
352352
device->reset(when);
353353

354354
if (device->isIgnored()) {
355-
ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
355+
ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
356+
identifier.name.string());
356357
} else {
357-
ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, name.string(),
358-
device->getSources());
358+
ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,
359+
identifier.name.string(), device->getSources());
359360
}
360361

361362
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
@@ -392,8 +393,8 @@ void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
392393
}
393394

394395
InputDevice* InputReader::createDeviceLocked(int32_t deviceId,
395-
const String8& name, uint32_t classes) {
396-
InputDevice* device = new InputDevice(&mContext, deviceId, name, classes);
396+
const InputDeviceIdentifier& identifier, uint32_t classes) {
397+
InputDevice* device = new InputDevice(&mContext, deviceId, identifier, classes);
397398

398399
// External devices.
399400
if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
@@ -851,9 +852,9 @@ bool InputReaderThread::threadLoop() {
851852

852853
// --- InputDevice ---
853854

854-
InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name,
855-
uint32_t classes) :
856-
mContext(context), mId(id), mName(name), mClasses(classes),
855+
InputDevice::InputDevice(InputReaderContext* context, int32_t id,
856+
const InputDeviceIdentifier& identifier, uint32_t classes) :
857+
mContext(context), mId(id), mIdentifier(identifier), mClasses(classes),
857858
mSources(0), mIsExternal(false), mDropUntilNextSync(false) {
858859
}
859860

@@ -961,7 +962,7 @@ void InputDevice::process(const RawEvent* rawEvents, size_t count) {
961962
#endif
962963
}
963964
} else if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_DROPPED) {
964-
ALOGI("Detected input event buffer overrun for device %s.", mName.string());
965+
ALOGI("Detected input event buffer overrun for device %s.", getName().string());
965966
mDropUntilNextSync = true;
966967
reset(rawEvent->when);
967968
} else {
@@ -982,7 +983,7 @@ void InputDevice::timeoutExpired(nsecs_t when) {
982983
}
983984

984985
void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
985-
outDeviceInfo->initialize(mId, mName);
986+
outDeviceInfo->initialize(mId, mIdentifier.name, mIdentifier.descriptor);
986987

987988
size_t numMappers = mMappers.size();
988989
for (size_t i = 0; i < numMappers; i++) {

0 commit comments

Comments
 (0)