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

Commit de1acacb authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Support combined vibration effects with input device."

parents 3a3cf3c5 8714371e
Loading
Loading
Loading
Loading
+82 −5
Original line number Diff line number Diff line
@@ -24,13 +24,28 @@
using android::base::StringPrintf;

namespace android {
// VibrationElement implementations
VibrationElement::VibrationElement(size_t channelNum) {
    channels.reserve(channelNum);
}

VibrationElement::VibrationElement(const VibrationElement& other) {
    duration = other.duration;
    channels.resize(other.channels.size());
    for (size_t i = 0; i < other.channels.size(); i++) {
        channels[i].first = other.channels[i].first;
        channels[i].second = other.channels[i].second;
    }
}

const std::string VibrationElement::toString() const {
    std::string dump;
    dump += StringPrintf("[duration=%lldms, channels=[", duration.count());

    for (auto it = channels.begin(); it != channels.end(); ++it) {
        dump += std::to_string(*it);
        dump += std::to_string(it->first);
        dump += " : ";
        dump += std::to_string(it->second);
        if (std::next(it) != channels.end()) {
            dump += ", ";
        }
@@ -40,17 +55,79 @@ const std::string VibrationElement::toString() const {
    return dump;
}

uint16_t VibrationElement::getMagnitude(size_t channelIdx) const {
    if (channelIdx >= channels.size()) {
uint16_t VibrationElement::getMagnitude(int32_t vibratorId) const {
    auto it =
            std::find_if(channels.begin(), channels.end(),
                         [vibratorId](const std::pair<int32_t /*vibratorId*/, uint8_t /*amplitude*/>
                                              pair) { return pair.first == vibratorId; });
    if (it == channels.end()) {
        return 0;
    }
    // convert range [0,255] to [0,65535] (android framework to linux ff ranges)
    return static_cast<uint16_t>(channels[channelIdx]) << 8;
    return static_cast<uint16_t>(it->second) << 8;
}

bool VibrationElement::isOn() const {
    return std::any_of(channels.begin(), channels.end(),
                       [](uint16_t channel) { return channel != 0; });
                       [](const auto& channel) { return channel.second != 0; });
}

void VibrationElement::addChannel(int32_t vibratorId, uint8_t amplitude) {
    channels.push_back(std::make_pair(vibratorId, amplitude));
}

bool VibrationElement::operator==(const VibrationElement& other) const {
    if (duration != other.duration || channels.size() != other.channels.size()) {
        return false;
    }
    for (size_t i = 0; i < CHANNEL_SIZE; i++) {
        if (channels[i] != other.channels[i]) {
            return false;
        }
    }
    return true;
}

bool VibrationElement::operator!=(const VibrationElement& other) const {
    return !(*this == other);
}

// VibrationSequence implementations
VibrationSequence::VibrationSequence(size_t length) {
    pattern.reserve(length);
}

void VibrationSequence::operator=(const VibrationSequence& other) {
    pattern = other.pattern;
}

bool VibrationSequence::operator==(const VibrationSequence& other) const {
    if (pattern.size() != other.pattern.size()) {
        return false;
    }
    for (size_t i = 0; i < pattern.size(); i++) {
        if (pattern[i] != other.pattern[i]) {
            return false;
        }
    }
    return true;
}

void VibrationSequence::addElement(VibrationElement element) {
    pattern.push_back(element);
}

const std::string VibrationSequence::toString() const {
    std::string dump;
    dump += "[";

    for (const auto& element : pattern) {
        dump += element.toString();
        dump += " ";
    }

    dump += "]";
    return dump;
}

} // namespace android
+6 −2
Original line number Diff line number Diff line
@@ -101,10 +101,14 @@ public:
    virtual void requestRefreshConfiguration(uint32_t changes) = 0;

    /* Controls the vibrator of a particular input device. */
    virtual void vibrate(int32_t deviceId, const std::vector<VibrationElement>& pattern,
                         ssize_t repeat, int32_t token) = 0;
    virtual void vibrate(int32_t deviceId, const VibrationSequence& sequence, ssize_t repeat,
                         int32_t token) = 0;
    virtual void cancelVibrate(int32_t deviceId, int32_t token) = 0;

    virtual bool isVibrating(int32_t deviceId) = 0;

    virtual std::vector<int32_t> getVibratorIds(int32_t deviceId) = 0;

    /* Return true if the device can send input events to the specified display. */
    virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) = 0;
};
+33 −2
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <chrono>
#include <cstdint>
#include <string>
#include <vector>

namespace android {

@@ -32,13 +33,43 @@ constexpr size_t CHANNEL_SIZE = 2;
struct VibrationElement {
    std::chrono::milliseconds duration;
    // Channel amplitude range 0-255.
    std::array<uint8_t, CHANNEL_SIZE> channels = {0, 0};
    std::vector<std::pair<int32_t /*vibratorId*/, uint8_t /*amplitude*/>> channels;

