diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Equalizer.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Equalizer.aidl index d825eac914..ea63de57d2 100644 --- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Equalizer.aidl +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Equalizer.aidl @@ -37,6 +37,7 @@ union Equalizer { android.hardware.audio.effect.VendorExtension vendorExtension; android.hardware.audio.effect.Equalizer.BandLevel[] bandLevels; int preset; + int[] centerFreqMh; @VintfStability union Id { int vendorExtensionTag; diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/HapticGenerator.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/HapticGenerator.aidl index 20f7e024f3..35186c381e 100644 --- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/HapticGenerator.aidl +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/HapticGenerator.aidl @@ -48,9 +48,9 @@ union HapticGenerator { } @Backing(type="int") @VintfStability enum VibratorScale { - MUTE = (-100), - VERY_LOW = (-2), - LOW = (-1), + MUTE = (-100) /* -100 */, + VERY_LOW = (-2) /* -2 */, + LOW = (-1) /* -1 */, NONE = 0, HIGH = 1, VERY_HIGH = 2, diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/NoiseSuppression.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/NoiseSuppression.aidl index 1cf92ef8f4..153e0213bc 100644 --- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/NoiseSuppression.aidl +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/NoiseSuppression.aidl @@ -36,6 +36,7 @@ package android.hardware.audio.effect; union NoiseSuppression { android.hardware.audio.effect.VendorExtension vendor; android.hardware.audio.effect.NoiseSuppression.Level level; + android.hardware.audio.effect.NoiseSuppression.Type type; @VintfStability union Id { int vendorExtensionTag; @@ -52,4 +53,9 @@ union NoiseSuppression { HIGH, VERY_HIGH, } + @Backing(type="int") @VintfStability + enum Type { + SINGLE_CHANNEL, + MULTI_CHANNEL, + } } diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Virtualizer.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Virtualizer.aidl index 9fdd69227c..2f367d9be1 100644 --- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Virtualizer.aidl +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Virtualizer.aidl @@ -36,10 +36,18 @@ package android.hardware.audio.effect; union Virtualizer { android.hardware.audio.effect.VendorExtension vendor; int strengthPm; + android.hardware.audio.effect.Virtualizer.ChannelAngle[] speakerAngles; + android.media.audio.common.AudioDeviceDescription device; @VintfStability union Id { int vendorExtensionTag; android.hardware.audio.effect.Virtualizer.Tag commonTag; + android.hardware.audio.effect.Virtualizer.SpeakerAnglesPayload speakerAnglesPayload; + } + @VintfStability + parcelable SpeakerAnglesPayload { + android.media.audio.common.AudioChannelLayout layout; + android.media.audio.common.AudioDeviceDescription device; } @VintfStability parcelable Capability { @@ -47,4 +55,10 @@ union Virtualizer { int maxStrengthPm; boolean strengthSupported; } + @VintfStability + parcelable ChannelAngle { + int channel; + int azimuthDegree; + int elevationDegree; + } } diff --git a/audio/aidl/android/hardware/audio/effect/Equalizer.aidl b/audio/aidl/android/hardware/audio/effect/Equalizer.aidl index 79a1c4f561..7903fde2c7 100644 --- a/audio/aidl/android/hardware/audio/effect/Equalizer.aidl +++ b/audio/aidl/android/hardware/audio/effect/Equalizer.aidl @@ -72,7 +72,7 @@ union Equalizer { } /** - * Supported minimal and maximal frequency for each band in millihertz. + * Supported minimal and maximal frequency for each band in milliHertz. */ @VintfStability parcelable BandFrequency { @@ -97,8 +97,14 @@ union Equalizer { * Level for each band. */ BandLevel[] bandLevels; + /** * Index of current preset. */ int preset; + + /** + * Get only parameter, get the center frequency for all bands in milliHertz. + */ + int[] centerFreqMh; } diff --git a/audio/aidl/android/hardware/audio/effect/NoiseSuppression.aidl b/audio/aidl/android/hardware/audio/effect/NoiseSuppression.aidl index 9969a0b581..c4baff84ce 100644 --- a/audio/aidl/android/hardware/audio/effect/NoiseSuppression.aidl +++ b/audio/aidl/android/hardware/audio/effect/NoiseSuppression.aidl @@ -68,4 +68,11 @@ union NoiseSuppression { * The NS level. */ Level level; + + /** + * Noise suppression type. + */ + @VintfStability @Backing(type="int") enum Type { SINGLE_CHANNEL, MULTI_CHANNEL } + + Type type; } diff --git a/audio/aidl/android/hardware/audio/effect/Virtualizer.aidl b/audio/aidl/android/hardware/audio/effect/Virtualizer.aidl index 5f385a65f9..fc453adde3 100644 --- a/audio/aidl/android/hardware/audio/effect/Virtualizer.aidl +++ b/audio/aidl/android/hardware/audio/effect/Virtualizer.aidl @@ -17,6 +17,8 @@ package android.hardware.audio.effect; import android.hardware.audio.effect.VendorExtension; +import android.media.audio.common.AudioChannelLayout; +import android.media.audio.common.AudioDeviceDescription; /** * Virtualizer specific definitions. An audio virtualizer is a general name for an effect to @@ -35,6 +37,7 @@ union Virtualizer { union Id { int vendorExtensionTag; Virtualizer.Tag commonTag; + SpeakerAnglesPayload speakerAnglesPayload; } /** @@ -42,6 +45,25 @@ union Virtualizer { */ VendorExtension vendor; + /** + * Payload to query speaker angles for the given channel position mask and device. + * The Virtualizer implementation must return EX_ILLEGAL_ARGUMENT if the given payload not + * supported. + */ + @VintfStability + parcelable SpeakerAnglesPayload { + /** + * Audio channel position definition. See + * android.media.audio.common.AudioChannelLayout.aidl. Only the channel position "CHANNEL_*" + * in AudioChannelLayout be used. + */ + AudioChannelLayout layout; + /** + * Audio device type. See android.media.audio.common.AudioDeviceDescription.aidl. + */ + AudioDeviceDescription device; + } + /** * Capability supported by Virtualizer implementation. */ @@ -74,4 +96,39 @@ union Virtualizer { * the 'maxStrengthPm' capability. */ int strengthPm; + + /** + * All angles are expressed in degrees and are relative to the listener. + */ + @VintfStability + parcelable ChannelAngle { + /** + * Audio channel layout, CHANNEL_* constants defined in + * android.media.audio.common.AudioChannelLayout. + */ + int channel; + + /** + * 0 is the direction the listener faces, 180 is behind the listener, and -90 is left of + * the listener. + */ + int azimuthDegree; + + /** + * 0 is the horizontal plane, +90 is above the listener, -90 is below. + */ + int elevationDegree; + } + + /** + * Get only parameter. + * A vector of angles per channel represented by azimuth and elevation (in degrees), client must + * set Parameter.Id to SpeakerAnglesPayload to get speakerAngles. + */ + ChannelAngle[] speakerAngles; + + /** + * The audio device on which virtualzation mode is forced. + */ + AudioDeviceDescription device; } diff --git a/audio/aidl/default/equalizer/EqualizerSw.cpp b/audio/aidl/default/equalizer/EqualizerSw.cpp index 984b943100..0a6ac3463c 100644 --- a/audio/aidl/default/equalizer/EqualizerSw.cpp +++ b/audio/aidl/default/equalizer/EqualizerSw.cpp @@ -150,6 +150,10 @@ ndk::ScopedAStatus EqualizerSw::getParameterEqualizer(const Equalizer::Tag& tag, eqParam.set(mContext->getEqPreset()); break; } + case Equalizer::centerFreqMh: { + eqParam.set(mContext->getCenterFreqs()); + break; + } default: { LOG(ERROR) << __func__ << " not handled tag: " << toString(tag); return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, diff --git a/audio/aidl/default/equalizer/EqualizerSw.h b/audio/aidl/default/equalizer/EqualizerSw.h index 65a80029cb..fabcfeb54c 100644 --- a/audio/aidl/default/equalizer/EqualizerSw.h +++ b/audio/aidl/default/equalizer/EqualizerSw.h @@ -68,10 +68,16 @@ class EqualizerSwContext final : public EffectContext { return bandLevels; } + std::vector getCenterFreqs() { + return {std::begin(kPresetsFrequencies), std::end(kPresetsFrequencies)}; + } + private: static const int NUM_OF_BANDS = 5; static const int NUM_OF_PRESETS = 10; static const int PRESET_CUSTOM = -1; + static constexpr std::array kPresetsFrequencies = {60, 230, 910, 3600, + 14000}; // preset band level int mPreset = PRESET_CUSTOM; int32_t mBandLevels[NUM_OF_BANDS] = {3, 0, 0, 0, 3}; diff --git a/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.cpp b/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.cpp index a36cfe00a8..51fe4ea836 100644 --- a/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.cpp +++ b/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.cpp @@ -90,10 +90,15 @@ ndk::ScopedAStatus NoiseSuppressionSw::setParameterSpecific(const Parameter::Spe switch (tag) { case NoiseSuppression::level: { RETURN_IF(mContext->setLevel(param.get()) != RetCode::SUCCESS, - EX_ILLEGAL_ARGUMENT, "levelSupported"); + EX_ILLEGAL_ARGUMENT, "levelNotSupported"); return ndk::ScopedAStatus::ok(); } - default: { + case NoiseSuppression::type: { + RETURN_IF(mContext->setType(param.get()) != RetCode::SUCCESS, + EX_ILLEGAL_ARGUMENT, "typeNotSupported"); + return ndk::ScopedAStatus::ok(); + } + case NoiseSuppression::vendor: { LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); return ndk::ScopedAStatus::fromExceptionCodeWithMessage( EX_ILLEGAL_ARGUMENT, "NoiseSuppressionTagNotSupported"); @@ -111,10 +116,11 @@ ndk::ScopedAStatus NoiseSuppressionSw::getParameterSpecific(const Parameter::Id& case NoiseSuppression::Id::commonTag: return getParameterNoiseSuppression(specificId.get(), specific); - default: + case NoiseSuppression::Id::vendorExtensionTag: { LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); return ndk::ScopedAStatus::fromExceptionCodeWithMessage( EX_ILLEGAL_ARGUMENT, "NoiseSuppressionTagNotSupported"); + } } } @@ -127,7 +133,11 @@ ndk::ScopedAStatus NoiseSuppressionSw::getParameterNoiseSuppression( param.set(mContext->getLevel()); break; } - default: { + case NoiseSuppression::type: { + param.set(mContext->getType()); + break; + } + case NoiseSuppression::vendor: { LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); return ndk::ScopedAStatus::fromExceptionCodeWithMessage( EX_ILLEGAL_ARGUMENT, "NoiseSuppressionTagNotSupported"); @@ -177,4 +187,9 @@ NoiseSuppression::Level NoiseSuppressionSwContext::getLevel() { return mLevel; } +RetCode NoiseSuppressionSwContext::setType(NoiseSuppression::Type type) { + mType = type; + return RetCode::SUCCESS; +} + } // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.h b/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.h index f39d8e5768..a851e38c0a 100644 --- a/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.h +++ b/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.h @@ -35,9 +35,12 @@ class NoiseSuppressionSwContext final : public EffectContext { RetCode setLevel(NoiseSuppression::Level level); NoiseSuppression::Level getLevel(); + RetCode setType(NoiseSuppression::Type type); + NoiseSuppression::Type getType() { return mType; } private: NoiseSuppression::Level mLevel = NoiseSuppression::Level::LOW; + NoiseSuppression::Type mType = NoiseSuppression::Type::SINGLE_CHANNEL; }; class NoiseSuppressionSw final : public EffectImpl { diff --git a/audio/aidl/default/virtualizer/VirtualizerSw.cpp b/audio/aidl/default/virtualizer/VirtualizerSw.cpp index cc51937495..08535bdc90 100644 --- a/audio/aidl/default/virtualizer/VirtualizerSw.cpp +++ b/audio/aidl/default/virtualizer/VirtualizerSw.cpp @@ -30,6 +30,8 @@ using aidl::android::hardware::audio::effect::IEffect; using aidl::android::hardware::audio::effect::kVirtualizerSwImplUUID; using aidl::android::hardware::audio::effect::State; using aidl::android::hardware::audio::effect::VirtualizerSw; +using aidl::android::media::audio::common::AudioChannelLayout; +using aidl::android::media::audio::common::AudioDeviceDescription; using aidl::android::media::audio::common::AudioUuid; extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid, @@ -93,10 +95,18 @@ ndk::ScopedAStatus VirtualizerSw::setParameterSpecific(const Parameter::Specific RETURN_IF(mContext->setVrStrength(vrParam.get()) != RetCode::SUCCESS, - EX_ILLEGAL_ARGUMENT, "strengthPmNotSupported"); + EX_ILLEGAL_ARGUMENT, "setStrengthPmFailed"); return ndk::ScopedAStatus::ok(); } - default: { + case Virtualizer::device: { + RETURN_IF(mContext->setForcedDevice(vrParam.get()) != + RetCode::SUCCESS, + EX_ILLEGAL_ARGUMENT, "setDeviceFailed"); + return ndk::ScopedAStatus::ok(); + } + case Virtualizer::speakerAngles: + FALLTHROUGH_INTENDED; + case Virtualizer::vendor: { LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, "VirtualizerTagNotSupported"); @@ -113,10 +123,13 @@ ndk::ScopedAStatus VirtualizerSw::getParameterSpecific(const Parameter::Id& id, switch (vrIdTag) { case Virtualizer::Id::commonTag: return getParameterVirtualizer(vrId.get(), specific); - default: + case Virtualizer::Id::speakerAnglesPayload: + return getSpeakerAngles(vrId.get(), specific); + case Virtualizer::Id::vendorExtensionTag: { LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, "VirtualizerTagNotSupported"); + } } } @@ -130,7 +143,13 @@ ndk::ScopedAStatus VirtualizerSw::getParameterVirtualizer(const Virtualizer::Tag vrParam.set(mContext->getVrStrength()); break; } - default: { + case Virtualizer::device: { + vrParam.set(mContext->getForcedDevice()); + break; + } + case Virtualizer::speakerAngles: + FALLTHROUGH_INTENDED; + case Virtualizer::vendor: { LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, "VirtualizerTagNotSupported"); @@ -141,6 +160,27 @@ ndk::ScopedAStatus VirtualizerSw::getParameterVirtualizer(const Virtualizer::Tag return ndk::ScopedAStatus::ok(); } +ndk::ScopedAStatus VirtualizerSw::getSpeakerAngles(const Virtualizer::SpeakerAnglesPayload payload, + Parameter::Specific* specific) { + std::vector angles; + if (::android::hardware::audio::common::getChannelCount(payload.layout) == 1) { + angles = {{.channel = (int32_t)AudioChannelLayout::CHANNEL_FRONT_LEFT, + .azimuthDegree = 0, + .elevationDegree = 0}}; + } else { + angles = {{.channel = (int32_t)AudioChannelLayout::CHANNEL_FRONT_LEFT, + .azimuthDegree = -90, + .elevationDegree = 0}, + {.channel = (int32_t)AudioChannelLayout::CHANNEL_FRONT_RIGHT, + .azimuthDegree = 90, + .elevationDegree = 0}}; + } + + Virtualizer param = Virtualizer::make(angles); + specific->set(param); + return ndk::ScopedAStatus::ok(); +} + std::shared_ptr VirtualizerSw::createContext(const Parameter::Common& common) { if (mContext) { LOG(DEBUG) << __func__ << " context already exist"; diff --git a/audio/aidl/default/virtualizer/VirtualizerSw.h b/audio/aidl/default/virtualizer/VirtualizerSw.h index 0f294cdf4f..1016ffc920 100644 --- a/audio/aidl/default/virtualizer/VirtualizerSw.h +++ b/audio/aidl/default/virtualizer/VirtualizerSw.h @@ -34,9 +34,18 @@ class VirtualizerSwContext final : public EffectContext { } RetCode setVrStrength(int strength); int getVrStrength() const { return mStrength; } + RetCode setForcedDevice( + const ::aidl::android::media::audio::common::AudioDeviceDescription& device) { + mForceDevice = device; + return RetCode::SUCCESS; + } + aidl::android::media::audio::common::AudioDeviceDescription getForcedDevice() const { + return mForceDevice; + } private: int mStrength = 0; + ::aidl::android::media::audio::common::AudioDeviceDescription mForceDevice; }; class VirtualizerSw final : public EffectImpl { @@ -68,5 +77,7 @@ class VirtualizerSw final : public EffectImpl { ndk::ScopedAStatus getParameterVirtualizer(const Virtualizer::Tag& tag, Parameter::Specific* specific); + ndk::ScopedAStatus getSpeakerAngles(const Virtualizer::SpeakerAnglesPayload payload, + Parameter::Specific* specific); }; } // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/vts/VtsHalNSTargetTest.cpp b/audio/aidl/vts/VtsHalNSTargetTest.cpp index 93ad86de43..0b922901ea 100644 --- a/audio/aidl/vts/VtsHalNSTargetTest.cpp +++ b/audio/aidl/vts/VtsHalNSTargetTest.cpp @@ -34,13 +34,14 @@ using aidl::android::hardware::audio::effect::kNoiseSuppressionTypeUUID; using aidl::android::hardware::audio::effect::NoiseSuppression; using aidl::android::hardware::audio::effect::Parameter; -enum ParamName { PARAM_INSTANCE_NAME, PARAM_LEVEL }; -using NSParamTestParam = - std::tuple, Descriptor>, NoiseSuppression::Level>; +enum ParamName { PARAM_INSTANCE_NAME, PARAM_LEVEL, PARAM_TYPE }; +using NSParamTestParam = std::tuple, Descriptor>, + NoiseSuppression::Level, NoiseSuppression::Type>; class NSParamTest : public ::testing::TestWithParam, public EffectHelper { public: - NSParamTest() : mLevel(std::get(GetParam())) { + NSParamTest() + : mLevel(std::get(GetParam())), mType(std::get(GetParam())) { std::tie(mFactory, mDescriptor) = std::get(GetParam()); } @@ -75,6 +76,7 @@ class NSParamTest : public ::testing::TestWithParam, public Ef std::shared_ptr mEffect; Descriptor mDescriptor; NoiseSuppression::Level mLevel; + NoiseSuppression::Type mType; void SetAndGetParameters() { for (auto& it : mTags) { @@ -113,10 +115,19 @@ class NSParamTest : public ::testing::TestWithParam, public Ef ns.set(level); mTags.push_back({NoiseSuppression::level, ns}); } + void addTypeParam(NoiseSuppression::Type type) { + NoiseSuppression ns; + ns.set(type); + mTags.push_back({NoiseSuppression::type, ns}); + } static std::unordered_set getLevelValues() { return {ndk::enum_range().begin(), ndk::enum_range().end()}; } + static std::unordered_set getTypeValues() { + return {ndk::enum_range().begin(), + ndk::enum_range().end()}; + } private: std::vector> mTags; @@ -128,18 +139,27 @@ TEST_P(NSParamTest, SetAndGetLevel) { SetAndGetParameters(); } +TEST_P(NSParamTest, SetAndGetType) { + EXPECT_NO_FATAL_FAILURE(addLevelParam(mLevel)); + SetAndGetParameters(); +} + INSTANTIATE_TEST_SUITE_P( NSParamTest, NSParamTest, ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors( IFactory::descriptor, kNoiseSuppressionTypeUUID)), - testing::ValuesIn(NSParamTest::getLevelValues())), + testing::ValuesIn(NSParamTest::getLevelValues()), + testing::ValuesIn(NSParamTest::getTypeValues())), [](const testing::TestParamInfo& info) { auto descriptor = std::get(info.param).second; std::string level = aidl::android::hardware::audio::effect::toString( std::get(info.param)); + std::string type = aidl::android::hardware::audio::effect::toString( + std::get(info.param)); std::string name = "Implementor_" + descriptor.common.implementor + "_name_" + descriptor.common.name + "_UUID_" + - descriptor.common.id.uuid.toString() + "_level_" + level; + descriptor.common.id.uuid.toString() + "_level_" + level + "_type_" + + type; std::replace_if( name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_'); return name;