From 0e465792b0f7e4537197216948d00c4ef841cb4f Mon Sep 17 00:00:00 2001 From: Ravi Jain Date: Mon, 26 Feb 2024 08:42:35 +0000 Subject: [PATCH 01/15] cs40l26: Align Felix Hal with common HAL Pull DSPMemChunk related CLs from common HAL. ag/22087481, ag/22093662 Bug: 322648133 Test: idlcli compose commands Test: adb shell cmd vibrator_manager synced prebaked 1 Test: adb shell idlcli vibrator composePwle -b \ a 0.1 300.0 0.1 30.0 1000 \ a 0.1 30.0 0.1 300.0 500 Test: atest PtsVibratorHalTestSuite \ PtsHapticsTestCases \ VibratorHalCs40l26TestSuite \ VtsHalVibratorManagerTargetTest \ VtsHalVibratorTargetTest \ android.os.cts.VibratorTest \ android.os.cts.VibratorManagerTest \ android.os.cts.VibrationEffectTest \ android.os.cts.VibrationAttributesTest \ android.os.cts.CombinedVibrationTest (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:85299be2adc9e3dec373dc48f321c4fa1930e260) Merged-In: I32258500ec02c2a8cbfc6d0b37aaea2c83c7c8b4 Change-Id: I32258500ec02c2a8cbfc6d0b37aaea2c83c7c8b4 --- vibrator/cs40l26/Hardware.h | 6 +- vibrator/cs40l26/Vibrator.cpp | 462 ++++++++++++++++++--------------- vibrator/cs40l26/Vibrator.h | 8 +- vibrator/cs40l26/tests/mocks.h | 2 +- 4 files changed, 268 insertions(+), 210 deletions(-) diff --git a/vibrator/cs40l26/Hardware.h b/vibrator/cs40l26/Hardware.h index 22667c9..af8d120 100644 --- a/vibrator/cs40l26/Hardware.h +++ b/vibrator/cs40l26/Hardware.h @@ -184,7 +184,7 @@ class HwApi : public Vibrator::HwApi, private HwApiBase { *haptic_pcm = NULL; return false; } - bool uploadOwtEffect(int fd, uint8_t *owtData, uint32_t numBytes, struct ff_effect *effect, + bool uploadOwtEffect(int fd, const uint8_t *owtData, const uint32_t numBytes, struct ff_effect *effect, uint32_t *outEffectIndex, int *status) override { (*effect).u.periodic.custom_len = numBytes / sizeof(uint16_t); delete[] ((*effect).u.periodic.custom_data); @@ -225,6 +225,10 @@ class HwApi : public Vibrator::HwApi, private HwApiBase { ALOGE("Invalid waveform index for OWT erase: %d", effectIndex); return false; } + if (effect == nullptr || (*effect).empty()) { + ALOGE("Invalid argument effect"); + return false; + } // Turn off the waiting time for SVC init phase to complete since chip // should already under STOP state setMinOnOffInterval(0); diff --git a/vibrator/cs40l26/Vibrator.cpp b/vibrator/cs40l26/Vibrator.cpp index bfb7cf1..2abe72e 100644 --- a/vibrator/cs40l26/Vibrator.cpp +++ b/vibrator/cs40l26/Vibrator.cpp @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #ifndef ARRAY_SIZE @@ -85,7 +87,7 @@ static constexpr uint8_t PWLE_AMP_REG_BIT = 0x2; static constexpr float PWLE_LEVEL_MIN = 0.0; static constexpr float PWLE_LEVEL_MAX = 1.0; -static constexpr float CS40L26_PWLE_LEVEL_MIX = -1.0; +static constexpr float CS40L26_PWLE_LEVEL_MIN = -1.0; static constexpr float CS40L26_PWLE_LEVEL_MAX = 0.9995118; static constexpr float PWLE_FREQUENCY_RESOLUTION_HZ = 1.00; static constexpr float PWLE_FREQUENCY_MIN_HZ = 1.00; @@ -157,79 +159,210 @@ enum vibe_state { VIBE_STATE_ASP, }; -static int min(int x, int y) { - return x < y ? x : y; -} +class DspMemChunk { + private: + std::unique_ptr head; + size_t bytes = 0; + uint8_t waveformType; + uint8_t *_current; + const uint8_t *_max; + uint32_t _cache = 0; + int _cachebits = 0; -static int floatToUint16(float input, uint16_t *output, float scale, float min, float max) { - if (input < min || input > max) - return -ERANGE; + bool isEnd() const { return _current == _max; } + int min(int x, int y) { return x < y ? x : y; } - *output = roundf(input * scale); - return 0; -} + int write(int nbits, uint32_t val) { + int nwrite, i; -struct dspmem_chunk { - uint8_t *head; - uint8_t *current; - uint8_t *max; - int bytes; + nwrite = min(24 - _cachebits, nbits); + _cache <<= nwrite; + _cache |= val >> (nbits - nwrite); + _cachebits += nwrite; + nbits -= nwrite; - uint32_t cache; - int cachebits; -}; + if (_cachebits == 24) { + if (isEnd()) + return -ENOSPC; -static dspmem_chunk *dspmem_chunk_create(void *data, int size) { - auto ch = new dspmem_chunk{ - .head = reinterpret_cast(data), - .current = reinterpret_cast(data), - .max = reinterpret_cast(data) + size, - }; + _cache &= 0xFFFFFF; + for (i = 0; i < sizeof(_cache); i++, _cache <<= 8) + *_current++ = (_cache & 0xFF000000) >> 24; - return ch; -} + bytes += sizeof(_cache); + _cachebits = 0; + } -static bool dspmem_chunk_end(struct dspmem_chunk *ch) { - return ch->current == ch->max; -} + if (nbits) + return write(nbits, val); -static int dspmem_chunk_bytes(struct dspmem_chunk *ch) { - return ch->bytes; -} - -static int dspmem_chunk_write(struct dspmem_chunk *ch, int nbits, uint32_t val) { - int nwrite, i; - - nwrite = min(24 - ch->cachebits, nbits); - ch->cache <<= nwrite; - ch->cache |= val >> (nbits - nwrite); - ch->cachebits += nwrite; - nbits -= nwrite; - - if (ch->cachebits == 24) { - if (dspmem_chunk_end(ch)) - return -ENOSPC; - - ch->cache &= 0xFFFFFF; - for (i = 0; i < sizeof(ch->cache); i++, ch->cache <<= 8) - *ch->current++ = (ch->cache & 0xFF000000) >> 24; - - ch->bytes += sizeof(ch->cache); - ch->cachebits = 0; + return 0; } - if (nbits) - return dspmem_chunk_write(ch, nbits, val); + int fToU16(float input, uint16_t *output, float scale, float min, float max) { + if (input < min || input > max) + return -ERANGE; - return 0; -} - -static int dspmem_chunk_flush(struct dspmem_chunk *ch) { - if (!ch->cachebits) + *output = roundf(input * scale); return 0; + } - return dspmem_chunk_write(ch, 24 - ch->cachebits, 0); -} + void constructPwleSegment(uint16_t delay, uint16_t amplitude, uint16_t frequency, uint8_t flags, + uint32_t vbemfTarget = 0) { + write(16, delay); + write(12, amplitude); + write(12, frequency); + /* feature flags to control the chirp, CLAB braking, back EMF amplitude regulation */ + write(8, (flags | 1) << 4); + if (flags & PWLE_AMP_REG_BIT) { + write(24, vbemfTarget); /* target back EMF voltage */ + } + } + + public: + uint8_t *front() const { return head.get(); } + uint8_t type() const { return waveformType; } + size_t size() const { return bytes; } + + DspMemChunk(uint8_t type, size_t size) : head(new uint8_t[size]{0x00}) { + waveformType = type; + _current = head.get(); + _max = _current + size; + + if (waveformType == WAVEFORM_COMPOSE) { + write(8, 0); /* Padding */ + write(8, 0); /* nsections placeholder */ + write(8, 0); /* repeat */ + } else if (waveformType == WAVEFORM_PWLE) { + write(24, 0); /* Waveform length placeholder */ + write(8, 0); /* Repeat */ + write(12, 0); /* Wait time between repeats */ + write(8, 0); /* nsections placeholder */ + } else { + ALOGE("%s: Invalid type: %u", __func__, waveformType); + } + } + + int flush() { + if (!_cachebits) + return 0; + + return write(24 - _cachebits, 0); + } + + int constructComposeSegment(uint32_t effectVolLevel, uint32_t effectIndex, uint8_t repeat, + uint8_t flags, uint16_t nextEffectDelay) { + if (waveformType != WAVEFORM_COMPOSE) { + ALOGE("%s: Invalid type: %d", __func__, waveformType); + return -EDOM; + } + if (effectVolLevel > 100 || effectIndex > WAVEFORM_MAX_PHYSICAL_INDEX) { + ALOGE("%s: Invalid argument: %u, %u", __func__, effectVolLevel, effectIndex); + return -EINVAL; + } + write(8, effectVolLevel); /* amplitude */ + write(8, effectIndex); /* index */ + write(8, repeat); /* repeat */ + write(8, flags); /* flags */ + write(16, nextEffectDelay); /* delay */ + return 0; + } + + int constructActiveSegment(int duration, float amplitude, float frequency, bool chirp) { + uint16_t delay = 0; + uint16_t amp = 0; + uint16_t freq = 0; + uint8_t flags = 0x0; + if (waveformType != WAVEFORM_PWLE) { + ALOGE("%s: Invalid type: %d", __func__, waveformType); + return -EDOM; + } + if ((fToU16(duration, &delay, 4, 0.0f, COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) < 0) || + (fToU16(amplitude, &, 2048, CS40L26_PWLE_LEVEL_MIN, CS40L26_PWLE_LEVEL_MAX) < 0) || + (fToU16(frequency, &freq, 4, PWLE_FREQUENCY_MIN_HZ, PWLE_FREQUENCY_MAX_HZ) < 0)) { + ALOGE("%s: Invalid argument: %d, %f, %f", __func__, duration, amplitude, frequency); + return -ERANGE; + } + if (chirp) { + flags |= PWLE_CHIRP_BIT; + } + constructPwleSegment(delay, amp, freq, flags, 0 /*ignored*/); + return 0; + } + + int constructBrakingSegment(int duration, Braking brakingType) { + uint16_t delay = 0; + uint16_t freq = 0; + uint8_t flags = 0x00; + if (waveformType != WAVEFORM_PWLE) { + ALOGE("%s: Invalid type: %d", __func__, waveformType); + return -EDOM; + } + if (fToU16(duration, &delay, 4, 0.0f, COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) < 0) { + ALOGE("%s: Invalid argument: %d", __func__, duration); + return -ERANGE; + } + fToU16(PWLE_FREQUENCY_MIN_HZ, &freq, 4, PWLE_FREQUENCY_MIN_HZ, PWLE_FREQUENCY_MAX_HZ); + if (static_cast::type>(brakingType)) { + flags |= PWLE_BRAKE_BIT; + } + + constructPwleSegment(delay, 0 /*ignored*/, freq, flags, 0 /*ignored*/); + return 0; + } + + int updateWLength(uint32_t totalDuration) { + uint8_t *f = front(); + if (f == nullptr) { + ALOGE("%s: head does not exist!", __func__); + return -ENOMEM; + } + if (waveformType != WAVEFORM_PWLE) { + ALOGE("%s: Invalid type: %d", __func__, waveformType); + return -EDOM; + } + if (totalDuration > 0x7FFFF) { + ALOGE("%s: Invalid argument: %u", __func__, totalDuration); + return -EINVAL; + } + totalDuration *= 8; /* Unit: 0.125 ms (since wlength played @ 8kHz). */ + totalDuration |= + WT_LEN_CALCD; /* Bit 23 is for WT_LEN_CALCD; Bit 22 is for WT_INDEFINITE. */ + *(f + 0) = (totalDuration >> 24) & 0xFF; + *(f + 1) = (totalDuration >> 16) & 0xFF; + *(f + 2) = (totalDuration >> 8) & 0xFF; + *(f + 3) = totalDuration & 0xFF; + return 0; + } + + int updateNSection(int segmentIdx) { + uint8_t *f = front(); + if (f == nullptr) { + ALOGE("%s: head does not exist!", __func__); + return -ENOMEM; + } + + if (waveformType == WAVEFORM_COMPOSE) { + if (segmentIdx > COMPOSE_SIZE_MAX + 1 /*1st effect may have a delay*/) { + ALOGE("%s: Invalid argument: %d", __func__, segmentIdx); + return -EINVAL; + } + *(f + 2) = (0xFF & segmentIdx); + } else if (waveformType == WAVEFORM_PWLE) { + if (segmentIdx > COMPOSE_PWLE_SIZE_MAX_DEFAULT) { + ALOGE("%s: Invalid argument: %d", __func__, segmentIdx); + return -EINVAL; + } + *(f + 7) |= (0xF0 & segmentIdx) >> 4; /* Bit 4 to 7 */ + *(f + 9) |= (0x0F & segmentIdx) << 4; /* Bit 3 to 0 */ + } else { + ALOGE("%s: Invalid type: %d", __func__, waveformType); + return -EDOM; + } + + return 0; + } +}; Vibrator::Vibrator(std::unique_ptr hwApiDefault, std::unique_ptr hwCalDefault, std::unique_ptr hwApiDual, std::unique_ptr hwCalDual, @@ -718,9 +851,6 @@ ndk::ScopedAStatus Vibrator::compose(const std::vector &composi uint16_t nextEffectDelay; uint16_t totalDuration = 0; - auto ch = dspmem_chunk_create(new uint8_t[FF_CUSTOM_DATA_LEN_MAX_COMP]{0x00}, - FF_CUSTOM_DATA_LEN_MAX_COMP); - if (composite.size() > COMPOSE_SIZE_MAX || composite.empty()) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } @@ -736,15 +866,13 @@ ndk::ScopedAStatus Vibrator::compose(const std::vector &composi size = composite.size(); } - dspmem_chunk_write(ch, 8, 0); /* Padding */ - dspmem_chunk_write(ch, 8, (uint8_t)(0xFF & size)); /* nsections */ - dspmem_chunk_write(ch, 8, 0); /* repeat */ - uint8_t header_count = dspmem_chunk_bytes(ch); + DspMemChunk ch(WAVEFORM_COMPOSE, FF_CUSTOM_DATA_LEN_MAX_COMP); + const uint8_t header_count = ch.size(); /* Insert 1 section for a wait before the first effect. */ if (nextEffectDelay) { - dspmem_chunk_write(ch, 32, 0); /* amplitude, index, repeat & flags */ - dspmem_chunk_write(ch, 16, (uint16_t)(0xFFFF & nextEffectDelay)); /* delay */ + ch.constructComposeSegment(0 /*amplitude*/, 0 /*index*/, 0 /*repeat*/, 0 /*flags*/, + nextEffectDelay /*delay*/); } for (uint32_t i_curr = 0, i_next = 1; i_curr < composite.size(); i_curr++, i_next++) { @@ -791,14 +919,16 @@ ndk::ScopedAStatus Vibrator::compose(const std::vector &composi return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } - dspmem_chunk_write(ch, 8, (uint8_t)(0xFF & effectVolLevel)); /* amplitude */ - dspmem_chunk_write(ch, 8, (uint8_t)(0xFF & effectIndex)); /* index */ - dspmem_chunk_write(ch, 8, 0); /* repeat */ - dspmem_chunk_write(ch, 8, 0); /* flags */ - dspmem_chunk_write(ch, 16, (uint16_t)(0xFFFF & nextEffectDelay)); /* delay */ + ch.constructComposeSegment(effectVolLevel, effectIndex, 0 /*repeat*/, 0 /*flags*/, + nextEffectDelay /*delay*/); } - dspmem_chunk_flush(ch); - if (header_count == dspmem_chunk_bytes(ch)) { + + ch.flush(); + if (ch.updateNSection(size) < 0) { + ALOGE("%s: Failed to update the section count", __func__); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + if (header_count == ch.size()) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } else { // Composition duration should be 0 to allow firmware to play the whole effect @@ -806,12 +936,12 @@ ndk::ScopedAStatus Vibrator::compose(const std::vector &composi if (mIsDual) { mFfEffectsDual[WAVEFORM_COMPOSE].replay.length = 0; } - return performEffect(WAVEFORM_MAX_INDEX /*ignored*/, VOLTAGE_SCALE_MAX /*ignored*/, ch, + return performEffect(WAVEFORM_MAX_INDEX /*ignored*/, VOLTAGE_SCALE_MAX /*ignored*/, &ch, callback); } } -ndk::ScopedAStatus Vibrator::on(uint32_t timeoutMs, uint32_t effectIndex, dspmem_chunk *ch, +ndk::ScopedAStatus Vibrator::on(uint32_t timeoutMs, uint32_t effectIndex, const DspMemChunk *ch, const std::shared_ptr &callback) { ndk::ScopedAStatus status = ndk::ScopedAStatus::ok(); @@ -826,28 +956,28 @@ ndk::ScopedAStatus Vibrator::on(uint32_t timeoutMs, uint32_t effectIndex, dspmem if (ch) { /* Upload OWT effect. */ - if (ch->head == nullptr) { + if (ch->front() == nullptr) { ALOGE("Invalid OWT bank"); - delete ch; return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } - bool isPwle = (*reinterpret_cast(ch->head) != 0x0000); - effectIndex = isPwle ? WAVEFORM_PWLE : WAVEFORM_COMPOSE; + + if (ch->type() != WAVEFORM_PWLE && ch->type() != WAVEFORM_COMPOSE) { + ALOGE("Invalid OWT type"); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + effectIndex = ch->type(); uint32_t freeBytes; mHwApiDef->getOwtFreeSpace(&freeBytes); - if (dspmem_chunk_bytes(ch) > freeBytes) { - ALOGE("Invalid OWT length: Effect %d: %d > %d!", effectIndex, dspmem_chunk_bytes(ch), - freeBytes); - delete ch; + if (ch->size() > freeBytes) { + ALOGE("Invalid OWT length: Effect %d: %zu > %d!", effectIndex, ch->size(), freeBytes); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } if (mIsDual) { mHwApiDual->getOwtFreeSpace(&freeBytes); - if (dspmem_chunk_bytes(ch) > freeBytes) { + if (ch-> size() > freeBytes) { ALOGE("Invalid OWT length in flip: Effect %d: %d > %d!", effectIndex, - dspmem_chunk_bytes(ch), freeBytes); - delete ch; + ch-> size(), freeBytes); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } } @@ -860,20 +990,17 @@ ndk::ScopedAStatus Vibrator::on(uint32_t timeoutMs, uint32_t effectIndex, dspmem ALOGD("Not dual haptics HAL and GPIO status fail"); } - if (!mHwApiDef->uploadOwtEffect(mInputFd, ch->head, dspmem_chunk_bytes(ch), - &mFfEffects[effectIndex], &effectIndex, &errorStatus)) { - delete ch; + if (!mHwApiDef->uploadOwtEffect(mInputFd, ch->front(), ch->size(), &mFfEffects[effectIndex], + &effectIndex, &errorStatus)) { ALOGE("Invalid uploadOwtEffect"); return ndk::ScopedAStatus::fromExceptionCode(errorStatus); } - if (mIsDual && !mHwApiDual->uploadOwtEffect(mInputFdDual, ch->head, dspmem_chunk_bytes(ch), + if (mIsDual && !mHwApiDual->uploadOwtEffect(mInputFdDual, ch->front(), ch->size(), &mFfEffectsDual[effectIndex], &effectIndex, &errorStatus)) { - delete ch; ALOGE("Invalid uploadOwtEffect in flip"); return ndk::ScopedAStatus::fromExceptionCode(errorStatus); } - delete ch; } else if (effectIndex == WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX || effectIndex == WAVEFORM_LONG_VIBRATION_EFFECT_INDEX) { @@ -1090,69 +1217,6 @@ static void incrementIndex(int *index) { *index += 1; } -static void constructPwleSegment(dspmem_chunk *ch, uint16_t delay, uint16_t amplitude, - uint16_t frequency, uint8_t flags, uint32_t vbemfTarget = 0) { - dspmem_chunk_write(ch, 16, delay); - dspmem_chunk_write(ch, 12, amplitude); - dspmem_chunk_write(ch, 12, frequency); - /* feature flags to control the chirp, CLAB braking, back EMF amplitude regulation */ - dspmem_chunk_write(ch, 8, (flags | 1) << 4); - if (flags & PWLE_AMP_REG_BIT) { - dspmem_chunk_write(ch, 24, vbemfTarget); /* target back EMF voltage */ - } -} - -static int constructActiveSegment(dspmem_chunk *ch, int duration, float amplitude, float frequency, - bool chirp) { - uint16_t delay = 0; - uint16_t amp = 0; - uint16_t freq = 0; - uint8_t flags = 0x0; - if ((floatToUint16(duration, &delay, 4, 0.0f, COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) < 0) || - (floatToUint16(amplitude, &, 2048, CS40L26_PWLE_LEVEL_MIX, CS40L26_PWLE_LEVEL_MAX) < - 0) || - (floatToUint16(frequency, &freq, 4, PWLE_FREQUENCY_MIN_HZ, PWLE_FREQUENCY_MAX_HZ) < 0)) { - ALOGE("Invalid argument: %d, %f, %f", duration, amplitude, frequency); - return -ERANGE; - } - if (chirp) { - flags |= PWLE_CHIRP_BIT; - } - constructPwleSegment(ch, delay, amp, freq, flags, 0 /*ignored*/); - return 0; -} - -static int constructBrakingSegment(dspmem_chunk *ch, int duration, Braking brakingType) { - uint16_t delay = 0; - uint16_t freq = 0; - uint8_t flags = 0x00; - if (floatToUint16(duration, &delay, 4, 0.0f, COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) < 0) { - ALOGE("Invalid argument: %d", duration); - return -ERANGE; - } - floatToUint16(PWLE_FREQUENCY_MIN_HZ, &freq, 4, PWLE_FREQUENCY_MIN_HZ, PWLE_FREQUENCY_MAX_HZ); - if (static_cast::type>(brakingType)) { - flags |= PWLE_BRAKE_BIT; - } - - constructPwleSegment(ch, delay, 0 /*ignored*/, freq, flags, 0 /*ignored*/); - return 0; -} - -static void updateWLength(dspmem_chunk *ch, uint32_t totalDuration) { - totalDuration *= 8; /* Unit: 0.125 ms (since wlength played @ 8kHz). */ - totalDuration |= WT_LEN_CALCD; /* Bit 23 is for WT_LEN_CALCD; Bit 22 is for WT_INDEFINITE. */ - *(ch->head + 0) = (totalDuration >> 24) & 0xFF; - *(ch->head + 1) = (totalDuration >> 16) & 0xFF; - *(ch->head + 2) = (totalDuration >> 8) & 0xFF; - *(ch->head + 3) = totalDuration & 0xFF; -} - -static void updateNSection(dspmem_chunk *ch, int segmentIdx) { - *(ch->head + 7) |= (0xF0 & segmentIdx) >> 4; /* Bit 4 to 7 */ - *(ch->head + 9) |= (0x0F & segmentIdx) << 4; /* Bit 3 to 0 */ -} - ndk::ScopedAStatus Vibrator::composePwle(const std::vector &composite, const std::shared_ptr &callback) { ATRACE_NAME("Vibrator::composePwle"); @@ -1177,15 +1241,9 @@ ndk::ScopedAStatus Vibrator::composePwle(const std::vector &compo float prevEndAmplitude; float prevEndFrequency; resetPreviousEndAmplitudeEndFrequency(&prevEndAmplitude, &prevEndFrequency); - auto ch = dspmem_chunk_create(new uint8_t[FF_CUSTOM_DATA_LEN_MAX_PWLE]{0x00}, - FF_CUSTOM_DATA_LEN_MAX_PWLE); + DspMemChunk ch(WAVEFORM_PWLE, FF_CUSTOM_DATA_LEN_MAX_PWLE); bool chirp = false; - dspmem_chunk_write(ch, 24, 0x000000); /* Waveform length placeholder */ - dspmem_chunk_write(ch, 8, 0); /* Repeat */ - dspmem_chunk_write(ch, 12, 0); /* Wait time between repeats */ - dspmem_chunk_write(ch, 8, 0x00); /* nsections placeholder */ - for (auto &e : composite) { switch (e.getTag()) { case PrimitivePwle::active: { @@ -1215,8 +1273,8 @@ ndk::ScopedAStatus Vibrator::composePwle(const std::vector &compo if (!((active.startAmplitude == prevEndAmplitude) && (active.startFrequency == prevEndFrequency))) { - if (constructActiveSegment(ch, 0, active.startAmplitude, active.startFrequency, - false) < 0) { + if (ch.constructActiveSegment(0, active.startAmplitude, active.startFrequency, + false) < 0) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } incrementIndex(&segmentIdx); @@ -1225,8 +1283,8 @@ ndk::ScopedAStatus Vibrator::composePwle(const std::vector &compo if (active.startFrequency != active.endFrequency) { chirp = true; } - if (constructActiveSegment(ch, active.duration, active.endAmplitude, - active.endFrequency, chirp) < 0) { + if (ch.constructActiveSegment(active.duration, active.endAmplitude, + active.endFrequency, chirp) < 0) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } incrementIndex(&segmentIdx); @@ -1249,12 +1307,12 @@ ndk::ScopedAStatus Vibrator::composePwle(const std::vector &compo return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } - if (constructBrakingSegment(ch, 0, braking.braking) < 0) { + if (ch.constructBrakingSegment(0, braking.braking) < 0) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } incrementIndex(&segmentIdx); - if (constructBrakingSegment(ch, braking.duration, braking.braking) < 0) { + if (ch.constructBrakingSegment(braking.duration, braking.braking) < 0) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } incrementIndex(&segmentIdx); @@ -1270,7 +1328,7 @@ ndk::ScopedAStatus Vibrator::composePwle(const std::vector &compo return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } } - dspmem_chunk_flush(ch); + ch.flush(); /* Update wlength */ totalDuration += MAX_COLD_START_LATENCY_MS; @@ -1278,12 +1336,19 @@ ndk::ScopedAStatus Vibrator::composePwle(const std::vector &compo ALOGE("Total duration is too long (%d)!", totalDuration); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } - updateWLength(ch, totalDuration); + + if (ch.updateWLength(totalDuration) < 0) { + ALOGE("%s: Failed to update the waveform length length", __func__); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } /* Update nsections */ - updateNSection(ch, segmentIdx); + if (ch.updateNSection(segmentIdx) < 0) { + ALOGE("%s: Failed to update the section count", __func__); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } - return performEffect(WAVEFORM_MAX_INDEX /*ignored*/, VOLTAGE_SCALE_MAX /*ignored*/, ch, + return performEffect(WAVEFORM_MAX_INDEX /*ignored*/, VOLTAGE_SCALE_MAX /*ignored*/, &ch, callback); } @@ -1460,7 +1525,7 @@ ndk::ScopedAStatus Vibrator::getSimpleDetails(Effect effect, EffectStrength stre } ndk::ScopedAStatus Vibrator::getCompoundDetails(Effect effect, EffectStrength strength, - uint32_t *outTimeMs, dspmem_chunk *outCh) { + uint32_t *outTimeMs, DspMemChunk *outCh) { ndk::ScopedAStatus status; uint32_t timeMs = 0; uint32_t thisEffectIndex; @@ -1468,23 +1533,14 @@ ndk::ScopedAStatus Vibrator::getCompoundDetails(Effect effect, EffectStrength st uint32_t thisVolLevel; switch (effect) { case Effect::DOUBLE_CLICK: - dspmem_chunk_write(outCh, 8, 0); /* Padding */ - dspmem_chunk_write(outCh, 8, 2); /* nsections */ - dspmem_chunk_write(outCh, 8, 0); /* repeat */ - status = getSimpleDetails(Effect::CLICK, strength, &thisEffectIndex, &thisTimeMs, &thisVolLevel); if (!status.isOk()) { return status; } timeMs += thisTimeMs; - - dspmem_chunk_write(outCh, 8, (uint8_t)(0xFF & thisVolLevel)); /* amplitude */ - dspmem_chunk_write(outCh, 8, (uint8_t)(0xFF & thisEffectIndex)); /* index */ - dspmem_chunk_write(outCh, 8, 0); /* repeat */ - dspmem_chunk_write(outCh, 8, 0); /* flags */ - dspmem_chunk_write(outCh, 16, - (uint16_t)(0xFFFF & WAVEFORM_DOUBLE_CLICK_SILENCE_MS)); /* delay */ + outCh->constructComposeSegment(thisVolLevel, thisEffectIndex, 0 /*repeat*/, 0 /*flags*/, + WAVEFORM_DOUBLE_CLICK_SILENCE_MS); timeMs += WAVEFORM_DOUBLE_CLICK_SILENCE_MS + MAX_PAUSE_TIMING_ERROR_MS; @@ -1495,12 +1551,13 @@ ndk::ScopedAStatus Vibrator::getCompoundDetails(Effect effect, EffectStrength st } timeMs += thisTimeMs; - dspmem_chunk_write(outCh, 8, (uint8_t)(0xFF & thisVolLevel)); /* amplitude */ - dspmem_chunk_write(outCh, 8, (uint8_t)(0xFF & thisEffectIndex)); /* index */ - dspmem_chunk_write(outCh, 8, 0); /* repeat */ - dspmem_chunk_write(outCh, 8, 0); /* flags */ - dspmem_chunk_write(outCh, 16, 0); /* delay */ - dspmem_chunk_flush(outCh); + outCh->constructComposeSegment(thisVolLevel, thisEffectIndex, 0 /*repeat*/, 0 /*flags*/, + 0 /*delay*/); + outCh->flush(); + if (outCh->updateNSection(2) < 0) { + ALOGE("%s: Failed to update the section count", __func__); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } break; default: @@ -1568,7 +1625,7 @@ ndk::ScopedAStatus Vibrator::performEffect(Effect effect, EffectStrength strengt uint32_t effectIndex; uint32_t timeMs = 0; uint32_t volLevel; - dspmem_chunk *ch = nullptr; + std::optional maybeCh; switch (effect) { case Effect::TEXTURE_TICK: // fall-through @@ -1580,28 +1637,25 @@ ndk::ScopedAStatus Vibrator::performEffect(Effect effect, EffectStrength strengt status = getSimpleDetails(effect, strength, &effectIndex, &timeMs, &volLevel); break; case Effect::DOUBLE_CLICK: - ch = dspmem_chunk_create(new uint8_t[FF_CUSTOM_DATA_LEN_MAX_COMP]{0x00}, - FF_CUSTOM_DATA_LEN_MAX_COMP); - status = getCompoundDetails(effect, strength, &timeMs, ch); + maybeCh.emplace(WAVEFORM_COMPOSE, FF_CUSTOM_DATA_LEN_MAX_COMP); + status = getCompoundDetails(effect, strength, &timeMs, &*maybeCh); volLevel = VOLTAGE_SCALE_MAX; break; default: status = ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); break; } - if (!status.isOk()) { - goto exit; + if (status.isOk()) { + DspMemChunk *ch = maybeCh ? &*maybeCh : nullptr; + status = performEffect(effectIndex, volLevel, ch, callback); } - status = performEffect(effectIndex, volLevel, ch, callback); - -exit: *outTimeMs = timeMs; return status; } ndk::ScopedAStatus Vibrator::performEffect(uint32_t effectIndex, uint32_t volLevel, - dspmem_chunk *ch, + const DspMemChunk *ch, const std::shared_ptr &callback) { setEffectAmplitude(volLevel, VOLTAGE_SCALE_MAX); diff --git a/vibrator/cs40l26/Vibrator.h b/vibrator/cs40l26/Vibrator.h index 5b1ff90..06bd6e5 100644 --- a/vibrator/cs40l26/Vibrator.h +++ b/vibrator/cs40l26/Vibrator.h @@ -89,7 +89,7 @@ class Vibrator : public BnVibrator { virtual bool setHapticPcmAmp(struct pcm **haptic_pcm, bool enable, int card, int device) = 0; // Set OWT waveform for compose or compose PWLE request - virtual bool uploadOwtEffect(int fd, uint8_t *owtData, uint32_t numBytes, + virtual bool uploadOwtEffect(int fd, const uint8_t *owtData, const uint32_t numBytes, struct ff_effect *effect, uint32_t *outEffectIndex, int *status) = 0; // Erase OWT waveform @@ -178,7 +178,7 @@ class Vibrator : public BnVibrator { static constexpr uint32_t MIN_ON_OFF_INTERVAL_US = 8500; // SVC initialization time private: - ndk::ScopedAStatus on(uint32_t timeoutMs, uint32_t effectIndex, struct dspmem_chunk *ch, + ndk::ScopedAStatus on(uint32_t timeoutMs, uint32_t effectIndex, const class DspMemChunk *ch, const std::shared_ptr &callback); // set 'amplitude' based on an arbitrary scale determined by 'maximum' ndk::ScopedAStatus setEffectAmplitude(float amplitude, float maximum); @@ -189,13 +189,13 @@ class Vibrator : public BnVibrator { uint32_t *outVolLevel); // 'compound' effects are those composed by stringing multiple 'simple' effects ndk::ScopedAStatus getCompoundDetails(Effect effect, EffectStrength strength, - uint32_t *outTimeMs, struct dspmem_chunk *outCh); + uint32_t *outTimeMs, class DspMemChunk *outCh); ndk::ScopedAStatus getPrimitiveDetails(CompositePrimitive primitive, uint32_t *outEffectIndex); ndk::ScopedAStatus performEffect(Effect effect, EffectStrength strength, const std::shared_ptr &callback, int32_t *outTimeMs); ndk::ScopedAStatus performEffect(uint32_t effectIndex, uint32_t volLevel, - struct dspmem_chunk *ch, + const class DspMemChunk *ch, const std::shared_ptr &callback); ndk::ScopedAStatus setPwle(const std::string &pwleQueue); bool isUnderExternalControl(); diff --git a/vibrator/cs40l26/tests/mocks.h b/vibrator/cs40l26/tests/mocks.h index c85b0b5..641aba8 100644 --- a/vibrator/cs40l26/tests/mocks.h +++ b/vibrator/cs40l26/tests/mocks.h @@ -51,7 +51,7 @@ class MockApi : public ::aidl::android::hardware::vibrator::Vibrator::HwApi { MOCK_METHOD2(getHapticAlsaDevice, bool(int *card, int *device)); MOCK_METHOD4(setHapticPcmAmp, bool(struct pcm **haptic_pcm, bool enable, int card, int device)); MOCK_METHOD6(uploadOwtEffect, - bool(int fd, uint8_t *owtData, uint32_t numBytes, struct ff_effect *effect, + bool(int fd, const uint8_t *owtData, const uint32_t numBytes, struct ff_effect *effect, uint32_t *outEffectIndex, int *status)); MOCK_METHOD3(eraseOwtEffect, bool(int fd, int8_t effectIndex, std::vector *effect)); MOCK_METHOD1(debug, void(int fd)); From 620aafc025f9cf44fcf281f70e8145ef8dd40bc5 Mon Sep 17 00:00:00 2001 From: Cheng Chang Date: Fri, 26 Jan 2024 05:52:08 +0000 Subject: [PATCH 02/15] gps: Disable Vzw SUPL OTDOA Bug: 322404137 Test: OTDOA test in b/322404137 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:06b419a5788399df5e4cf5721e8e487a6c052121) Merged-In: Id0fb2286c594f335349b3219953043f7f7830a03 Change-Id: Id0fb2286c594f335349b3219953043f7f7830a03 --- location/gps.xml.f10 | 2 +- location/gps_user.xml.f10 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/location/gps.xml.f10 b/location/gps.xml.f10 index a47afb2..bda9cf9 100644 --- a/location/gps.xml.f10 +++ b/location/gps.xml.f10 @@ -35,7 +35,7 @@ SuplVersion="2" SuplMinorVersion="0" SuplOtdoaCapable="true" - SuplOtdoaCapable2="true" + SuplOtdoaCapable2="false" SuplGlonassCapable = "true" SuplGalileoCapable = "true" SuplBdsCapable = "true" diff --git a/location/gps_user.xml.f10 b/location/gps_user.xml.f10 index 19842ca..b92b252 100644 --- a/location/gps_user.xml.f10 +++ b/location/gps_user.xml.f10 @@ -34,7 +34,7 @@ SuplVersion="2" SuplMinorVersion="0" SuplOtdoaCapable="true" - SuplOtdoaCapable2="true" + SuplOtdoaCapable2="false" SuplGlonassCapable = "true" SuplGalileoCapable = "true" SuplBdsCapable = "true" From 74ea4be15405d97f50c0ba636d21ff9941006a74 Mon Sep 17 00:00:00 2001 From: Ankur Bakshi Date: Thu, 15 Feb 2024 02:05:19 +0000 Subject: [PATCH 03/15] Update felix SVN to 44 Bug: 325156176 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:e30274d4c9f0f7138a665f3092c99fb767607c95) Merged-In: Id9052a3303fc7c2c1842f3db9b52a2adf1ba164e Change-Id: Id9052a3303fc7c2c1842f3db9b52a2adf1ba164e --- device-felix.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/device-felix.mk b/device-felix.mk index 1166a1f..d3cead9 100644 --- a/device-felix.mk +++ b/device-felix.mk @@ -220,7 +220,7 @@ PRODUCT_SOONG_NAMESPACES += \ # Increment the SVN for any official public releases PRODUCT_VENDOR_PROPERTIES += \ - ro.vendor.build.svn=43 + ro.vendor.build.svn=44 # Vibrator HAL PRODUCT_VENDOR_PROPERTIES +=\ From 94385458477f3f76bbefdb7e1c779bef5726b547 Mon Sep 17 00:00:00 2001 From: Ankur Bakshi Date: Thu, 15 Feb 2024 02:08:07 +0000 Subject: [PATCH 04/15] Update felix SVN to 45 Bug: 325156176 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:abb540718bb58da443eb970b65e63de85704eef1) Merged-In: I5ebc65fcd00c7d5c593f8a56c8ccdfd424551005 Change-Id: I5ebc65fcd00c7d5c593f8a56c8ccdfd424551005 --- device-felix.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/device-felix.mk b/device-felix.mk index d3cead9..505da03 100644 --- a/device-felix.mk +++ b/device-felix.mk @@ -220,7 +220,7 @@ PRODUCT_SOONG_NAMESPACES += \ # Increment the SVN for any official public releases PRODUCT_VENDOR_PROPERTIES += \ - ro.vendor.build.svn=44 + ro.vendor.build.svn=45 # Vibrator HAL PRODUCT_VENDOR_PROPERTIES +=\ From ad8c399053cc7816168ed9621165c7bec3ae5cd9 Mon Sep 17 00:00:00 2001 From: Ankur Bakshi Date: Thu, 15 Feb 2024 02:09:11 +0000 Subject: [PATCH 05/15] Update felix SVN to 46 Bug: 325156176 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:bc701d8d613ee962e0a2702a527dd5955e8e38eb) Merged-In: I84212cd2b6e36d162d6f6624a21f393e0ec0d070 Change-Id: I84212cd2b6e36d162d6f6624a21f393e0ec0d070 --- device-felix.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/device-felix.mk b/device-felix.mk index 505da03..1af3c76 100644 --- a/device-felix.mk +++ b/device-felix.mk @@ -220,7 +220,7 @@ PRODUCT_SOONG_NAMESPACES += \ # Increment the SVN for any official public releases PRODUCT_VENDOR_PROPERTIES += \ - ro.vendor.build.svn=45 + ro.vendor.build.svn=46 # Vibrator HAL PRODUCT_VENDOR_PROPERTIES +=\ From 0eb1a04ba57f4fa0eae449e78dd31d4cdf6e34bd Mon Sep 17 00:00:00 2001 From: Ankur Bakshi Date: Wed, 6 Mar 2024 00:28:13 +0000 Subject: [PATCH 06/15] Update felix SVN to 47 Bug: 325156176 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:0771df9996399b0dedc54365019ee465293cf386) Merged-In: I80ca14c7073707ef69dd3feef8f7731afbe09582 Change-Id: I80ca14c7073707ef69dd3feef8f7731afbe09582 --- device-felix.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/device-felix.mk b/device-felix.mk index 1af3c76..394d6c3 100644 --- a/device-felix.mk +++ b/device-felix.mk @@ -220,7 +220,7 @@ PRODUCT_SOONG_NAMESPACES += \ # Increment the SVN for any official public releases PRODUCT_VENDOR_PROPERTIES += \ - ro.vendor.build.svn=46 + ro.vendor.build.svn=47 # Vibrator HAL PRODUCT_VENDOR_PROPERTIES +=\ From cf3571dadb47a75124cbfe2095b36c613c5b26f9 Mon Sep 17 00:00:00 2001 From: Ankur Bakshi Date: Thu, 21 Mar 2024 21:45:27 +0000 Subject: [PATCH 07/15] Update felix SVN to 48 Bug: 325156176 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:662666134fbc1977fb83a555ffaa5c7c816d62e0) Merged-In: Ifd4c3df67510d9f7cf5a88b9269614572b5eb0bc Change-Id: Ifd4c3df67510d9f7cf5a88b9269614572b5eb0bc --- device-felix.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/device-felix.mk b/device-felix.mk index 394d6c3..bc7189e 100644 --- a/device-felix.mk +++ b/device-felix.mk @@ -220,7 +220,7 @@ PRODUCT_SOONG_NAMESPACES += \ # Increment the SVN for any official public releases PRODUCT_VENDOR_PROPERTIES += \ - ro.vendor.build.svn=47 + ro.vendor.build.svn=48 # Vibrator HAL PRODUCT_VENDOR_PROPERTIES +=\ From ecc275fbeb2d16841f2eccd32f0c6908f67c03f1 Mon Sep 17 00:00:00 2001 From: Ravi Jain Date: Thu, 21 Mar 2024 15:16:14 +0000 Subject: [PATCH 08/15] cs40l26: Align Felix Hal with common HAL Pull ag/22589260 to replace new/delete by using vector from the common HAL. Bug: 322648133 Test: idlcli compose commands Test: adb shell cmd vibrator_manager synced prebaked 1 Test: adb shell idlcli vibrator compose 0 8 1.0; \ sleep 1; adb shell idlcli vibrator compose 0 7 1.0; Test: atest PtsVibratorHalTestSuite \ PtsHapticsTestCases \ VibratorHalCs40l26TestSuitePrivate \ VtsHalVibratorManagerTargetTest \ VtsHalVibratorTargetTest \ android.os.cts.VibratorTest \ android.os.cts.VibratorManagerTest \ android.os.cts.VibrationEffectTest \ android.os.cts.VibrationAttributesTest \ android.os.cts.CombinedVibrationTest (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:75d87040c7284b0d0ef2f20e5edd2e2d384d943c) Merged-In: Ia6e9111c47f27089521f05a68b538bbefb235d6b Change-Id: Ia6e9111c47f27089521f05a68b538bbefb235d6b --- vibrator/cs40l26/Hardware.h | 25 +++++++++++++++++-------- vibrator/cs40l26/Vibrator.cpp | 28 +++++++++++++++++++++------- vibrator/cs40l26/Vibrator.h | 2 ++ 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/vibrator/cs40l26/Hardware.h b/vibrator/cs40l26/Hardware.h index af8d120..69cf9ae 100644 --- a/vibrator/cs40l26/Hardware.h +++ b/vibrator/cs40l26/Hardware.h @@ -104,18 +104,25 @@ class HwApi : public Vibrator::HwApi, private HwApiBase { .code = FF_GAIN, .value = value, }; + if (value > 100) { + ALOGE("Invalid gain"); + return false; + } if (write(fd, (const void *)&gain, sizeof(gain)) != sizeof(gain)) { return false; } return true; } bool setFFEffect(int fd, struct ff_effect *effect, uint16_t timeoutMs) override { + if (effect == nullptr) { + ALOGE("Invalid ff_effect"); + return false; + } if (ioctl(fd, EVIOCSFF, effect) < 0) { ALOGE("setFFEffect fail"); return false; - } else { - return true; } + return true; } bool setFFPlay(int fd, int8_t index, bool value) override { struct input_event play = { @@ -186,14 +193,17 @@ class HwApi : public Vibrator::HwApi, private HwApiBase { } bool uploadOwtEffect(int fd, const uint8_t *owtData, const uint32_t numBytes, struct ff_effect *effect, uint32_t *outEffectIndex, int *status) override { - (*effect).u.periodic.custom_len = numBytes / sizeof(uint16_t); - delete[] ((*effect).u.periodic.custom_data); - (*effect).u.periodic.custom_data = new int16_t[(*effect).u.periodic.custom_len]{0x0000}; - if ((*effect).u.periodic.custom_data == nullptr) { - ALOGE("Failed to allocate memory for custom data\n"); + if (owtData == nullptr || effect == nullptr || outEffectIndex == nullptr) { + ALOGE("Invalid argument owtData, ff_effect or outEffectIndex"); *status = EX_NULL_POINTER; return false; } + if (status == nullptr) { + ALOGE("Invalid argument status"); + return false; + } + + (*effect).u.periodic.custom_len = numBytes / sizeof(uint16_t); memcpy((*effect).u.periodic.custom_data, owtData, numBytes); if ((*effect).id != -1) { @@ -204,7 +214,6 @@ class HwApi : public Vibrator::HwApi, private HwApiBase { (*effect).id = -1; if (ioctl(fd, EVIOCSFF, effect) < 0) { ALOGE("Failed to upload effect %d (%d): %s", *outEffectIndex, errno, strerror(errno)); - delete[] ((*effect).u.periodic.custom_data); *status = EX_ILLEGAL_STATE; return false; } diff --git a/vibrator/cs40l26/Vibrator.cpp b/vibrator/cs40l26/Vibrator.cpp index 2abe72e..b3ce88e 100644 --- a/vibrator/cs40l26/Vibrator.cpp +++ b/vibrator/cs40l26/Vibrator.cpp @@ -44,7 +44,6 @@ namespace aidl { namespace android { namespace hardware { namespace vibrator { -static constexpr uint8_t FF_CUSTOM_DATA_LEN = 2; static constexpr uint16_t FF_CUSTOM_DATA_LEN_MAX_COMP = 2044; // (COMPOSE_SIZE_MAX + 1) * 8 + 4 static constexpr uint16_t FF_CUSTOM_DATA_LEN_MAX_PWLE = 2302; @@ -488,19 +487,23 @@ Vibrator::Vibrator(std::unique_ptr hwApiDefault, std::unique_ptr h mEffectDurations = { 1000, 100, 12, 1000, 300, 130, 150, 500, 100, 5, 12, 1000, 1000, 1000, }; /* 11+3 waveforms. The duration must < UINT16_MAX */ + mEffectCustomData.reserve(WAVEFORM_MAX_INDEX); uint8_t effectIndex; + uint16_t numBytes = 0; for (effectIndex = 0; effectIndex < WAVEFORM_MAX_INDEX; effectIndex++) { if (effectIndex < WAVEFORM_MAX_PHYSICAL_INDEX) { /* Initialize physical waveforms. */ + mEffectCustomData.push_back({RAM_WVFRM_BANK, effectIndex}); mFfEffects[effectIndex] = { .type = FF_PERIODIC, .id = -1, // Length == 0 to allow firmware control of the duration .replay.length = 0, .u.periodic.waveform = FF_CUSTOM, - .u.periodic.custom_data = new int16_t[2]{RAM_WVFRM_BANK, effectIndex}, - .u.periodic.custom_len = FF_CUSTOM_DATA_LEN, + .u.periodic.custom_data = mEffectCustomData[effectIndex].data(), + .u.periodic.custom_len = + static_cast(mEffectCustomData[effectIndex].size()), }; // Bypass the waveform update due to different input name if ((strstr(inputEventName, "cs40l26") != nullptr) || @@ -518,12 +521,16 @@ Vibrator::Vibrator(std::unique_ptr hwApiDefault, std::unique_ptr h } } else { /* Initiate placeholders for OWT effects. */ + numBytes = effectIndex == WAVEFORM_COMPOSE ? FF_CUSTOM_DATA_LEN_MAX_COMP + : FF_CUSTOM_DATA_LEN_MAX_PWLE; + std::vector tempVec(numBytes, 0); + mEffectCustomData.push_back(std::move(tempVec)); mFfEffects[effectIndex] = { .type = FF_PERIODIC, .id = -1, .replay.length = 0, .u.periodic.waveform = FF_CUSTOM, - .u.periodic.custom_data = nullptr, + .u.periodic.custom_data = mEffectCustomData[effectIndex].data(), .u.periodic.custom_len = 0, }; } @@ -532,18 +539,21 @@ Vibrator::Vibrator(std::unique_ptr hwApiDefault, std::unique_ptr h // ====================HAL internal effect table== Flip ================================== if (mIsDual) { mFfEffectsDual.resize(WAVEFORM_MAX_INDEX); + mEffectCustomDataDual.reserve(WAVEFORM_MAX_INDEX); for (effectIndex = 0; effectIndex < WAVEFORM_MAX_INDEX; effectIndex++) { if (effectIndex < WAVEFORM_MAX_PHYSICAL_INDEX) { /* Initialize physical waveforms. */ + mEffectCustomDataDual.push_back({RAM_WVFRM_BANK, effectIndex}); mFfEffectsDual[effectIndex] = { .type = FF_PERIODIC, .id = -1, // Length == 0 to allow firmware control of the duration .replay.length = 0, .u.periodic.waveform = FF_CUSTOM, - .u.periodic.custom_data = new int16_t[2]{RAM_WVFRM_BANK, effectIndex}, - .u.periodic.custom_len = FF_CUSTOM_DATA_LEN, + .u.periodic.custom_data = mEffectCustomDataDual[effectIndex].data(), + .u.periodic.custom_len = + static_cast(mEffectCustomDataDual[effectIndex].size()), }; // Bypass the waveform update due to different input name if ((strstr(inputEventName, "cs40l26") != nullptr) || @@ -563,12 +573,16 @@ Vibrator::Vibrator(std::unique_ptr hwApiDefault, std::unique_ptr h } } else { /* Initiate placeholders for OWT effects. */ + numBytes = effectIndex == WAVEFORM_COMPOSE ? FF_CUSTOM_DATA_LEN_MAX_COMP + : FF_CUSTOM_DATA_LEN_MAX_PWLE; + std::vector tempVec(numBytes, 0); + mEffectCustomDataDual.push_back(std::move(tempVec)); mFfEffectsDual[effectIndex] = { .type = FF_PERIODIC, .id = -1, .replay.length = 0, .u.periodic.waveform = FF_CUSTOM, - .u.periodic.custom_data = nullptr, + .u.periodic.custom_data = mEffectCustomDataDual[effectIndex].data(), .u.periodic.custom_len = 0, }; } diff --git a/vibrator/cs40l26/Vibrator.h b/vibrator/cs40l26/Vibrator.h index 06bd6e5..8f89713 100644 --- a/vibrator/cs40l26/Vibrator.h +++ b/vibrator/cs40l26/Vibrator.h @@ -218,6 +218,8 @@ class Vibrator : public BnVibrator { std::vector mFfEffects; std::vector mFfEffectsDual; std::vector mEffectDurations; + std::vector> mEffectCustomData; + std::vector> mEffectCustomDataDual; std::future mAsyncHandle; ::android::base::unique_fd mInputFd; ::android::base::unique_fd mInputFdDual; From b979856d65f6e1479b767e0536a37b9eeed74be7 Mon Sep 17 00:00:00 2001 From: Ankur Bakshi Date: Thu, 28 Mar 2024 15:34:45 +0000 Subject: [PATCH 09/15] Update felix SVN to 49 Bug: 330382848 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:f4e79e0825e6520e1d801f8b238ee87d22003341) Merged-In: I4adff31a3d552c862fab43cba73c0cb074904be8 Change-Id: I4adff31a3d552c862fab43cba73c0cb074904be8 --- device-felix.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/device-felix.mk b/device-felix.mk index bc7189e..17ec024 100644 --- a/device-felix.mk +++ b/device-felix.mk @@ -220,7 +220,7 @@ PRODUCT_SOONG_NAMESPACES += \ # Increment the SVN for any official public releases PRODUCT_VENDOR_PROPERTIES += \ - ro.vendor.build.svn=48 + ro.vendor.build.svn=49 # Vibrator HAL PRODUCT_VENDOR_PROPERTIES +=\ From d87c7b793538d3f4a001ddb274cbe415efebfd3a Mon Sep 17 00:00:00 2001 From: Ankur Bakshi Date: Wed, 3 Apr 2024 23:17:02 +0000 Subject: [PATCH 10/15] Update felix SVN to 50 Bug: 330382848 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:73220aeecf69ad2c7a04be657263379aa4406b24) Merged-In: Ic4cb9fec016661b45d7af9a1075e5912bd435b9e Change-Id: Ic4cb9fec016661b45d7af9a1075e5912bd435b9e --- device-felix.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/device-felix.mk b/device-felix.mk index 17ec024..b11d813 100644 --- a/device-felix.mk +++ b/device-felix.mk @@ -220,7 +220,7 @@ PRODUCT_SOONG_NAMESPACES += \ # Increment the SVN for any official public releases PRODUCT_VENDOR_PROPERTIES += \ - ro.vendor.build.svn=49 + ro.vendor.build.svn=50 # Vibrator HAL PRODUCT_VENDOR_PROPERTIES +=\ From 3f3a05ab872b41e90f17050c8ac14067026c6202 Mon Sep 17 00:00:00 2001 From: Ankur Bakshi Date: Wed, 24 Apr 2024 19:47:53 +0000 Subject: [PATCH 11/15] Update felix SVN to 51 Bug: 336526332 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:e222c307125a3c038eb3c5376453c70d9c47040c) Merged-In: I0b4bea1a97004139cc18129eeeab302aa557ca05 Change-Id: I0b4bea1a97004139cc18129eeeab302aa557ca05 --- device-felix.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/device-felix.mk b/device-felix.mk index b11d813..44f35b1 100644 --- a/device-felix.mk +++ b/device-felix.mk @@ -220,7 +220,7 @@ PRODUCT_SOONG_NAMESPACES += \ # Increment the SVN for any official public releases PRODUCT_VENDOR_PROPERTIES += \ - ro.vendor.build.svn=50 + ro.vendor.build.svn=51 # Vibrator HAL PRODUCT_VENDOR_PROPERTIES +=\ From 30b137a0e312685d94ff0532c080adce10e5feee Mon Sep 17 00:00:00 2001 From: Leo Chen Date: Thu, 23 May 2024 06:44:03 +0000 Subject: [PATCH 12/15] Update IDisplay to V12 Test: trigger test build Bug: 309897479 Change-Id: Ia66b36711deaad59135d15f435a0db9319687051 Signed-off-by: Leo Chen --- device_framework_matrix_product_felix.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/device_framework_matrix_product_felix.xml b/device_framework_matrix_product_felix.xml index 3fd94a9..475edd2 100644 --- a/device_framework_matrix_product_felix.xml +++ b/device_framework_matrix_product_felix.xml @@ -1,7 +1,7 @@ com.google.hardware.pixel.display - 11-12 + 12 IDisplay secondary From bc25286b64b9c867c3638196002a7b70ac69ac62 Mon Sep 17 00:00:00 2001 From: Ankur Bakshi Date: Thu, 30 May 2024 00:05:17 +0000 Subject: [PATCH 13/15] Update felix SVN to 53 Bug: 342381152 Change-Id: I21048d04ff40b1237bcf3d8258b3a3263394fe42 --- device-felix.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/device-felix.mk b/device-felix.mk index 94a95d5..19292e3 100644 --- a/device-felix.mk +++ b/device-felix.mk @@ -224,7 +224,7 @@ PRODUCT_SOONG_NAMESPACES += \ # Increment the SVN for any official public releases PRODUCT_VENDOR_PROPERTIES += \ - ro.vendor.build.svn=52 + ro.vendor.build.svn=53 # Vibrator HAL PRODUCT_VENDOR_PROPERTIES +=\ From e6dbfef4d86749540fecc9d5cf9017d86d0c8833 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Mon, 10 Jun 2024 17:38:45 +0000 Subject: [PATCH 14/15] libc++fs is part of libc++ now. Change-Id: I543c95f9813e055dd441ea03363f2205648847c8 --- vibrator/cs40l26/tests/Android.bp | 1 - 1 file changed, 1 deletion(-) diff --git a/vibrator/cs40l26/tests/Android.bp b/vibrator/cs40l26/tests/Android.bp index 48baa90..0924709 100644 --- a/vibrator/cs40l26/tests/Android.bp +++ b/vibrator/cs40l26/tests/Android.bp @@ -26,7 +26,6 @@ cc_test { "test-vibrator.cpp", ], static_libs: [ - "libc++fs", "libgmock", ], shared_libs: [ From 22b192c34af1f4ffd30c90d57733b31c58b0d208 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 13 Jun 2024 14:47:44 +0100 Subject: [PATCH 15/15] Use singular OWNERS file. Rather than every project having an OWNERS with explicit people, just use one centralized OWNERS file and have every other OWNERS reference that. This way when the team changes there's only one place that needs to be updated. Bug: 346876927 Test: N/A Flag: EXEMPT OWNERS change Change-Id: Ia51b1745f14bda22629e05cd33f6c807cf6f6565 --- vibrator/OWNERS | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/vibrator/OWNERS b/vibrator/OWNERS index 859c7e0..dec74a8 100644 --- a/vibrator/OWNERS +++ b/vibrator/OWNERS @@ -1,4 +1 @@ -chrispaulo@google.com -michaelwr@google.com -nathankulczak@google.com -taikuo@google.com +file:platform/hardware/google/pixel:/vibrator/OWNERS