Skip to content

Commit 69bba1d

Browse files
Jeff BrownAndroid (Google) Code Review
authored andcommitted
Merge "Add a unique input device descriptor."
2 parents 43de94a + e38fdfa commit 69bba1d

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)