Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 319107bf authored by RoboErik's avatar RoboErik
Browse files

b/12068020 Add a way to add uniqueness to device descriptors

This adds an integer to the descriptor of devices without uniqely
identifying information. It will reuse values that are no longer
in use, so if you remove a single device and attach a different
identical device it will appear to be the same device.

TODO: Derive uniqueness from USB port when possible. This version
will generate different descriptors for each half of a USB keyboard
that shows up twice.

Change-Id: Id05d5265e21b10cbb4ae3e30f91a89a6b0e55d63
parent 418312f4
Loading
Loading
Loading
Loading
+64 −30
Original line number Diff line number Diff line
@@ -102,34 +102,6 @@ static void getLinuxRelease(int* major, int* minor) {
    }
}

static void setDescriptor(InputDeviceIdentifier& identifier) {
    // 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);
    ALOGV("Created descriptor: raw=%s, cooked=%s", rawDescriptor.string(),
            identifier.descriptor.string());
}

// --- Global Functions ---

uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses) {
@@ -590,6 +562,57 @@ bool EventHub::setKeyboardLayoutOverlay(int32_t deviceId,
    return false;
}

static String8 generateDescriptor(InputDeviceIdentifier& identifier) {
    String8 rawDescriptor;
    rawDescriptor.appendFormat(":%04x:%04x:", identifier.vendor,
            identifier.product);
    // TODO add handling for USB devices to not uniqueify kbs that show up twice
    if (!identifier.uniqueId.isEmpty()) {
        rawDescriptor.append("uniqueId:");
        rawDescriptor.append(identifier.uniqueId);
    } else if (identifier.nonce != 0) {
        rawDescriptor.appendFormat("nonce:%04x", identifier.nonce);
    }

    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);
    return rawDescriptor;
}

void EventHub::assignDescriptorLocked(InputDeviceIdentifier& identifier) {
    // 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. In practice we sometimes get devices that cannot be uniquely
    // identified. In this case we enforce uniqueness between connected devices.
    // Ideally, we also want the descriptor to be short and relatively opaque.

    identifier.nonce = 0;
    String8 rawDescriptor = generateDescriptor(identifier);
    if (identifier.uniqueId.isEmpty()) {
        // If it didn't have a unique id check for conflicts and enforce
        // uniqueness if necessary.
        while(getDeviceByDescriptorLocked(identifier.descriptor) != NULL) {
            identifier.nonce++;
            rawDescriptor = generateDescriptor(identifier);
        }
    }
    ALOGV("Created descriptor: raw=%s, cooked=%s", rawDescriptor.string(),
            identifier.descriptor.string());
}

void EventHub::vibrate(int32_t deviceId, nsecs_t duration) {
    AutoMutex _l(mLock);
    Device* device = getDeviceLocked(deviceId);
@@ -646,6 +669,17 @@ void EventHub::cancelVibrate(int32_t deviceId) {
    }
}

EventHub::Device* EventHub::getDeviceByDescriptorLocked(String8& descriptor) const {
    size_t size = mDevices.size();
    for (size_t i = 0; i < size; i++) {
        Device* device = mDevices.valueAt(i);
        if (descriptor.compare(device->identifier.descriptor) == 0) {
            return device;
        }
    }
    return NULL;
}

EventHub::Device* EventHub::getDeviceLocked(int32_t deviceId) const {
    if (deviceId == BUILT_IN_KEYBOARD_ID) {
        deviceId = mBuiltInKeyboardId;
@@ -1085,7 +1119,7 @@ status_t EventHub::openDeviceLocked(const char *devicePath) {
    }

    // Fill in the descriptor.
    setDescriptor(identifier);
    assignDescriptorLocked(identifier);

    // Make file descriptor non-blocking for use with poll().
    if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
@@ -1325,7 +1359,7 @@ void EventHub::createVirtualKeyboardLocked() {
    InputDeviceIdentifier identifier;
    identifier.name = "Virtual";
    identifier.uniqueId = "<virtual>";
    setDescriptor(identifier);
    assignDescriptorLocked(identifier);

    Device* device = new Device(-1, VIRTUAL_KEYBOARD_ID, String8("<virtual>"), identifier);
    device->classes = INPUT_DEVICE_CLASS_KEYBOARD
+2 −0
Original line number Diff line number Diff line
@@ -373,6 +373,7 @@ private:
    status_t openDeviceLocked(const char *devicePath);
    void createVirtualKeyboardLocked();
    void addDeviceLocked(Device* device);
    void assignDescriptorLocked(InputDeviceIdentifier& identifier);

    status_t closeDeviceByPathLocked(const char *devicePath);
    void closeDeviceLocked(Device* device);
@@ -382,6 +383,7 @@ private:
    void scanDevicesLocked();
    status_t readNotifyLocked();

    Device* getDeviceByDescriptorLocked(String8& descriptor) const;
    Device* getDeviceLocked(int32_t deviceId) const;
    Device* getDeviceByPathLocked(const char* devicePath) const;