Add AIDL support for effect bundle with lvm implementation.
Bug: 255361653
Test: atest VtsHalAudioEffectTargetTest
atest VtsHalAudioEffectFactoryTargetTest
atest VtsHalEqualizerTargetTest
Change-Id: I87470cbcf915cba3155a0a2026149d4637f2b553
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
new file mode 100644
index 0000000..2defa4e
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BundleContext"
+#include <Utils.h>
+
+#include "BundleContext.h"
+#include "BundleTypes.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+RetCode BundleContext::init() {
+ // init with pre-defined preset NORMAL
+ for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ mBandGaindB[i] = lvm::kSoftPresets[0 /* normal */][i];
+ }
+
+ // allocate lvm instance
+ LVM_ReturnStatus_en status;
+ LVM_InstParams_t params = {.BufferMode = LVM_UNMANAGED_BUFFERS,
+ .MaxBlockSize = lvm::MAX_CALL_SIZE,
+ .EQNB_NumBands = lvm::MAX_NUM_BANDS,
+ .PSA_Included = LVM_PSA_ON};
+ status = LVM_GetInstanceHandle(&mInstance, ¶ms);
+ GOTO_IF_LVM_ERROR(status, deinit, "LVM_GetInstanceHandleFailed");
+
+ // set control
+ LVM_ControlParams_t controlParams;
+ initControlParameter(controlParams);
+ status = LVM_SetControlParameters(mInstance, &controlParams);
+ GOTO_IF_LVM_ERROR(status, deinit, "LVM_SetControlParametersFailed");
+
+ /* Set the headroom parameters */
+ LVM_HeadroomParams_t headroomParams;
+ initHeadroomParameter(headroomParams);
+ status = LVM_SetHeadroomParams(mInstance, &headroomParams);
+ GOTO_IF_LVM_ERROR(status, deinit, "LVM_SetHeadroomParamsFailed");
+
+ return RetCode::SUCCESS;
+
+deinit:
+ deInit();
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+}
+
+void BundleContext::deInit() {
+ if (mInstance) {
+ LVM_DelInstanceHandle(&mInstance);
+ mInstance = nullptr;
+ }
+}
+
+RetCode BundleContext::enable() {
+ LVM_ControlParams_t params;
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, "failGetControlParams");
+ if (mType == lvm::BundleEffectType::EQUALIZER) {
+ LOG(DEBUG) << __func__ << " enable bundle EQ";
+ params.EQNB_OperatingMode = LVM_EQNB_ON;
+ }
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, "failSetControlParams");
+ mEnabled = true;
+ // LvmEffect_limitLevel(pContext);
+ return RetCode::SUCCESS;
+}
+
+RetCode BundleContext::disable() {
+ LVM_ControlParams_t params;
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, "failGetControlParams");
+ if (mType == lvm::BundleEffectType::EQUALIZER) {
+ LOG(DEBUG) << __func__ << " disable bundle EQ";
+ params.EQNB_OperatingMode = LVM_EQNB_OFF;
+ }
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, "failSetControlParams");
+ mEnabled = false;
+ // LvmEffect_limitLevel(pContext);
+ return RetCode::SUCCESS;
+}
+
+LVM_INT16 BundleContext::LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix) const {
+ LVM_INT16 db_fix;
+ LVM_INT16 Shift;
+ LVM_INT16 SmallRemainder;
+ LVM_UINT32 Remainder = (LVM_UINT32)Lin_fix;
+
+ /* Count leading bits, 1 cycle in assembly*/
+ for (Shift = 0; Shift < 32; Shift++) {
+ if ((Remainder & 0x80000000U) != 0) {
+ break;
+ }
+ Remainder = Remainder << 1;
+ }
+
+ /*
+ * Based on the approximation equation (for Q11.4 format):
+ *
+ * dB = -96 * Shift + 16 * (8 * Remainder - 2 * Remainder^2)
+ */
+ db_fix = (LVM_INT16)(-96 * Shift); /* Six dB steps in Q11.4 format*/
+ SmallRemainder = (LVM_INT16)((Remainder & 0x7fffffff) >> 24);
+ db_fix = (LVM_INT16)(db_fix + SmallRemainder);
+ SmallRemainder = (LVM_INT16)(SmallRemainder * SmallRemainder);
+ db_fix = (LVM_INT16)(db_fix - (LVM_INT16)((LVM_UINT16)SmallRemainder >> 9));
+
+ /* Correct for small offset */
+ db_fix = (LVM_INT16)(db_fix - 5);
+
+ return db_fix;
+}
+
+// TODO: replace with more generic approach, like: audio_utils_power_from_amplitude
+int16_t BundleContext::VolToDb(uint32_t vol) const {
+ int16_t dB;
+
+ dB = LVC_ToDB_s32Tos16(vol << 7);
+ dB = (dB + 8) >> 4;
+ dB = (dB < -96) ? -96 : dB;
+
+ return dB;
+}
+
+RetCode BundleContext::setVolumeStereo(const Parameter::VolumeStereo& volume) {
+ LVM_ControlParams_t params;
+ LVM_ReturnStatus_en status = LVM_SUCCESS;
+
+ // Convert volume to dB
+ int leftdB = VolToDb(volume.left);
+ int rightdB = VolToDb(volume.right);
+ int maxdB = std::max(leftdB, rightdB);
+ int pandB = rightdB - leftdB;
+ // TODO: add volume effect implementation here:
+ // android::VolumeSetVolumeLevel(pContext, (int16_t)(maxdB * 100));
+ LOG(DEBUG) << __func__ << " pandB: " << pandB << " maxdB " << maxdB;
+
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, "");
+
+ params.VC_Balance = pandB;
+
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, "");
+
+ mVolumeStereo = volume;
+ return RetCode::SUCCESS;
+}
+
+RetCode BundleContext::setEqualizerPreset(const int presetIdx) {
+ if (presetIdx < 0 || presetIdx >= lvm::MAX_NUM_PRESETS) {
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+
+ std::vector<Equalizer::BandLevel> bandLevels;
+ bandLevels.reserve(lvm::MAX_NUM_BANDS);
+ for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ bandLevels.emplace_back(Equalizer::BandLevel{i, lvm::kSoftPresets[presetIdx][i]});
+ }
+
+ RetCode ret = updateControlParameter(bandLevels);
+ if (RetCode::SUCCESS == ret) {
+ mCurPresetIdx = presetIdx;
+ LOG(INFO) << __func__ << " success with " << presetIdx;
+ } else {
+ LOG(ERROR) << __func__ << " failed to setPreset " << presetIdx;
+ }
+ return ret;
+}
+
+RetCode BundleContext::setEqualizerBandLevels(const std::vector<Equalizer::BandLevel>& bandLevels) {
+ RETURN_VALUE_IF(bandLevels.size() > lvm::MAX_NUM_BANDS || bandLevels.empty(),
+ RetCode::ERROR_ILLEGAL_PARAMETER, "sizeExceedMax");
+ RetCode ret = updateControlParameter(bandLevels);
+ if (RetCode::SUCCESS == ret) {
+ mCurPresetIdx = lvm::PRESET_CUSTOM;
+ LOG(INFO) << __func__ << " succeed with " << ::android::internal::ToString(bandLevels);
+ } else {
+ LOG(ERROR) << __func__ << " failed with " << ::android::internal::ToString(bandLevels);
+ }
+ return ret;
+}
+
+std::vector<Equalizer::BandLevel> BundleContext::getEqualizerBandLevels() const {
+ std::vector<Equalizer::BandLevel> bandLevels;
+ bandLevels.reserve(lvm::MAX_NUM_BANDS);
+ for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ bandLevels.emplace_back(Equalizer::BandLevel{i, mBandGaindB[i]});
+ }
+ return bandLevels;
+}
+
+bool BundleContext::isBandLevelIndexInRange(
+ const std::vector<Equalizer::BandLevel>& bandLevels) const {
+ const auto [min, max] =
+ std::minmax_element(bandLevels.begin(), bandLevels.end(),
+ [](const auto& a, const auto& b) { return a.index < b.index; });
+ return min->index >= 0 && max->index < lvm::MAX_NUM_BANDS;
+}
+
+RetCode BundleContext::updateControlParameter(const std::vector<Equalizer::BandLevel>& bandLevels) {
+ RETURN_VALUE_IF(!isBandLevelIndexInRange(bandLevels), RetCode::ERROR_ILLEGAL_PARAMETER,
+ "indexOutOfRange");
+
+ std::array<int, lvm::MAX_NUM_BANDS> tempLevel;
+ for (const auto& it : bandLevels) {
+ tempLevel[it.index] = it.levelMb;
+ }
+
+ LVM_ControlParams_t params;
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+ for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ params.pEQNB_BandDefinition[i].Frequency = lvm::kPresetsFrequencies[i];
+ params.pEQNB_BandDefinition[i].QFactor = lvm::kPresetsQFactors[i];
+ params.pEQNB_BandDefinition[i].Gain = tempLevel[i];
+ }
+
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+ mBandGaindB = tempLevel;
+ LOG(INFO) << __func__ << " update bandGain to " << ::android::internal::ToString(mBandGaindB);
+
+ return RetCode::SUCCESS;
+}
+
+void BundleContext::initControlParameter(LVM_ControlParams_t& params) const {
+ /* General parameters */
+ params.OperatingMode = LVM_MODE_ON;
+ params.SampleRate = LVM_FS_44100;
+ params.SourceFormat = LVM_STEREO;
+ params.SpeakerType = LVM_HEADPHONES;
+
+ /* Concert Sound parameters */
+ params.VirtualizerOperatingMode = LVM_MODE_OFF;
+ params.VirtualizerType = LVM_CONCERTSOUND;
+ params.VirtualizerReverbLevel = 100;
+ params.CS_EffectLevel = LVM_CS_EFFECT_NONE;
+
+ params.EQNB_OperatingMode = LVM_EQNB_OFF;
+ params.EQNB_NBands = lvm::MAX_NUM_BANDS;
+ params.pEQNB_BandDefinition = getDefaultEqualizerBandDefs();
+
+ /* Volume Control parameters */
+ params.VC_EffectLevel = 0;
+ params.VC_Balance = 0;
+
+ /* Treble Enhancement parameters */
+ params.TE_OperatingMode = LVM_TE_OFF;
+ params.TE_EffectLevel = 0;
+
+ /* PSA Control parameters */
+ params.PSA_Enable = LVM_PSA_OFF;
+ params.PSA_PeakDecayRate = (LVM_PSA_DecaySpeed_en)0;
+
+ /* Bass Enhancement parameters */
+ params.BE_OperatingMode = LVM_BE_OFF;
+ params.BE_EffectLevel = 0;
+ params.BE_CentreFreq = LVM_BE_CENTRE_90Hz;
+ params.BE_HPF = LVM_BE_HPF_ON;
+
+ /* PSA Control parameters */
+ params.PSA_Enable = LVM_PSA_OFF;
+ params.PSA_PeakDecayRate = LVM_PSA_SPEED_MEDIUM;
+
+ /* TE Control parameters */
+ params.TE_OperatingMode = LVM_TE_OFF;
+ params.TE_EffectLevel = 0;
+
+ params.NrChannels = audio_channel_count_from_out_mask(AUDIO_CHANNEL_OUT_STEREO);
+ params.ChMask = AUDIO_CHANNEL_OUT_STEREO;
+ params.SourceFormat = LVM_STEREO;
+}
+
+void BundleContext::initHeadroomParameter(LVM_HeadroomParams_t& params) const {
+ params.pHeadroomDefinition = getDefaultEqualizerHeadroomBanDefs();
+ params.NHeadroomBands = 2;
+ params.Headroom_OperatingMode = LVM_HEADROOM_OFF;
+}
+
+LVM_EQNB_BandDef_t *BundleContext::getDefaultEqualizerBandDefs() {
+ static LVM_EQNB_BandDef_t* BandDefs = []() {
+ static LVM_EQNB_BandDef_t tempDefs[lvm::MAX_NUM_BANDS];
+ /* N-Band Equaliser parameters */
+ for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ tempDefs[i].Frequency = lvm::kPresetsFrequencies[i];
+ tempDefs[i].QFactor = lvm::kPresetsQFactors[i];
+ tempDefs[i].Gain = lvm::kSoftPresets[0/* normal */][i];
+ }
+ return tempDefs;
+ }();
+
+ return BandDefs;
+}
+
+LVM_HeadroomBandDef_t *BundleContext::getDefaultEqualizerHeadroomBanDefs() {
+ static LVM_HeadroomBandDef_t HeadroomBandDef[LVM_HEADROOM_MAX_NBANDS] = {
+ {
+ .Limit_Low = 20,
+ .Limit_High = 4999,
+ .Headroom_Offset = 0,
+ },
+ {
+ .Limit_Low = 5000,
+ .Limit_High = 24000,
+ .Headroom_Offset = 0,
+ },
+ };
+ return HeadroomBandDef;
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
new file mode 100644
index 0000000..616ab78
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/logging.h>
+#include <array>
+
+#include "BundleTypes.h"
+#include "effect-impl/EffectContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class BundleContext final : public EffectContext {
+ public:
+ BundleContext(int statusDepth, const Parameter::Common& common,
+ const lvm::BundleEffectType& type)
+ : EffectContext(statusDepth, common), mType(type) {
+ LOG(DEBUG) << __func__ << type;
+ }
+ ~BundleContext() override {
+ LOG(DEBUG) << __func__;
+ deInit();
+ }
+
+ RetCode init();
+ void deInit();
+ lvm::BundleEffectType getBundleType() const { return mType; }
+
+ RetCode enable();
+ RetCode disable();
+
+ LVM_Handle_t getLvmInstance() const { return mInstance; }
+
+ void setSampleRate (const int sampleRate) { mSampleRate = sampleRate; }
+ int getSampleRate() const { return mSampleRate; }
+
+ void setChannelMask(const aidl::android::media::audio::common::AudioChannelLayout& chMask) {
+ mChMask = chMask;
+ }
+ aidl::android::media::audio::common::AudioChannelLayout getChannelMask() const {
+ return mChMask;
+ }
+
+ RetCode setEqualizerPreset(const int presetIdx);
+ int getEqualizerPreset() const { return mCurPresetIdx; }
+ RetCode setEqualizerBandLevels(const std::vector<Equalizer::BandLevel>& bandLevels);
+ std::vector<Equalizer::BandLevel> getEqualizerBandLevels() const;
+
+ RetCode setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) override;
+ Parameter::VolumeStereo getVolumeStereo() override { return mVolumeStereo; };
+
+ private:
+ const lvm::BundleEffectType mType;
+ bool mEnabled = false;
+ LVM_Handle_t mInstance = nullptr;
+
+ aidl::android::media::audio::common::AudioDeviceDescription mVirtualizerForcedDevice;
+ aidl::android::media::audio::common::AudioChannelLayout mChMask;
+
+ int mSampleRate = LVM_FS_44100;
+ int mSamplesPerSecond = 0;
+ int mSamplesToExitCountEq = 0;
+ int mSamplesToExitCountBb = 0;
+ int mSamplesToExitCountVirt = 0;
+ int mFrameCount = 0;
+
+ /* Bitmask whether drain is in progress due to disabling the effect.
+ The corresponding bit to an effect is set by 1 << lvm_effect_en. */
+ int mEffectInDrain = 0;
+
+ /* Bitmask whether process() was called for a particular effect.
+ The corresponding bit to an effect is set by 1 << lvm_effect_en. */
+ int mEffectProcessCalled = 0;
+ int mNumberEffectsEnabled = 0;
+ int mNumberEffectsCalled = 0;
+ bool mFirstVolume = false;
+ // Bass
+ bool mBassTempDisabled = false;
+ int mBassStrengthSaved = 0;
+ // Equalizer
+ int mCurPresetIdx = lvm::PRESET_CUSTOM; /* Current preset being used */
+ std::array<int, lvm::MAX_NUM_BANDS> mBandGaindB;
+ // Virtualizer
+ int mVirtStrengthSaved = 0; /* Conversion between Get/Set */
+ bool mVirtualizerTempDisabled = false;
+ // Volume
+ int mLevelSaved = 0; /* for when mute is set, level must be saved */
+ bool mMuteEnabled = false; /* Must store as mute = -96dB level */
+
+ void initControlParameter(LVM_ControlParams_t& params) const;
+ void initHeadroomParameter(LVM_HeadroomParams_t& params) const;
+ int16_t VolToDb(uint32_t vol) const;
+ LVM_INT16 LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix) const;
+ RetCode updateControlParameter(const std::vector<Equalizer::BandLevel>& bandLevels);
+ bool isBandLevelIndexInRange(const std::vector<Equalizer::BandLevel>& bandLevels) const;
+ static LVM_EQNB_BandDef_t* getDefaultEqualizerBandDefs();
+ static LVM_HeadroomBandDef_t* getDefaultEqualizerHeadroomBanDefs();
+};
+
+} // namespace aidl::android::hardware::audio::effect
+
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
new file mode 100644
index 0000000..1772bd1
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include <array>
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include "effect-impl/EffectUUID.h"
+#include "effect-impl/EffectTypes.h"
+#include "LVM.h"
+
+namespace aidl::android::hardware::audio::effect {
+namespace lvm {
+
+constexpr inline size_t MAX_NUM_PRESETS = 10;
+constexpr inline size_t MAX_NUM_BANDS = 5;
+constexpr inline size_t MAX_CALL_SIZE = 256;
+constexpr inline int BASS_BOOST_CUP_LOAD_ARM9E = 150; // Expressed in 0.1 MIPS
+constexpr inline int VIRTUALIZER_CUP_LOAD_ARM9E = 120; // Expressed in 0.1 MIPS
+constexpr inline int EQUALIZER_CUP_LOAD_ARM9E = 220; // Expressed in 0.1 MIPS
+constexpr inline int VOLUME_CUP_LOAD_ARM9E = 0; // Expressed in 0.1 MIPS
+constexpr inline int BUNDLE_MEM_USAGE = 25; // Expressed in kB
+constexpr inline int PRESET_CUSTOM = -1;
+
+static const std::vector<Equalizer::BandFrequency> kEqBandFrequency = {{0, 30000, 120000},
+ {1, 120001, 460000},
+ {2, 460001, 1800000},
+ {3, 1800001, 7000000},
+ {4, 7000001, 20000000}};
+
+/*
+Frequencies in Hz
+Note: If these frequencies change, please update LimitLevel values accordingly.
+*/
+constexpr inline std::array<uint16_t, MAX_NUM_BANDS> kPresetsFrequencies = {60, 230, 910, 3600,
+ 14000};
+
+/* Q factor multiplied by 100 */
+constexpr inline std::array<uint16_t, MAX_NUM_BANDS> kPresetsQFactors = {96, 96, 96, 96, 96};
+
+constexpr inline std::array<std::array<int16_t, MAX_NUM_BANDS>, MAX_NUM_PRESETS> kSoftPresets = {
+ {{3, 0, 0, 0, 3}, /* Normal Preset */
+ {5, 3, -2, 4, 4}, /* Classical Preset */
+ {6, 0, 2, 4, 1}, /* Dance Preset */
+ {0, 0, 0, 0, 0}, /* Flat Preset */
+ {3, 0, 0, 2, -1}, /* Folk Preset */
+ {4, 1, 9, 3, 0}, /* Heavy Metal Preset */
+ {5, 3, 0, 1, 3}, /* Hip Hop Preset */
+ {4, 2, -2, 2, 5}, /* Jazz Preset */
+ {-1, 2, 5, 1, -2}, /* Pop Preset */
+ {5, 3, -1, 3, 5}}}; /* Rock Preset */
+
+static const std::vector<Equalizer::Preset> kEqPresets = {
+ {0, "Normal"}, {1, "Classical"}, {2, "Dance"}, {3, "Flat"}, {4, "Folk"},
+ {5, "Heavy Metal"}, {6, "Hip Hop"}, {7, "Jazz"}, {8, "Pop"}, {9, "Rock"}};
+
+static const Equalizer::Capability kEqCap = {.bandFrequencies = kEqBandFrequency,
+ .presets = kEqPresets};
+
+static const Descriptor kEqualizerDesc = {
+ .common = {.id = {.type = EqualizerTypeUUID,
+ .uuid = EqualizerBundleImplUUID,
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL},
+ .name = "EqualizerBundle",
+ .implementor = "NXP Software Ltd."},
+ .capability = Capability::make<Capability::equalizer>(kEqCap)};
+
+// TODO: add descriptors for other bundle effect types here.
+static const Descriptor kVirtualizerDesc;
+static const Descriptor kBassBoostDesc;
+static const Descriptor kVolumeDesc;
+
+/* The following tables have been computed using the actual levels measured by the output of
+ * white noise or pink noise (IEC268-1) for the EQ and BassBoost Effects. These are estimates of
+ * the actual energy that 'could' be present in the given band.
+ * If the frequency values in EQNB_5BandPresetsFrequencies change, these values might need to be
+ * updated.
+ */
+constexpr inline std::array<float, MAX_NUM_BANDS> kBandEnergyCoefficient = {7.56, 9.69, 9.59, 7.37,
+ 2.88};
+
+constexpr inline std::array<float, MAX_NUM_BANDS - 1> kBandEnergyCrossCoefficient = {126.0, 115.0,
+ 125.0, 104.0};
+
+constexpr inline std::array<float, MAX_NUM_BANDS> kBassBoostEnergyCrossCoefficient = {
+ 221.21, 208.10, 28.16, 0.0, 0.0};
+
+constexpr inline float kBassBoostEnergyCoefficient = 9.00;
+
+constexpr inline float kVirtualizerContribution = 1.9;
+
+enum class BundleEffectType {
+ BASS_BOOST,
+ VIRTUALIZER,
+ EQUALIZER,
+ VOLUME,
+};
+
+inline std::ostream& operator<<(std::ostream& out, const BundleEffectType& type) {
+ switch (type) {
+ case BundleEffectType::BASS_BOOST:
+ return out << "BASS_BOOST";
+ case BundleEffectType::VIRTUALIZER:
+ return out << "VIRTUALIZER";
+ case BundleEffectType::EQUALIZER:
+ return out << "EQUALIZER";
+ case BundleEffectType::VOLUME:
+ return out << "VOLUME";
+ }
+ return out << "EnumBundleEffectTypeError";
+}
+
+inline std::ostream& operator<<(std::ostream& out, const LVM_ReturnStatus_en& status) {
+ switch (status) {
+ case LVM_SUCCESS:
+ return out << "LVM_SUCCESS";
+ case LVM_ALIGNMENTERROR:
+ return out << "LVM_ALIGNMENTERROR";
+ case LVM_NULLADDRESS:
+ return out << "LVM_NULLADDRESS";
+ case LVM_OUTOFRANGE:
+ return out << "LVM_OUTOFRANGE";
+ case LVM_INVALIDNUMSAMPLES:
+ return out << "LVM_INVALIDNUMSAMPLES";
+ case LVM_WRONGAUDIOTIME:
+ return out << "LVM_WRONGAUDIOTIME";
+ case LVM_ALGORITHMDISABLED:
+ return out << "LVM_ALGORITHMDISABLED";
+ case LVM_ALGORITHMPSA:
+ return out << "LVM_ALGORITHMPSA";
+ case LVM_RETURNSTATUS_DUMMY:
+ return out << "LVM_RETURNSTATUS_DUMMY";
+ }
+ return out << "EnumLvmRetStatusError";
+}
+
+#define GOTO_IF_LVM_ERROR(status, tag, log) \
+ do { \
+ LVM_ReturnStatus_en temp = (status); \
+ if (temp != LVM_SUCCESS) { \
+ LOG(ERROR) << __func__ << " return status: " << temp << " " << (log); \
+ goto tag; \
+ } \
+ } while (0)
+
+} // namespace lvm
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
new file mode 100644
index 0000000..8272462
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "EffectBundleAidl"
+#include <Utils.h>
+#include <algorithm>
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+#include <audio_effects/effect_bassboost.h>
+#include <audio_effects/effect_equalizer.h>
+#include <audio_effects/effect_virtualizer.h>
+
+#include "EffectBundleAidl.h"
+#include <LVM.h>
+#include <limits.h>
+
+using aidl::android::hardware::audio::effect::EffectBundleAidl;
+using aidl::android::hardware::audio::effect::EqualizerBundleImplUUID;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (uuid == nullptr || *uuid != EqualizerBundleImplUUID) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<EffectBundleAidl>(*uuid);
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
+ if (!instanceSp) {
+ LOG(ERROR) << __func__ << "nullInstance";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ State state;
+ ndk::ScopedAStatus status = instanceSp->getState(&state);
+ if (!status.isOk() || State::INIT != state) {
+ LOG(ERROR) << __func__ << " instance " << instanceSp.get()
+ << " in state: " << toString(state) << ", status: " << status.getDescription();
+ return EX_ILLEGAL_STATE;
+ }
+ LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+EffectBundleAidl::EffectBundleAidl(const AudioUuid& uuid) {
+ LOG(DEBUG) << __func__ << uuid.toString();
+ if (uuid == EqualizerBundleImplUUID) {
+ mType = lvm::BundleEffectType::EQUALIZER;
+ mDescriptor = &lvm::kEqualizerDesc;
+ } else {
+ // TODO: add other bundle effect types here.
+ LOG(ERROR) << __func__ << uuid.toString() << " not supported yet!";
+ }
+}
+
+EffectBundleAidl::~EffectBundleAidl() {
+ releaseContext();
+ LOG(DEBUG) << __func__;
+}
+
+ndk::ScopedAStatus EffectBundleAidl::getDescriptor(Descriptor* _aidl_return) {
+ LOG(DEBUG) << _aidl_return->toString();
+ RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+ *_aidl_return = *mDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterCommon(const Parameter& param) {
+ std::lock_guard lg(mMutex);
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ auto tag = param.getTag();
+ switch (tag) {
+ case Parameter::common:
+ RETURN_IF(mContext->setCommon(param.get<Parameter::common>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setCommFailed");
+ break;
+ case Parameter::deviceDescription:
+ RETURN_IF(mContext->setOutputDevice(param.get<Parameter::deviceDescription>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setDeviceFailed");
+ break;
+ case Parameter::mode:
+ RETURN_IF(mContext->setAudioMode(param.get<Parameter::mode>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setModeFailed");
+ break;
+ case Parameter::source:
+ RETURN_IF(mContext->setAudioSource(param.get<Parameter::source>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setSourceFailed");
+ break;
+ case Parameter::volumeStereo:
+ RETURN_IF(mContext->setVolumeStereo(param.get<Parameter::volumeStereo>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setVolumeStereoFailed");
+ break;
+ default: {
+ LOG(ERROR) << __func__ << " unsupportedParameterTag " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "commonParamNotSupported");
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterSpecific(const Parameter::Specific& specific) {
+ LOG(DEBUG) << __func__ << " specific " << specific.toString();
+ auto tag = specific.getTag();
+ RETURN_IF(tag != Parameter::Specific::equalizer, EX_ILLEGAL_ARGUMENT,
+ "specificParamNotSupported");
+ RETURN_IF(mContext == nullptr, EX_NULL_POINTER , "nullContext");
+
+ auto& eq = specific.get<Parameter::Specific::equalizer>();
+ auto eqTag = eq.getTag();
+ switch (eqTag) {
+ case Equalizer::preset:
+ RETURN_IF(mContext->setEqualizerPreset(eq.get<Equalizer::preset>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setBandLevelsFailed");
+ break;
+ case Equalizer::bandLevels:
+ RETURN_IF(mContext->setEqualizerBandLevels(eq.get<Equalizer::bandLevels>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setBandLevelsFailed");
+ break;
+ default:
+ LOG(ERROR) << __func__ << " unsupported parameter " << specific.toString();
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "eqTagNotSupported");
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectBundleAidl::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::equalizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ auto eqId = id.get<Parameter::Id::equalizerTag>();
+ auto eqIdTag = eqId.getTag();
+ switch (eqIdTag) {
+ case Equalizer::Id::commonTag:
+ return getParameterEqualizer(eqId.get<Equalizer::Id::commonTag>(), specific);
+ default:
+ LOG(ERROR) << __func__ << " tag " << toString(eqIdTag) << " not supported";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "EqualizerTagNotSupported");
+ }
+}
+
+ndk::ScopedAStatus EffectBundleAidl::getParameterEqualizer(const Equalizer::Tag& tag,
+ Parameter::Specific* specific) {
+ std::lock_guard lg(mMutex);
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ Equalizer eqParam;
+ switch (tag) {
+ case Equalizer::bandLevels: {
+ eqParam.set<Equalizer::bandLevels>(mContext->getEqualizerBandLevels());
+ break;
+ }
+ case Equalizer::preset: {
+ eqParam.set<Equalizer::preset>(mContext->getEqualizerPreset());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "unsupportedTag");
+ }
+ }
+
+ specific->set<Parameter::Specific::equalizer>(eqParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> EffectBundleAidl::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ return mContext;
+ }
+
+ // GlobalSession is a singleton
+ mContext =
+ GlobalSession::getGlobalSession().createSession(mType, 1 /* statusFmqDepth */, common);
+ return mContext;
+}
+
+RetCode EffectBundleAidl::releaseContext() {
+ if (mContext) {
+ GlobalSession::getGlobalSession().releaseSession(mType, mContext->getSessionId());
+ mContext.reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status EffectBundleAidl::effectProcessImpl(float* in, float* out, int sampleToProcess) {
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << sampleToProcess;
+ if (!mContext) {
+ LOG(ERROR) << __func__ << " nullContext";
+ return {EX_NULL_POINTER, 0, 0};
+ }
+
+ auto frameSize = mContext->getInputFrameSize();
+ if (0 == frameSize) {
+ LOG(ERROR) << __func__ << " frameSizeIs0";
+ return {EX_ILLEGAL_ARGUMENT, 0, 0};
+ }
+
+ LOG(DEBUG) << __func__ << " start processing";
+ LVM_UINT16 frames = sampleToProcess * sizeof(float) / frameSize;
+ LVM_ReturnStatus_en lvmStatus = LVM_Process(mContext->getLvmInstance(), in, out, frames, 0);
+ if (lvmStatus != LVM_SUCCESS) {
+ LOG(ERROR) << __func__ << lvmStatus;
+ return {EX_UNSUPPORTED_OPERATION, 0, 0};
+ }
+ LOG(DEBUG) << __func__ << " done processing";
+ return {STATUS_OK, sampleToProcess, sampleToProcess};
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
new file mode 100644
index 0000000..f10003e
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include <functional>
+#include <map>
+#include <memory>
+#include <mutex>
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <android-base/logging.h>
+
+#include "effect-impl/EffectImpl.h"
+#include "effect-impl/EffectUUID.h"
+
+#include "BundleContext.h"
+#include "BundleTypes.h"
+#include "GlobalSession.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class EffectBundleAidl final : public EffectImpl {
+ public:
+ explicit EffectBundleAidl(const AudioUuid& uuid);
+ ~EffectBundleAidl() override;
+
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterCommon(const Parameter& param) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+ IEffect::Status effectProcessImpl(float *in, float *out, int process) override;
+
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ RetCode releaseContext() override;
+
+ ndk::ScopedAStatus commandStart() override {
+ mContext->enable();
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus commandStop() override {
+ mContext->disable();
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus commandReset() override {
+ mContext->disable();
+ return ndk::ScopedAStatus::ok();
+ }
+
+ private:
+ const Descriptor* mDescriptor;
+ lvm::BundleEffectType mType = lvm::BundleEffectType::EQUALIZER;
+ std::shared_ptr<BundleContext> mContext;
+
+ int mPreset = lvm::PRESET_CUSTOM;
+ size_t mInputFrameSize, mOutputFrameSize;
+
+ // Equalizer
+ int mCurPresetIdx = lvm::PRESET_CUSTOM; /* Current preset being used */
+ int32_t mBandGaindB[lvm::MAX_NUM_BANDS];
+
+ RetCode setEqPreset(const int& presetIdx);
+ int getEqPreset() const { return mCurPresetIdx; }
+
+ RetCode setEqBandLevels(const std::vector<Equalizer::BandLevel>& bandLevels);
+ std::vector<Equalizer::BandLevel> getEqBandLevels() const;
+
+ IEffect::Status status(binder_status_t status, size_t consumed, size_t produced);
+ ndk::ScopedAStatus getParameterEqualizer(const Equalizer::Tag& tag,
+ Parameter::Specific* specific);
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Aidl/GlobalSession.h b/media/libeffects/lvm/wrapper/Aidl/GlobalSession.h
new file mode 100644
index 0000000..9226274
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Aidl/GlobalSession.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <algorithm>
+#include <memory>
+#include <unordered_map>
+
+#include <android-base/logging.h>
+
+#include "BundleContext.h"
+#include "BundleTypes.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+/**
+ * @brief Maintain all effect bundle sessions.
+ *
+ * Sessions are identified with the session ID, maximum of MAX_BUNDLE_SESSIONS is supported by the
+ * bundle implementation.
+ */
+class GlobalSession {
+ public:
+ static GlobalSession& getGlobalSession() {
+ static GlobalSession instance;
+ return instance;
+ }
+
+ bool isSessionIdExist(int sessionId) const { return mSessionMap.count(sessionId); }
+
+ static bool findBundleTypeInList(std::vector<std::shared_ptr<BundleContext>>& list,
+ const lvm::BundleEffectType& type, bool remove = false) {
+ auto itor = std::find_if(list.begin(), list.end(),
+ [type](const std::shared_ptr<BundleContext>& bundle) {
+ return bundle ? bundle->getBundleType() == type : false;
+ });
+ if (itor == list.end()) {
+ return false;
+ }
+ if (remove && *itor) {
+ (*itor)->deInit();
+ list.erase(itor);
+ }
+ return true;
+ }
+
+ /**
+ * Create a certain type of BundleContext in shared_ptr container, each session must not have
+ * more than one session for each type.
+ */
+ std::shared_ptr<BundleContext> createSession(const lvm::BundleEffectType& type, int statusDepth,
+ const Parameter::Common& common) {
+ int sessionId = common.session;
+ LOG(DEBUG) << __func__ << type << " with sessionId " << sessionId;
+ std::lock_guard lg(mMutex);
+ if (mSessionMap.count(sessionId) == 0 && mSessionMap.size() >= MAX_BUNDLE_SESSIONS) {
+ LOG(ERROR) << __func__ << " exceed max bundle session";
+ return nullptr;
+ }
+
+ if (mSessionMap.count(sessionId)) {
+ if (findBundleTypeInList(mSessionMap[sessionId], type)) {
+ LOG(ERROR) << __func__ << type << " already exist in session " << sessionId;
+ return nullptr;
+ }
+ }
+
+ auto& list = mSessionMap[sessionId];
+ auto context = std::make_shared<BundleContext>(statusDepth, common, type);
+ RETURN_VALUE_IF(!context, nullptr, "failedToCreateContext");
+
+ RetCode ret = context->init();
+ if (RetCode::SUCCESS != ret) {
+ LOG(ERROR) << __func__ << " context init ret " << ret;
+ return nullptr;
+ }
+ list.push_back(context);
+ return context;
+ }
+
+ void releaseSession(const lvm::BundleEffectType& type, int sessionId) {
+ LOG(DEBUG) << __func__ << type << " sessionId " << sessionId;
+ std::lock_guard lg(mMutex);
+ if (mSessionMap.count(sessionId)) {
+ auto& list = mSessionMap[sessionId];
+ if (!findBundleTypeInList(list, type, true /* remove */)) {
+ LOG(ERROR) << __func__ << " can't find " << type << "in session " << sessionId;
+ return;
+ }
+ if (list.size() == 0) {
+ mSessionMap.erase(sessionId);
+ }
+ }
+ }
+
+ private:
+ // Lock for mSessionMap access.
+ std::mutex mMutex;
+ // Max session number supported.
+ static constexpr int MAX_BUNDLE_SESSIONS = 32;
+ std::unordered_map<int /* session ID */, std::vector<std::shared_ptr<BundleContext>>>
+ mSessionMap GUARDED_BY(mMutex);
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Android.bp b/media/libeffects/lvm/wrapper/Android.bp
index 1287514..a32188a 100644
--- a/media/libeffects/lvm/wrapper/Android.bp
+++ b/media/libeffects/lvm/wrapper/Android.bp
@@ -100,3 +100,29 @@
integer_overflow: true,
},
}
+
+cc_library_shared {
+ name: "libbundleaidl",
+ srcs: [
+ "Aidl/BundleContext.cpp",
+ "Aidl/EffectBundleAidl.cpp",
+ ":effectCommonFile",
+ ],
+ static_libs: ["libmusicbundle"],
+ defaults: [
+ "aidlaudioservice_defaults",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ "latest_android_media_audio_common_types_ndk_shared",
+ ],
+ local_include_dirs: ["Aidl"],
+ header_libs: [
+ "libaudioeffects",
+ "libhardware_headers",
+ ],
+ shared_libs: [
+ "liblog",
+ ],
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
\ No newline at end of file