/* * SPDX-FileCopyrightText: 2025 The LineageOS Project * SPDX-License-Identifier: Apache-2.0 */ #include "Vibrator.h" #include #include #include #include #include "aac_vibra_function.h" #define RICHTAP_LIGHT_STRENGTH 69 #define RICHTAP_MEDIUM_STRENGTH 89 #define RICHTAP_STRONG_STRENGTH 99 namespace aidl { namespace android { namespace hardware { namespace vibrator { Vibrator::Vibrator() { uint32_t deviceType = 0; int32_t ret = aac_vibra_init(&deviceType); if (ret) { ALOGE("AAC init failed: %d\n", ret); return; } aac_vibra_looper_start(); ALOGI("AAC init success: %u\n", deviceType); } ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) { *_aidl_return = IVibrator::CAP_ON_CALLBACK | IVibrator::CAP_PERFORM_CALLBACK | IVibrator::CAP_AMPLITUDE_CONTROL; return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus Vibrator::off() { int32_t ret = aac_vibra_off(); if (ret) { ALOGE("AAC off failed: %d\n", ret); return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_SERVICE_SPECIFIC)); } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus Vibrator::on(int32_t timeoutMs, const std::shared_ptr& callback) { int32_t ret = aac_vibra_looper_on(timeoutMs); if (ret < 0) { ALOGE("AAC on failed: %d\n", ret); return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_SERVICE_SPECIFIC)); } if (callback != nullptr) { std::thread([=] { usleep(ret * 1000); callback->onComplete(); }).detach(); } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus Vibrator::perform(Effect effect, EffectStrength es, const std::shared_ptr& callback, int32_t* _aidl_return) { int32_t strength; if (effect < Effect::CLICK || effect > Effect::HEAVY_CLICK) return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); switch (es) { case EffectStrength::LIGHT: strength = RICHTAP_LIGHT_STRENGTH; break; case EffectStrength::MEDIUM: strength = RICHTAP_MEDIUM_STRENGTH; break; case EffectStrength::STRONG: strength = RICHTAP_STRONG_STRENGTH; break; default: return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); } int32_t ret = aac_vibra_looper_prebaked_effect(static_cast(effect), strength); if (ret < 0) { ALOGE("AAC perform failed: %d\n", ret); return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_SERVICE_SPECIFIC)); } if (callback != nullptr) { std::thread([=] { usleep(ret * 1000); callback->onComplete(); }).detach(); } *_aidl_return = ret; return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus Vibrator::getSupportedEffects(std::vector* _aidl_return) { *_aidl_return = {Effect::CLICK, Effect::DOUBLE_CLICK, Effect::TICK, Effect::THUD, Effect::POP, Effect::HEAVY_CLICK}; return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus Vibrator::setAmplitude(float amplitude) { uint8_t tmp = (uint8_t)(amplitude * 0xff); int32_t ret = aac_vibra_setAmplitude(tmp); if (ret) { ALOGE("AAC set amplitude failed: %d\n", ret); return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_SERVICE_SPECIFIC)); } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus Vibrator::setExternalControl(bool enabled __unused) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); } ndk::ScopedAStatus Vibrator::getCompositionDelayMax(int32_t* maxDelayMs __unused) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); } ndk::ScopedAStatus Vibrator::getCompositionSizeMax(int32_t* maxSize __unused) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); } ndk::ScopedAStatus Vibrator::getSupportedPrimitives( std::vector* supported __unused) { return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus Vibrator::getPrimitiveDuration(CompositePrimitive primitive __unused, int32_t* durationMs __unused) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); } ndk::ScopedAStatus Vibrator::compose(const std::vector& composite __unused, const std::shared_ptr& callback __unused) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); } ndk::ScopedAStatus Vibrator::getSupportedAlwaysOnEffects(std::vector* _aidl_return __unused) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); } ndk::ScopedAStatus Vibrator::alwaysOnEnable(int32_t id __unused, Effect effect __unused, EffectStrength strength __unused) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); } ndk::ScopedAStatus Vibrator::alwaysOnDisable(int32_t id __unused) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); } ndk::ScopedAStatus Vibrator::getResonantFrequency(float* resonantFreqHz __unused) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); } ndk::ScopedAStatus Vibrator::getQFactor(float* qFactor __unused) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); } ndk::ScopedAStatus Vibrator::getFrequencyResolution(float* freqResolutionHz __unused) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); } ndk::ScopedAStatus Vibrator::getFrequencyMinimum(float* freqMinimumHz __unused) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); } ndk::ScopedAStatus Vibrator::getBandwidthAmplitudeMap(std::vector* _aidl_return __unused) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); } ndk::ScopedAStatus Vibrator::getPwlePrimitiveDurationMax(int32_t* durationMs __unused) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); } ndk::ScopedAStatus Vibrator::getPwleCompositionSizeMax(int32_t* maxSize __unused) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); } ndk::ScopedAStatus Vibrator::getSupportedBraking(std::vector* supported __unused) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); } ndk::ScopedAStatus Vibrator::composePwle(const std::vector& composite __unused, const std::shared_ptr& callback __unused) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); } } // namespace vibrator } // namespace hardware } // namespace android } // namespace aidl