    explicit VibrationElement(size_t channelNum);

    VibrationElement(const VibrationElement& other);

    bool operator==(const VibrationElement& other) const;

    bool operator!=(const VibrationElement& other) const;

    void addChannel(int32_t vibratorId, uint8_t amplitude);

    const std::string toString() const;
    uint16_t getMagnitude(size_t channelIndex) const;

    uint16_t getMagnitude(int32_t vibratorId) const;

    bool isOn() const;
};

/*
 * Describes a sequence of rumble effect
 */
struct VibrationSequence {
    // Pattern of vibration elements
    std::vector<VibrationElement> pattern;

    explicit VibrationSequence(size_t length);

    void operator=(const VibrationSequence& other);

    bool operator==(const VibrationSequence& other) const;

    void addElement(VibrationElement element);

    const std::string toString() const;
};

} // namespace android

#endif // _VIBRATION_ELEMENT_H
+44 −32
Original line number Diff line number Diff line
@@ -61,8 +61,8 @@ static const char* DEVICE_PATH = "/dev/input";
// v4l2 devices go directly into /dev
static const char* VIDEO_DEVICE_PATH = "/dev";

static constexpr size_t FF_STRONG_MAGNITUDE_CHANNEL_IDX = 0;
static constexpr size_t FF_WEAK_MAGNITUDE_CHANNEL_IDX = 1;
static constexpr int32_t FF_STRONG_MAGNITUDE_CHANNEL_IDX = 0;
static constexpr int32_t FF_WEAK_MAGNITUDE_CHANNEL_IDX = 1;

static inline const char* toString(bool value) {
    return value ? "true" : "false";
@@ -475,25 +475,25 @@ EventHub::~EventHub(void) {
}

InputDeviceIdentifier EventHub::getDeviceIdentifier(int32_t deviceId) const {
    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    return device != nullptr ? device->identifier : InputDeviceIdentifier();
}

Flags<InputDeviceClass> EventHub::getDeviceClasses(int32_t deviceId) const {
    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    return device != nullptr ? device->classes : Flags<InputDeviceClass>(0);
}

int32_t EventHub::getDeviceControllerNumber(int32_t deviceId) const {
    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    return device != nullptr ? device->controllerNumber : 0;
}

void EventHub::getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const {
    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    if (device != nullptr && device->configuration) {
        *outConfiguration = *device->configuration;
@@ -507,7 +507,7 @@ status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,
    outAxisInfo->clear();

    if (axis >= 0 && axis <= ABS_MAX) {
        std::lock_guard<std::mutex> lock(mLock);
        std::scoped_lock _l(mLock);

        Device* device = getDeviceLocked(deviceId);
        if (device != nullptr && device->hasValidFd() && device->absBitmask.test(axis)) {
@@ -534,7 +534,7 @@ status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,

bool EventHub::hasRelativeAxis(int32_t deviceId, int axis) const {
    if (axis >= 0 && axis <= REL_MAX) {
        std::lock_guard<std::mutex> lock(mLock);
        std::scoped_lock _l(mLock);
        Device* device = getDeviceLocked(deviceId);
        return device != nullptr ? device->relBitmask.test(axis) : false;
    }
@@ -542,7 +542,7 @@ bool EventHub::hasRelativeAxis(int32_t deviceId, int axis) const {
}

bool EventHub::hasInputProperty(int32_t deviceId, int property) const {
    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);

    Device* device = getDeviceLocked(deviceId);
    return property >= 0 && property <= INPUT_PROP_MAX && device != nullptr
@@ -552,7 +552,7 @@ bool EventHub::hasInputProperty(int32_t deviceId, int property) const {

int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const {
    if (scanCode >= 0 && scanCode <= KEY_MAX) {
        std::lock_guard<std::mutex> lock(mLock);
        std::scoped_lock _l(mLock);

        Device* device = getDeviceLocked(deviceId);
        if (device != nullptr && device->hasValidFd() && device->keyBitmask.test(scanCode)) {
@@ -565,7 +565,7 @@ int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const {
}

int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);

    Device* device = getDeviceLocked(deviceId);
    if (device != nullptr && device->hasValidFd() && device->keyMap.haveKeyLayout()) {
@@ -588,7 +588,7 @@ int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const {

int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const {
    if (sw >= 0 && sw <= SW_MAX) {
        std::lock_guard<std::mutex> lock(mLock);
        std::scoped_lock _l(mLock);

        Device* device = getDeviceLocked(deviceId);
        if (device != nullptr && device->hasValidFd() && device->swBitmask.test(sw)) {
@@ -604,7 +604,7 @@ status_t EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t*
    *outValue = 0;

    if (axis >= 0 && axis <= ABS_MAX) {
        std::lock_guard<std::mutex> lock(mLock);
        std::scoped_lock _l(mLock);

        Device* device = getDeviceLocked(deviceId);
        if (device != nullptr && device->hasValidFd() && device->absBitmask.test(axis)) {
@@ -624,7 +624,7 @@ status_t EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t*

bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
                                     uint8_t* outFlags) const {
    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);

    Device* device = getDeviceLocked(deviceId);
    if (device != nullptr && device->keyMap.haveKeyLayout()) {
@@ -652,7 +652,7 @@ bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const in

status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState,
                          int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const {
    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    status_t status = NAME_NOT_FOUND;

@@ -692,7 +692,7 @@ status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,
}

status_t EventHub::mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const {
    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);
    Device* device = getDeviceLocked(deviceId);

    if (device != nullptr && device->keyMap.haveKeyLayout()) {
@@ -706,13 +706,13 @@ status_t EventHub::mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxis
}

void EventHub::setExcludedDevices(const std::vector<std::string>& devices) {
    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);

    mExcludedDevices = devices;
}

bool EventHub::hasScanCode(int32_t deviceId, int32_t scanCode) const {
    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    if (device != nullptr && scanCode >= 0 && scanCode <= KEY_MAX) {
        return device->keyBitmask.test(scanCode);
@@ -721,7 +721,7 @@ bool EventHub::hasScanCode(int32_t deviceId, int32_t scanCode) const {
}

bool EventHub::hasLed(int32_t deviceId, int32_t led) const {
    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    int32_t sc;
    if (device != nullptr && device->mapLed(led, &sc) == NO_ERROR) {
@@ -731,7 +731,7 @@ bool EventHub::hasLed(int32_t deviceId, int32_t led) const {
}

void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) {
    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    if (device != nullptr && device->hasValidFd()) {
        device->setLedStateLocked(led, on);
@@ -742,7 +742,7 @@ void EventHub::getVirtualKeyDefinitions(int32_t deviceId,
                                        std::vector<VirtualKeyDefinition>& outVirtualKeys) const {
    outVirtualKeys.clear();

    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    if (device != nullptr && device->virtualKeyMap) {
        const std::vector<VirtualKeyDefinition> virtualKeys =
@@ -752,7 +752,7 @@ void EventHub::getVirtualKeyDefinitions(int32_t deviceId,
}

const std::shared_ptr<KeyCharacterMap> EventHub::getKeyCharacterMap(int32_t deviceId) const {
    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    if (device != nullptr) {
        return device->getKeyCharacterMap();
@@ -761,7 +761,7 @@ const std::shared_ptr<KeyCharacterMap> EventHub::getKeyCharacterMap(int32_t devi
}

bool EventHub::setKeyboardLayoutOverlay(int32_t deviceId, std::shared_ptr<KeyCharacterMap> map) {
    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    if (device != nullptr && map != nullptr && device->keyMap.keyCharacterMap != nullptr) {
        device->keyMap.keyCharacterMap->combine(*map);
@@ -822,7 +822,7 @@ void EventHub::assignDescriptorLocked(InputDeviceIdentifier& identifier) {
}

void EventHub::vibrate(int32_t deviceId, const VibrationElement& element) {
    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    if (device != nullptr && device->hasValidFd()) {
        ff_effect effect;
@@ -857,7 +857,7 @@ void EventHub::vibrate(int32_t deviceId, const VibrationElement& element) {
}

void EventHub::cancelVibrate(int32_t deviceId) {
    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    if (device != nullptr && device->hasValidFd()) {
        if (device->ffEffectPlaying) {
@@ -878,6 +878,18 @@ void EventHub::cancelVibrate(int32_t deviceId) {
    }
}

std::vector<int32_t> EventHub::getVibratorIds(int32_t deviceId) {
    std::scoped_lock _l(mLock);
    std::vector<int32_t> vibrators;
    Device* device = getDeviceLocked(deviceId);
    if (device != nullptr && device->hasValidFd() &&
        device->classes.test(InputDeviceClass::VIBRATOR)) {
        vibrators.push_back(FF_STRONG_MAGNITUDE_CHANNEL_IDX);
        vibrators.push_back(FF_WEAK_MAGNITUDE_CHANNEL_IDX);
    }
    return vibrators;
}

EventHub::Device* EventHub::getDeviceByDescriptorLocked(const std::string& descriptor) const {
    for (const auto& [id, device] : mDevices) {
        if (descriptor == device->identifier.descriptor) {
@@ -930,7 +942,7 @@ EventHub::Device* EventHub::getDeviceByFdLocked(int fd) const {
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
    ALOG_ASSERT(bufferSize >= 1);

    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);

    struct input_event readBuffer[bufferSize];

@@ -1184,7 +1196,7 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz
}

std::vector<TouchVideoFrame> EventHub::getVideoFrames(int32_t deviceId) {
    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);

    Device* device = getDeviceLocked(deviceId);
    if (device == nullptr || !device->videoDevice) {
@@ -1593,7 +1605,7 @@ bool EventHub::tryAddVideoDevice(EventHub::Device& device,
}

bool EventHub::isDeviceEnabled(int32_t deviceId) {
    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    if (device == nullptr) {
        ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
@@ -1603,7 +1615,7 @@ bool EventHub::isDeviceEnabled(int32_t deviceId) {
}

status_t EventHub::enableDevice(int32_t deviceId) {
    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    if (device == nullptr) {
        ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
@@ -1625,7 +1637,7 @@ status_t EventHub::enableDevice(int32_t deviceId) {
}

status_t EventHub::disableDevice(int32_t deviceId) {
    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    if (device == nullptr) {
        ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
@@ -1809,7 +1821,7 @@ status_t EventHub::scanVideoDirLocked(const std::string& dirname) {
void EventHub::requestReopenDevices() {
    ALOGV("requestReopenDevices() called");

    std::lock_guard<std::mutex> lock(mLock);
    std::scoped_lock _l(mLock);
    mNeedToReopenDevices = true;
}

@@ -1817,7 +1829,7 @@ void EventHub::dump(std::string& dump) {
    dump += "Event Hub State:\n";

    { // acquire lock
        std::lock_guard<std::mutex> lock(mLock);
        std::scoped_lock _l(mLock);

        dump += StringPrintf(INDENT "BuiltInKeyboardId: %d\n", mBuiltInKeyboardId);

+24 −4
Original line number Diff line number Diff line
@@ -429,10 +429,9 @@ bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
    return result;
}

void InputDevice::vibrate(const std::vector<VibrationElement>& pattern, ssize_t repeat,
                          int32_t token) {
    for_each_mapper([pattern, repeat, token](InputMapper& mapper) {
        mapper.vibrate(pattern, repeat, token);
void InputDevice::vibrate(const VibrationSequence& sequence, ssize_t repeat, int32_t token) {
    for_each_mapper([sequence, repeat, token](InputMapper& mapper) {
        mapper.vibrate(sequence, repeat, token);
    });
}

@@ -440,6 +439,27 @@ void InputDevice::cancelVibrate(int32_t token) {
    for_each_mapper([token](InputMapper& mapper) { mapper.cancelVibrate(token); });
}

bool InputDevice::isVibrating() {
    bool vibrating = false;
    for_each_mapper([&vibrating](InputMapper& mapper) { vibrating |= mapper.isVibrating(); });
    return vibrating;
}

/* There's no guarantee the IDs provided by the different mappers are unique, so if we have two
 * different vibration mappers then we could have duplicate IDs.
 * Alternatively, if we have a merged device that has multiple evdev nodes with FF_* capabilities,
 * we would definitely have duplicate IDs.
 */
std::vector<int32_t> InputDevice::getVibratorIds() {
    std::vector<int32_t> vibrators;
    for_each_mapper([&vibrators](InputMapper& mapper) {
        std::vector<int32_t> devVibs = mapper.getVibratorIds();
        vibrators.reserve(vibrators.size() + devVibs.size());
        vibrators.insert(vibrators.end(), devVibs.begin(), devVibs.end());
    });
    return vibrators;
}

void InputDevice::cancelTouch(nsecs_t when) {
    for_each_mapper([when](InputMapper& mapper) { mapper.cancelTouch(when); });
}
Loading