From 82a6f7a8adc1c06510f40bc04692b2cc5ac579cf Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Mon, 31 Oct 2022 21:46:08 +0000 Subject: [PATCH 1/2] AIDL effect: Add all aosp effect parameters definition Bug: 238913361 Test: atest VtsHalAudioEffectTargetTest atest VtsHalAudioEffectFactoryTargetTest atest VtsHalEqualizerTargetTest Change-Id: Ice5cac10956c419c04be44f9142b5b2935cacf3b --- audio/aidl/Android.bp | 10 + .../hardware/audio/effect/BassBoost.aidl | 49 +++ .../hardware/audio/effect/Capability.aidl | 15 +- .../hardware/audio/effect/Descriptor.aidl | 2 +- .../hardware/audio/effect/Downmix.aidl | 53 +++ .../audio/effect/DynamicsProcessing.aidl | 116 +++++++ .../hardware/audio/effect/Equalizer.aidl | 13 +- .../audio/effect/HapticGenerator.aidl | 69 ++++ .../hardware/audio/effect/IEffect.aidl | 10 +- .../hardware/audio/effect/IFactory.aidl | 2 +- .../audio/effect/LoudnessEnhancer.aidl | 48 +++ .../hardware/audio/effect/Parameter.aidl | 42 ++- .../android/hardware/audio/effect/Reverb.aidl | 57 ++++ .../audio/effect/VendorExtension.aidl | 38 +++ .../hardware/audio/effect/Virtualizer.aidl | 49 +++ .../hardware/audio/effect/Visualizer.aidl | 86 +++++ .../android/hardware/audio/effect/Volume.aidl | 50 +++ .../hardware/audio/effect/BassBoost.aidl | 71 +++++ .../hardware/audio/effect/Capability.aidl | 27 +- .../hardware/audio/effect/Descriptor.aidl | 8 +- .../hardware/audio/effect/Downmix.aidl | 71 +++++ .../audio/effect/DynamicsProcessing.aidl | 301 ++++++++++++++++++ .../hardware/audio/effect/Equalizer.aidl | 25 +- .../audio/effect/HapticGenerator.aidl | 95 ++++++ .../hardware/audio/effect/IEffect.aidl | 18 +- .../hardware/audio/effect/IFactory.aidl | 9 +- .../audio/effect/LoudnessEnhancer.aidl | 61 ++++ .../hardware/audio/effect/Parameter.aidl | 88 ++--- .../android/hardware/audio/effect/Reverb.aidl | 92 ++++++ .../audio/effect/VendorExtension.aidl | 25 ++ .../hardware/audio/effect/Virtualizer.aidl | 72 +++++ .../hardware/audio/effect/Visualizer.aidl | 167 ++++++++++ .../android/hardware/audio/effect/Volume.aidl | 69 ++++ 33 files changed, 1807 insertions(+), 101 deletions(-) create mode 100644 audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/BassBoost.aidl create mode 100644 audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Downmix.aidl create mode 100644 audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/DynamicsProcessing.aidl create mode 100644 audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/HapticGenerator.aidl create mode 100644 audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/LoudnessEnhancer.aidl create mode 100644 audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl create mode 100644 audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/VendorExtension.aidl create mode 100644 audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Virtualizer.aidl create mode 100644 audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Visualizer.aidl create mode 100644 audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Volume.aidl create mode 100644 audio/aidl/android/hardware/audio/effect/BassBoost.aidl create mode 100644 audio/aidl/android/hardware/audio/effect/Downmix.aidl create mode 100644 audio/aidl/android/hardware/audio/effect/DynamicsProcessing.aidl create mode 100644 audio/aidl/android/hardware/audio/effect/HapticGenerator.aidl create mode 100644 audio/aidl/android/hardware/audio/effect/LoudnessEnhancer.aidl create mode 100644 audio/aidl/android/hardware/audio/effect/Reverb.aidl create mode 100644 audio/aidl/android/hardware/audio/effect/VendorExtension.aidl create mode 100644 audio/aidl/android/hardware/audio/effect/Virtualizer.aidl create mode 100644 audio/aidl/android/hardware/audio/effect/Visualizer.aidl create mode 100644 audio/aidl/android/hardware/audio/effect/Volume.aidl diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp index 4e50b7ab50..e58ae6ab9e 100644 --- a/audio/aidl/Android.bp +++ b/audio/aidl/Android.bp @@ -148,16 +148,26 @@ aidl_interface { name: "android.hardware.audio.effect", vendor_available: true, srcs: [ + "android/hardware/audio/effect/BassBoost.aidl", "android/hardware/audio/effect/Capability.aidl", "android/hardware/audio/effect/CommandId.aidl", "android/hardware/audio/effect/Descriptor.aidl", + "android/hardware/audio/effect/Downmix.aidl", + "android/hardware/audio/effect/DynamicsProcessing.aidl", "android/hardware/audio/effect/Equalizer.aidl", "android/hardware/audio/effect/Flags.aidl", + "android/hardware/audio/effect/HapticGenerator.aidl", "android/hardware/audio/effect/IEffect.aidl", "android/hardware/audio/effect/IFactory.aidl", + "android/hardware/audio/effect/LoudnessEnhancer.aidl", "android/hardware/audio/effect/Parameter.aidl", "android/hardware/audio/effect/Processing.aidl", + "android/hardware/audio/effect/Reverb.aidl", "android/hardware/audio/effect/State.aidl", + "android/hardware/audio/effect/VendorExtension.aidl", + "android/hardware/audio/effect/Virtualizer.aidl", + "android/hardware/audio/effect/Visualizer.aidl", + "android/hardware/audio/effect/Volume.aidl", ], imports: [ "android.hardware.common-V2", diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/BassBoost.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/BassBoost.aidl new file mode 100644 index 0000000000..979ebb8a3a --- /dev/null +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/BassBoost.aidl @@ -0,0 +1,49 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.audio.effect; +@VintfStability +union BassBoost { + android.hardware.audio.effect.VendorExtension vendor; + int strengthPm; + @VintfStability + union Id { + int vendorExtensionTag; + android.hardware.audio.effect.BassBoost.Tag commonTag; + } + @VintfStability + parcelable Capability { + ParcelableHolder extension; + boolean strengthSupported; + } +} diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Capability.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Capability.aidl index 11acf5e9ed..06f2bfeb33 100644 --- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Capability.aidl +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Capability.aidl @@ -34,10 +34,15 @@ package android.hardware.audio.effect; @VintfStability union Capability { - android.hardware.audio.effect.Capability.VendorEffectCapability vendor; + android.hardware.audio.effect.VendorExtension vendorExtension; + android.hardware.audio.effect.BassBoost.Capability bassBoost; + android.hardware.audio.effect.Downmix.Capability downmix; + android.hardware.audio.effect.DynamicsProcessing.Capability dynamicsProcessing; android.hardware.audio.effect.Equalizer.Capability equalizer; - @VintfStability - parcelable VendorEffectCapability { - ParcelableHolder extension; - } + android.hardware.audio.effect.HapticGenerator.Capability hapticGenerator; + android.hardware.audio.effect.LoudnessEnhancer.Capability loudnessEnhancer; + android.hardware.audio.effect.Reverb.Capability reverb; + android.hardware.audio.effect.Virtualizer.Capability virtualizer; + android.hardware.audio.effect.Visualizer.Capability visualizer; + android.hardware.audio.effect.Volume.Capability volume; } diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl index 4707011963..990d369373 100644 --- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl @@ -54,11 +54,11 @@ parcelable Descriptor { android.media.audio.common.AudioUuid type; android.media.audio.common.AudioUuid uuid; @nullable android.media.audio.common.AudioUuid proxy; - android.hardware.audio.effect.Flags flags; } @VintfStability parcelable Common { android.hardware.audio.effect.Descriptor.Identity id; + android.hardware.audio.effect.Flags flags; int cpuLoad; int memoryUsage; @utf8InCpp String name; diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Downmix.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Downmix.aidl new file mode 100644 index 0000000000..76f8ce50fe --- /dev/null +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Downmix.aidl @@ -0,0 +1,53 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.audio.effect; +@VintfStability +union Downmix { + android.hardware.audio.effect.VendorExtension vendor; + android.hardware.audio.effect.Downmix.Type type; + @VintfStability + union Id { + int vendorExtensionTag; + android.hardware.audio.effect.Downmix.Tag commonTag; + } + @VintfStability + parcelable Capability { + ParcelableHolder extension; + } + @VintfStability + enum Type { + STRIP = 0, + FOLD = 1, + } +} diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/DynamicsProcessing.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/DynamicsProcessing.aidl new file mode 100644 index 0000000000..ed4dc80dc7 --- /dev/null +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/DynamicsProcessing.aidl @@ -0,0 +1,116 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.audio.effect; +@VintfStability +union DynamicsProcessing { + android.hardware.audio.effect.VendorExtension vendorExtension; + android.hardware.audio.effect.DynamicsProcessing.EngineArchitecture engineArchitecture; + android.hardware.audio.effect.DynamicsProcessing.BandChannelConfig preEq; + android.hardware.audio.effect.DynamicsProcessing.BandChannelConfig postEq; + android.hardware.audio.effect.DynamicsProcessing.EqBandConfig preEqBand; + android.hardware.audio.effect.DynamicsProcessing.EqBandConfig postEqBand; + android.hardware.audio.effect.DynamicsProcessing.BandChannelConfig mbc; + android.hardware.audio.effect.DynamicsProcessing.MbcBandConfig mbcBand; + android.hardware.audio.effect.DynamicsProcessing.LimiterConfig limiter; + float inputGainDb; + @VintfStability + union Id { + int vendorExtensionTag; + android.hardware.audio.effect.DynamicsProcessing.Tag commonTag; + } + @VintfStability + parcelable Capability { + ParcelableHolder extension; + } + enum ResolutionPreference { + FAVOR_FREQUENCY_RESOLUTION = 0, + FAVOR_TIME_RESOLUTION = 1, + } + @VintfStability + parcelable BandEnablement { + boolean inUse; + int bandCount; + } + @VintfStability + parcelable EngineArchitecture { + android.hardware.audio.effect.DynamicsProcessing.ResolutionPreference resolutionPreference = android.hardware.audio.effect.DynamicsProcessing.ResolutionPreference.FAVOR_FREQUENCY_RESOLUTION; + float preferredFrameDurationMs; + android.hardware.audio.effect.DynamicsProcessing.BandEnablement preEqBand; + android.hardware.audio.effect.DynamicsProcessing.BandEnablement postEqBand; + android.hardware.audio.effect.DynamicsProcessing.BandEnablement mbcBand; + boolean limiterInUse; + } + @VintfStability + parcelable BandChannelConfig { + int channel; + android.hardware.audio.effect.DynamicsProcessing.BandEnablement enablement; + } + @VintfStability + parcelable EqBandConfig { + int channel; + int band; + boolean enable; + float cutoffFrequency; + float gain; + } + @VintfStability + parcelable MbcBandConfig { + int channel; + int band; + boolean enable; + float cutoffFrequencyHz; + float gainDb; + float attackTimeMs; + float releaseTimeMs; + float ratio; + float thresholdDb; + float kneeWidthDb; + float noiseGateThresholdDb; + float expanderRatio; + float preGainDb; + float postGainDb; + } + @VintfStability + parcelable LimiterConfig { + int channel; + boolean enable; + boolean inUse; + int linkGroup; + float attackTimeMs; + float releaseTimeMs; + float ratio; + float thresholdDb; + float postGainDb; + } +} 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 f7af30058e..d825eac914 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 @@ -34,12 +34,13 @@ package android.hardware.audio.effect; @VintfStability union Equalizer { - android.hardware.audio.effect.Equalizer.VendorExtension vendor; + android.hardware.audio.effect.VendorExtension vendorExtension; android.hardware.audio.effect.Equalizer.BandLevel[] bandLevels; int preset; @VintfStability - parcelable VendorExtension { - ParcelableHolder extension; + union Id { + int vendorExtensionTag; + android.hardware.audio.effect.Equalizer.Tag commonTag; } @VintfStability parcelable Capability { @@ -50,13 +51,13 @@ union Equalizer { @VintfStability parcelable BandLevel { int index; - int level; + int levelMb; } @VintfStability parcelable BandFrequency { int index; - int min; - int max; + int minMh; + int maxMh; } @VintfStability parcelable Preset { 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 new file mode 100644 index 0000000000..40a8d72c87 --- /dev/null +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/HapticGenerator.aidl @@ -0,0 +1,69 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.audio.effect; +@VintfStability +union HapticGenerator { + android.hardware.audio.effect.VendorExtension vendorExtension; + android.hardware.audio.effect.HapticGenerator.HapticScale hapticScale; + android.hardware.audio.effect.HapticGenerator.VibratorInformation vibratorInfo; + @VintfStability + union Id { + int vendorExtensionTag; + android.hardware.audio.effect.HapticGenerator.Tag commonTag; + } + @VintfStability + parcelable Capability { + android.hardware.audio.effect.VendorExtension extension; + } + @Backing(type="int") @VintfStability + enum VibratorScale { + MUTE = -100, + VERY_LOW = -2, + LOW = -1, + NONE = 0, + HIGH = 1, + VERY_HIGH = 2, + } + @VintfStability + parcelable HapticScale { + int id; + android.hardware.audio.effect.HapticGenerator.VibratorScale scale = android.hardware.audio.effect.HapticGenerator.VibratorScale.MUTE; + } + @VintfStability + parcelable VibratorInformation { + float resonantFrequencyHz; + float qFactor; + float maxAmplitude; + } +} diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IEffect.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IEffect.aidl index e5c96f5164..8c196e7abf 100644 --- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IEffect.aidl +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IEffect.aidl @@ -34,7 +34,7 @@ package android.hardware.audio.effect; @VintfStability interface IEffect { - android.hardware.audio.effect.IEffect.OpenEffectReturn open(in android.hardware.audio.effect.Parameter.Common common, in android.hardware.audio.effect.Parameter.Specific specific); + android.hardware.audio.effect.IEffect.OpenEffectReturn open(in android.hardware.audio.effect.Parameter.Common common, in @nullable android.hardware.audio.effect.Parameter.Specific specific); void close(); android.hardware.audio.effect.Descriptor getDescriptor(); void command(in android.hardware.audio.effect.CommandId commandId); @@ -44,13 +44,13 @@ interface IEffect { @FixedSize @VintfStability parcelable Status { int status; - int fmqByteConsumed; - int fmqByteProduced; + int fmqConsumed; + int fmqProduced; } @VintfStability parcelable OpenEffectReturn { android.hardware.common.fmq.MQDescriptor statusMQ; - android.hardware.common.fmq.MQDescriptor inputDataMQ; - android.hardware.common.fmq.MQDescriptor outputDataMQ; + android.hardware.common.fmq.MQDescriptor inputDataMQ; + android.hardware.common.fmq.MQDescriptor outputDataMQ; } } diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IFactory.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IFactory.aidl index a22c591cd3..5b85d33a29 100644 --- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IFactory.aidl +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IFactory.aidl @@ -34,7 +34,7 @@ package android.hardware.audio.effect; @VintfStability interface IFactory { - android.hardware.audio.effect.Descriptor.Identity[] queryEffects(in @nullable android.media.audio.common.AudioUuid type, in @nullable android.media.audio.common.AudioUuid implementation); + android.hardware.audio.effect.Descriptor.Identity[] queryEffects(in @nullable android.media.audio.common.AudioUuid type, in @nullable android.media.audio.common.AudioUuid implementation, in @nullable android.media.audio.common.AudioUuid proxy); android.hardware.audio.effect.Processing[] queryProcessing(in @nullable android.hardware.audio.effect.Processing.Type type); android.hardware.audio.effect.IEffect createEffect(in android.media.audio.common.AudioUuid implUuid); void destroyEffect(in android.hardware.audio.effect.IEffect handle); diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/LoudnessEnhancer.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/LoudnessEnhancer.aidl new file mode 100644 index 0000000000..5c6ca16449 --- /dev/null +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/LoudnessEnhancer.aidl @@ -0,0 +1,48 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.audio.effect; +@VintfStability +union LoudnessEnhancer { + android.hardware.audio.effect.VendorExtension vendor; + int gainMb; + @VintfStability + union Id { + int vendorExtensionTag; + android.hardware.audio.effect.LoudnessEnhancer.Tag commonTag; + } + @VintfStability + parcelable Capability { + android.hardware.audio.effect.VendorExtension extension; + } +} diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl index 547112a6ae..321c286fca 100644 --- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl @@ -35,18 +35,25 @@ package android.hardware.audio.effect; @VintfStability union Parameter { android.hardware.audio.effect.Parameter.Common common; - android.media.audio.common.AudioDeviceType device; + android.media.audio.common.AudioDeviceDescription deviceDescription; android.media.audio.common.AudioMode mode; android.media.audio.common.AudioSource source; - android.hardware.audio.effect.Parameter.Volume volume; - boolean offload; - android.hardware.audio.effect.Parameter.VendorEffectParameter vendorEffect; + android.hardware.audio.effect.Parameter.VolumeStereo volumeStereo; android.hardware.audio.effect.Parameter.Specific specific; @VintfStability union Id { - int commonTag; - int vendorTag; - android.hardware.audio.effect.Parameter.Specific.Id specificId; + int vendorEffectTag; + android.hardware.audio.effect.BassBoost.Id bassBoostTag; + android.hardware.audio.effect.Downmix.Id downmixTag; + android.hardware.audio.effect.DynamicsProcessing.Id dynamicsProcessingTag; + android.hardware.audio.effect.Equalizer.Id equalizerTag; + android.hardware.audio.effect.HapticGenerator.Id hapticGeneratorTag; + android.hardware.audio.effect.LoudnessEnhancer.Id loudnessEnhancerTag; + android.hardware.audio.effect.Reverb.Id reverbTag; + android.hardware.audio.effect.Virtualizer.Id virtualizerTag; + android.hardware.audio.effect.Visualizer.Id visualizerTag; + android.hardware.audio.effect.Volume.Id volumeTag; + android.hardware.audio.effect.Parameter.Tag commonTag; } @VintfStability parcelable Common { @@ -56,21 +63,22 @@ union Parameter { android.media.audio.common.AudioConfig output; } @VintfStability - parcelable Volume { + parcelable VolumeStereo { float left; float right; } @VintfStability - parcelable VendorEffectParameter { - ParcelableHolder extension; - } - @VintfStability union Specific { - android.hardware.audio.effect.Parameter.Specific.Id id; + android.hardware.audio.effect.VendorExtension vendorEffect; + android.hardware.audio.effect.BassBoost bassBoost; + android.hardware.audio.effect.Downmix downmix; + android.hardware.audio.effect.DynamicsProcessing dynamicsProcessing; android.hardware.audio.effect.Equalizer equalizer; - @VintfStability - union Id { - android.hardware.audio.effect.Equalizer.Tag equalizerTag = android.hardware.audio.effect.Equalizer.Tag.vendor; - } + android.hardware.audio.effect.LoudnessEnhancer loudnessEnhancer; + android.hardware.audio.effect.HapticGenerator hapticGenerator; + android.hardware.audio.effect.Reverb reverb; + android.hardware.audio.effect.Virtualizer virtualizer; + android.hardware.audio.effect.Visualizer visualizer; + android.hardware.audio.effect.Volume volume; } } diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl new file mode 100644 index 0000000000..8ad4848368 --- /dev/null +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl @@ -0,0 +1,57 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.audio.effect; +@VintfStability +union Reverb { + android.hardware.audio.effect.VendorExtension vendor; + int roomLevelMb; + int roomHfLevelMb; + int decayTimeMs; + int decayHfRatioPm; + int levelMb; + int delayMs; + int diffusionPm; + int densityPm; + boolean bypass; + @VintfStability + union Id { + int vendorExtensionTag; + android.hardware.audio.effect.Reverb.Tag commonTag; + } + @VintfStability + parcelable Capability { + android.hardware.audio.effect.VendorExtension extension; + int maxDecayTimeMs; + } +} diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/VendorExtension.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/VendorExtension.aidl new file mode 100644 index 0000000000..b806334a90 --- /dev/null +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/VendorExtension.aidl @@ -0,0 +1,38 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.audio.effect; +@VintfStability +parcelable VendorExtension { + ParcelableHolder extension; +} 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 new file mode 100644 index 0000000000..d4fb9e0110 --- /dev/null +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Virtualizer.aidl @@ -0,0 +1,49 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.audio.effect; +@VintfStability +union Virtualizer { + android.hardware.audio.effect.VendorExtension vendor; + int strengthPm; + @VintfStability + union Id { + int vendorExtensionTag; + android.hardware.audio.effect.Virtualizer.Tag commonTag; + } + @VintfStability + parcelable Capability { + android.hardware.audio.effect.VendorExtension extension; + boolean strengthSupported; + } +} diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Visualizer.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Visualizer.aidl new file mode 100644 index 0000000000..9ee19f0e49 --- /dev/null +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Visualizer.aidl @@ -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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.audio.effect; +@VintfStability +union Visualizer { + android.hardware.audio.effect.Visualizer.Id id; + android.hardware.audio.effect.VendorExtension vendor; + android.hardware.audio.effect.Visualizer.GetOnlyParameters getOnlyParameters; + android.hardware.audio.effect.Visualizer.SetOnlyParameters setOnlyParameters; + int captureSizeBytes; + android.hardware.audio.effect.Visualizer.ScalingMode scalingMode; + android.hardware.audio.effect.Visualizer.MeasurementMode measurementMode; + @VintfStability + union Id { + int vendorExtensionTag; + android.hardware.audio.effect.Visualizer.GetOnlyParameters.Tag getOnlyParamTag; + android.hardware.audio.effect.Visualizer.SetOnlyParameters.Tag setOnlyParamTag; + android.hardware.audio.effect.Visualizer.Tag commonTag; + } + @VintfStability + parcelable Capability { + android.hardware.audio.effect.VendorExtension extension; + int maxLatencyMs; + android.hardware.audio.effect.Visualizer.CaptureSizeRange captureSizeRange; + } + @VintfStability + parcelable CaptureSizeRange { + int minBytes; + int maxBytes; + } + @VintfStability + enum ScalingMode { + NORMALIZED = 0, + AS_PLAYED = 1, + } + @VintfStability + enum MeasurementMode { + NONE = 0, + PEAK_RMS = 1, + } + @VintfStability + union GetOnlyParameters { + android.hardware.audio.effect.Visualizer.GetOnlyParameters.Measurement measurement; + byte[] captureBytes; + @VintfStability + parcelable Measurement { + int rms; + int peak; + } + } + @VintfStability + union SetOnlyParameters { + int latencyMs; + } +} diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Volume.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Volume.aidl new file mode 100644 index 0000000000..8c836b03a1 --- /dev/null +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Volume.aidl @@ -0,0 +1,50 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.audio.effect; +@VintfStability +union Volume { + android.hardware.audio.effect.VendorExtension vendor; + int levelDb; + boolean mute; + @VintfStability + union Id { + int vendorExtensionTag; + android.hardware.audio.effect.Volume.Tag commonTag; + } + @VintfStability + parcelable Capability { + android.hardware.audio.effect.VendorExtension extension; + int maxLevel; + } +} diff --git a/audio/aidl/android/hardware/audio/effect/BassBoost.aidl b/audio/aidl/android/hardware/audio/effect/BassBoost.aidl new file mode 100644 index 0000000000..810c1889d0 --- /dev/null +++ b/audio/aidl/android/hardware/audio/effect/BassBoost.aidl @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package android.hardware.audio.effect; + +import android.hardware.audio.effect.VendorExtension; + +/** + * Bass boost is an audio effect to boost or amplify low frequencies of the sound. It is comparable + * to a simple equalizer but limited to one band amplification in the low frequency range. + * + * All parameters defined in union BassBoost must be gettable and settable. The capabilities defined + * in BassBoost.Capability can only acquired with IEffect.getDescriptor() and not settable. + */ +@VintfStability +union BassBoost { + /** + * Effect parameter tag to identify the parameters for getParameter(). + */ + @VintfStability + union Id { + int vendorExtensionTag; + BassBoost.Tag commonTag; + } + + /** + * Vendor BassBoost implementation definition for additional parameters. + */ + VendorExtension vendor; + + /** + * Capability supported by BassBoost implementation. + */ + @VintfStability + parcelable Capability { + /** + * BassBoost capability extension, vendor can use this extension in case existing capability + * definition not enough. + */ + ParcelableHolder extension; + /** + * Indicates whether setting strength is supported. False value indicates only one strength + * is supported and setParameter() method will return EX_ILLEGAL_ARGUMENT. + */ + boolean strengthSupported; + } + + /** + * The per mille strength of the bass boost effect. + * + * If the implementation does not support per mille accuracy for setting the strength, it is + * allowed to round the given strength to the nearest supported value. In this case {@link + * #IEffect.getParameter()} method should return the rounded value that was actually set. + * + * The valid range for strength is [0, 1000]. + */ + int strengthPm; +} diff --git a/audio/aidl/android/hardware/audio/effect/Capability.aidl b/audio/aidl/android/hardware/audio/effect/Capability.aidl index e792f8652e..f741f338bf 100644 --- a/audio/aidl/android/hardware/audio/effect/Capability.aidl +++ b/audio/aidl/android/hardware/audio/effect/Capability.aidl @@ -16,7 +16,17 @@ package android.hardware.audio.effect; +import android.hardware.audio.effect.BassBoost; +import android.hardware.audio.effect.Downmix; +import android.hardware.audio.effect.DynamicsProcessing; import android.hardware.audio.effect.Equalizer; +import android.hardware.audio.effect.HapticGenerator; +import android.hardware.audio.effect.LoudnessEnhancer; +import android.hardware.audio.effect.Reverb; +import android.hardware.audio.effect.VendorExtension; +import android.hardware.audio.effect.Virtualizer; +import android.hardware.audio.effect.Visualizer; +import android.hardware.audio.effect.Volume; /** * Effect capability definitions. @@ -33,14 +43,19 @@ union Capability { * the ParcelableHolder in each effect capability definition. For example: * Equalizer.Capability.extension. */ - @VintfStability - parcelable VendorEffectCapability { - ParcelableHolder extension; - } - VendorEffectCapability vendor; + VendorExtension vendorExtension; /** - * Equalizer capability definition. + * Effect capabilities. */ + BassBoost.Capability bassBoost; + Downmix.Capability downmix; + DynamicsProcessing.Capability dynamicsProcessing; Equalizer.Capability equalizer; + HapticGenerator.Capability hapticGenerator; + LoudnessEnhancer.Capability loudnessEnhancer; + Reverb.Capability reverb; + Virtualizer.Capability virtualizer; + Visualizer.Capability visualizer; + Volume.Capability volume; } diff --git a/audio/aidl/android/hardware/audio/effect/Descriptor.aidl b/audio/aidl/android/hardware/audio/effect/Descriptor.aidl index 562c2499cb..47c88dc8d3 100644 --- a/audio/aidl/android/hardware/audio/effect/Descriptor.aidl +++ b/audio/aidl/android/hardware/audio/effect/Descriptor.aidl @@ -107,10 +107,6 @@ parcelable Descriptor { * implementation is part of a proxy effect. */ @nullable AudioUuid proxy; - /** - * Capability flags defined for the effect implementation. - */ - Flags flags; } /** @@ -122,6 +118,10 @@ parcelable Descriptor { * Identity of effect implementation. */ Identity id; + /** + * Capability flags defined for the effect implementation. + */ + Flags flags; /** * CPU load indication expressed in 0.1 MIPS units as estimated on an ARM9E core (ARMv5TE) * with 0 WS. diff --git a/audio/aidl/android/hardware/audio/effect/Downmix.aidl b/audio/aidl/android/hardware/audio/effect/Downmix.aidl new file mode 100644 index 0000000000..ee57baf440 --- /dev/null +++ b/audio/aidl/android/hardware/audio/effect/Downmix.aidl @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package android.hardware.audio.effect; + +import android.hardware.audio.effect.VendorExtension; + +/** + * Downmix specific definitions. + * + * All parameters defined in union Downmix must be gettable and settable. The capabilities defined + * in Downmix.Capability can only acquired with IEffect.getDescriptor() and not settable. + */ +@VintfStability +union Downmix { + /** + * Effect parameter tag to identify the parameters for getParameter(). + */ + @VintfStability + union Id { + int vendorExtensionTag; + Downmix.Tag commonTag; + } + + /** + * Vendor Downmix implementation definition for additional parameters. + */ + VendorExtension vendor; + + /** + * Capability supported by Downmix implementation. + */ + @VintfStability + parcelable Capability { + /** + * Downmix capability extension, vendor can use this extension in case existing capability + * definition not enough. + */ + ParcelableHolder extension; + } + + @VintfStability + enum Type { + /** + * Throw away the extra channels. + */ + STRIP, + /** + * Mix the extra channels with FL/FR. + */ + FOLD, + } + + /** + * Type of downmix. + */ + Type type; +} diff --git a/audio/aidl/android/hardware/audio/effect/DynamicsProcessing.aidl b/audio/aidl/android/hardware/audio/effect/DynamicsProcessing.aidl new file mode 100644 index 0000000000..ee5dcad9e0 --- /dev/null +++ b/audio/aidl/android/hardware/audio/effect/DynamicsProcessing.aidl @@ -0,0 +1,301 @@ +/* + * 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. + */ + +package android.hardware.audio.effect; + +import android.hardware.audio.effect.VendorExtension; + +/** + * DynamicsProcessing specific definitions. + * + * All parameters defined in union DynamicsProcessing must be gettable and settable. The + * capabilities defined in DynamicsProcessing.Capability can only acquired with + * IEffect.getDescriptor() and not settable. + */ +@VintfStability +union DynamicsProcessing { + /** + * Effect parameter tag to identify the parameters for getParameter(). + */ + @VintfStability + union Id { + int vendorExtensionTag; + DynamicsProcessing.Tag commonTag; + } + + /** + * Vendor DynamicsProcessing implementation definition for additional parameters. + */ + VendorExtension vendorExtension; + + /** + * Capability supported by DynamicsProcessing implementation. + */ + @VintfStability + parcelable Capability { + /** + * DynamicsProcessing capability extension, vendor can use this extension in case existing + * capability definition not enough. + */ + ParcelableHolder extension; + } + + /** + * Resolution preference definition. + */ + enum ResolutionPreference { + /** + * Favors frequency domain based implementation. + */ + FAVOR_FREQUENCY_RESOLUTION, + /** + * Favors tme domain based implementation. + */ + FAVOR_TIME_RESOLUTION, + } + + /** + * Band enablement configuration. + */ + @VintfStability + parcelable BandEnablement { + /** + * True if multi-band stage is in use. + */ + boolean inUse; + /** + * Number of bands configured for this stage. + */ + int bandCount; + } + + /** + * Effect engine configuration. Set the enablement of all stages. + */ + @VintfStability + parcelable EngineArchitecture { + /** + * Resolution preference. + */ + ResolutionPreference resolutionPreference = ResolutionPreference.FAVOR_FREQUENCY_RESOLUTION; + /** + * Preferred frame duration in milliseconds (ms). + */ + float preferredFrameDurationMs; + /** + * PreEq stage (Multi-band Equalizer) configuration. + */ + BandEnablement preEqBand; + /** + * PostEq stage (Multi-band Equalizer) configuration. + */ + BandEnablement postEqBand; + /** + * MBC stage (Multi-band Compressor) configuration. + */ + BandEnablement mbcBand; + /** + * True if Limiter stage is in use. + */ + boolean limiterInUse; + } + + /** + * Band enablement configuration for a specific channel. + */ + @VintfStability + parcelable BandChannelConfig { + /** + * Channel index. + */ + int channel; + /** + * Channel index. + */ + BandEnablement enablement; + } + + /** + * Equalizer band configuration for a specific channel and band. + */ + @VintfStability + parcelable EqBandConfig { + /** + * Channel index. + */ + int channel; + /** + * Band index, must in the range of [0, bandCount-1]. + */ + int band; + /** + * True if EQ stage is enabled. + */ + boolean enable; + /** + * Topmost frequency number (in Hz) this band will process. + */ + float cutoffFrequency; + /** + * Gain factor in decibels (dB). + */ + float gain; + } + + /** + * MBC configuration for a specific channel and band. + */ + @VintfStability + parcelable MbcBandConfig { + /** + * Channel index. + */ + int channel; + /** + * Band index, must in the range of [0, bandCount-1]. + */ + int band; + /** + * True if MBC stage is enabled. + */ + boolean enable; + /** + * Topmost frequency number (in Hz) this band will process. + */ + float cutoffFrequencyHz; + /** + * Gain factor in decibels (dB). + */ + float gainDb; + /** + * Attack Time for compressor in milliseconds (ms). + */ + float attackTimeMs; + /** + * Release Time for compressor in milliseconds (ms). + */ + float releaseTimeMs; + /** + * Compressor ratio (N:1) (input:output). + */ + float ratio; + /** + * Compressor threshold measured in decibels (dB) from 0 dB Full Scale (dBFS). + */ + float thresholdDb; + /** + * Width in decibels (dB) around compressor threshold point. + */ + float kneeWidthDb; + /** + * Noise gate threshold in decibels (dB) from 0 dB Full Scale (dBFS). + */ + float noiseGateThresholdDb; + /** + * Expander ratio (1:N) (input:output) for signals below the Noise Gate Threshold. + */ + float expanderRatio; + /** + * Gain applied to the signal BEFORE the compression in dB. + */ + float preGainDb; + /** + * Gain applied to the signal AFTER compression in dB. + */ + float postGainDb; + } + + /** + * Limiter configuration for a specific channel. + */ + @VintfStability + parcelable LimiterConfig { + /** + * Channel index. + */ + int channel; + /** + * True if Limiter stage is enabled. + */ + boolean enable; + /** + * True if Limiter stage is in use. + */ + boolean inUse; + /** + * Index of group assigned to this Limiter. Only limiters that share the same linkGroup + * index will react together. + */ + int linkGroup; + /** + * Attack Time for compressor in milliseconds (ms). + */ + float attackTimeMs; + /** + * Release Time for compressor in milliseconds (ms). + */ + float releaseTimeMs; + /** + * Compressor ratio (N:1) (input:output). + */ + float ratio; + /** + * Compressor threshold measured in decibels (dB) from 0 dB Full Scale (dBFS). + */ + float thresholdDb; + /** + * Gain applied to the signal AFTER compression in dB. + */ + float postGainDb; + } + + /** + * Effect engine architecture. + */ + EngineArchitecture engineArchitecture; + /** + * PreEq stage per channel configuration. + */ + BandChannelConfig preEq; + /** + * PostEq stage per channel configuration. + */ + BandChannelConfig postEq; + /** + * PreEq stage per band configuration. + */ + EqBandConfig preEqBand; + /** + * PostEq stage per band configuration. + */ + EqBandConfig postEqBand; + /** + * MBC stage per channel configuration. + */ + BandChannelConfig mbc; + /** + * PostEq stage per band configuration. + */ + MbcBandConfig mbcBand; + /** + * Limiter stage configuration. + */ + LimiterConfig limiter; + /** + * Input gain factor in decibels (dB). 0 dB means no change in level. + */ + float inputGainDb; +} diff --git a/audio/aidl/android/hardware/audio/effect/Equalizer.aidl b/audio/aidl/android/hardware/audio/effect/Equalizer.aidl index 7fe9bb2b67..79a1c4f561 100644 --- a/audio/aidl/android/hardware/audio/effect/Equalizer.aidl +++ b/audio/aidl/android/hardware/audio/effect/Equalizer.aidl @@ -16,7 +16,7 @@ package android.hardware.audio.effect; -import android.media.audio.common.AudioProfile; +import android.hardware.audio.effect.VendorExtension; /** * Equalizer specific definitions. @@ -27,13 +27,18 @@ import android.media.audio.common.AudioProfile; @VintfStability union Equalizer { /** - * Vendor Equalizer implementation definition for additional parameters. + * Effect parameter tag to identify the parameters for getParameter(). */ @VintfStability - parcelable VendorExtension { - ParcelableHolder extension; + union Id { + int vendorExtensionTag; + Equalizer.Tag commonTag; } - VendorExtension vendor; + + /** + * Vendor Equalizer implementation definition for additional parameters. + */ + VendorExtension vendorExtension; /** * Capability MUST be supported by Equalizer implementation. @@ -58,22 +63,22 @@ union Equalizer { } /** - * Level setting for each band. + * Level setting for each band in millibels. */ @VintfStability parcelable BandLevel { int index; - int level; + int levelMb; } /** - * Supported minimal and maximal frequency for each band. + * Supported minimal and maximal frequency for each band in millihertz. */ @VintfStability parcelable BandFrequency { int index; - int min; - int max; + int minMh; + int maxMh; } /** diff --git a/audio/aidl/android/hardware/audio/effect/HapticGenerator.aidl b/audio/aidl/android/hardware/audio/effect/HapticGenerator.aidl new file mode 100644 index 0000000000..944155fbcc --- /dev/null +++ b/audio/aidl/android/hardware/audio/effect/HapticGenerator.aidl @@ -0,0 +1,95 @@ +/* + * 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. + */ + +package android.hardware.audio.effect; + +import android.hardware.audio.effect.VendorExtension; + +/** + * HapticGenerator specific definitions. HapticGenerator effect provide HapticGenerator control and + * mute/unmute functionality. + * + * All parameters defined in union HapticGenerator must be gettable and settable. The capabilities + * defined in HapticGenerator.Capability can only acquired with IEffect.getDescriptor() and not + * settable. + */ +@VintfStability +union HapticGenerator { + /** + * Effect parameter tag to identify the parameters for getParameter(). + */ + @VintfStability + union Id { + int vendorExtensionTag; + HapticGenerator.Tag commonTag; + } + + /** + * Vendor HapticGenerator implementation definition for additional parameters. + */ + VendorExtension vendorExtension; + + /** + * Capability supported by HapticGenerator implementation. + */ + @VintfStability + parcelable Capability { + /** + * HapticGenerator capability extension, vendor can use this extension in case existing + * capability definition not enough. + */ + VendorExtension extension; + } + + @VintfStability + @Backing(type="int") + enum VibratorScale { + MUTE = -100, + VERY_LOW = -2, + LOW = -1, + NONE = 0, + HIGH = 1, + VERY_HIGH = 2, + } + + @VintfStability + parcelable HapticScale { + /** + * Audio track ID. + */ + int id; + /** + * Haptic intensity. + */ + VibratorScale scale = VibratorScale.MUTE; + } + + /** + * Vibrator information including resonant frequency, Q factor. + */ + @VintfStability + parcelable VibratorInformation { + /** + * Resonant frequency in Hz. + */ + float resonantFrequencyHz; + float qFactor; + float maxAmplitude; + } + + HapticScale hapticScale; + VibratorInformation vibratorInfo; +} diff --git a/audio/aidl/android/hardware/audio/effect/IEffect.aidl b/audio/aidl/android/hardware/audio/effect/IEffect.aidl index 5dd390f544..3b957d702d 100644 --- a/audio/aidl/android/hardware/audio/effect/IEffect.aidl +++ b/audio/aidl/android/hardware/audio/effect/IEffect.aidl @@ -44,13 +44,15 @@ interface IEffect { */ int status; /** - * The amount of bytes consumed by the effect instance. + * The amount of audio data samples in the floating point format consumed by the effect + * instance. */ - int fmqByteConsumed; + int fmqConsumed; /** - * The amount of bytes produced by the effect instance. + * The amount of audio data samples in the floating point format produced by the effect + * instance. */ - int fmqByteProduced; + int fmqProduced; } /** @@ -65,11 +67,11 @@ interface IEffect { /** * Message queue for input data buffer. */ - MQDescriptor inputDataMQ; + MQDescriptor inputDataMQ; /** * Message queue for output data buffer. */ - MQDescriptor outputDataMQ; + MQDescriptor outputDataMQ; } /** @@ -79,13 +81,15 @@ interface IEffect { * the effect instance must be able to handle all IEffect interface calls. * * @param common Parameters which MUST pass from client at open time. + * @param specific Effect specific parameters which can optional pass from client at open time. * * @throws EX_ILLEGAL_ARGUMENT if the effect instance receive unsupported command. * @throws a EX_UNSUPPORTED_OPERATION if device capability/resource is not enough or system * failure happens. * @note Open an already-opened effect instance should do nothing and should not throw an error. */ - OpenEffectReturn open(in Parameter.Common common, in Parameter.Specific specific); + OpenEffectReturn open( + in Parameter.Common common, in @nullable Parameter.Specific specific); /** * Called by the client to close the effect instance, processing thread should be destroyed and diff --git a/audio/aidl/android/hardware/audio/effect/IFactory.aidl b/audio/aidl/android/hardware/audio/effect/IFactory.aidl index e56c24f5e5..59433599be 100644 --- a/audio/aidl/android/hardware/audio/effect/IFactory.aidl +++ b/audio/aidl/android/hardware/audio/effect/IFactory.aidl @@ -39,11 +39,14 @@ interface IFactory { * null, used as a filter for effect type UUIDs. * @param implementation Indicates the particular implementation of the effect in that type. * This is an optional parameter, pass in null if this parameter is not necessary; if - * non null, used as a filter for effect type UUIDs. + * non null, used as a filter for effect implementation UUIDs. + * @param proxy Indicates the proxy UUID filter to query. + * This is an optional parameter, pass in null if this parameter is not necessary; if + * non null, used as a filter for effect proxy UUIDs. * @return List of effect identities supported and filtered by type/implementation UUID. */ - Descriptor.Identity[] queryEffects( - in @nullable AudioUuid type, in @nullable AudioUuid implementation); + Descriptor.Identity[] queryEffects(in @nullable AudioUuid type, + in @nullable AudioUuid implementation, in @nullable AudioUuid proxy); /** * Return a list of defined processings, with the optional filter by Processing type. diff --git a/audio/aidl/android/hardware/audio/effect/LoudnessEnhancer.aidl b/audio/aidl/android/hardware/audio/effect/LoudnessEnhancer.aidl new file mode 100644 index 0000000000..0441f10f17 --- /dev/null +++ b/audio/aidl/android/hardware/audio/effect/LoudnessEnhancer.aidl @@ -0,0 +1,61 @@ +/* + * 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. + */ + +package android.hardware.audio.effect; + +import android.hardware.audio.effect.VendorExtension; + +/** + * LoudnessEnhancer specific definitions. + * + * All parameters defined in union LoudnessEnhancer must be gettable and settable. The capabilities + * defined in LoudnessEnhancer.Capability can only acquired with IEffect.getDescriptor() and not + * settable. + */ +@VintfStability +union LoudnessEnhancer { + /** + * Effect parameter tag to identify the parameters for getParameter(). + */ + @VintfStability + union Id { + int vendorExtensionTag; + LoudnessEnhancer.Tag commonTag; + } + + /** + * Vendor LoudnessEnhancer implementation definition for additional parameters. + */ + VendorExtension vendor; + + /** + * Capability supported by LoudnessEnhancer implementation. + */ + @VintfStability + parcelable Capability { + /** + * LoudnessEnhancer capability extension, vendor can use this extension in case existing + * capability definition not enough. + */ + VendorExtension extension; + } + + /** + * The maximum gain in millibels (mB) applied to the signal to process, default value is 0 which + * corresponds to no amplification. + */ + int gainMb; +} diff --git a/audio/aidl/android/hardware/audio/effect/Parameter.aidl b/audio/aidl/android/hardware/audio/effect/Parameter.aidl index 739c9ff4c2..e7d3d5efd5 100644 --- a/audio/aidl/android/hardware/audio/effect/Parameter.aidl +++ b/audio/aidl/android/hardware/audio/effect/Parameter.aidl @@ -16,9 +16,19 @@ package android.hardware.audio.effect; +import android.hardware.audio.effect.BassBoost; +import android.hardware.audio.effect.Downmix; +import android.hardware.audio.effect.DynamicsProcessing; import android.hardware.audio.effect.Equalizer; +import android.hardware.audio.effect.HapticGenerator; +import android.hardware.audio.effect.LoudnessEnhancer; +import android.hardware.audio.effect.Reverb; +import android.hardware.audio.effect.VendorExtension; +import android.hardware.audio.effect.Virtualizer; +import android.hardware.audio.effect.Visualizer; +import android.hardware.audio.effect.Volume; import android.media.audio.common.AudioConfig; -import android.media.audio.common.AudioDeviceType; +import android.media.audio.common.AudioDeviceDescription; import android.media.audio.common.AudioMode; import android.media.audio.common.AudioSource; @@ -28,9 +38,8 @@ import android.media.audio.common.AudioSource; * There are three groups of parameters: * 1. Common parameters are essential parameters, MUST pass to effects at open() interface. * 2. Parameters defined for a specific effect type. - * 3. Extension parameters for vendor. + * 3. Extension parameters ParcelableHolder can be used for vendor effect definition. * - * For all supported parameter, implementation MUST support both set and get. */ @VintfStability union Parameter { @@ -44,17 +53,38 @@ union Parameter { @VintfStability union Id { /** - * Common parameter tag. + * Parameter tag defined for vendor effects. Use int here so there is flexibility for vendor + * to define different tag. */ - int commonTag; + int vendorEffectTag; /** - * Vendor defined parameter tag. + * Parameter tag defined for nested parameters. Can be used to get any parameter defined in + * nested Union structure. + * + * Example: + * To get BassBoost strength in param from effectInstance: + * IEffect effectInstance; + * Parameter param; + * BassBoost::Id bassId = BassBoost::Id::make(BassBoost::strengthPm); + * Parameter::Id id = Parameter::Id::make(bassId); + * effectInstance.getParameter(id, ¶m); + * */ - int vendorTag; + BassBoost.Id bassBoostTag; + Downmix.Id downmixTag; + DynamicsProcessing.Id dynamicsProcessingTag; + Equalizer.Id equalizerTag; + HapticGenerator.Id hapticGeneratorTag; + LoudnessEnhancer.Id loudnessEnhancerTag; + Reverb.Id reverbTag; + Virtualizer.Id virtualizerTag; + Visualizer.Id visualizerTag; + Volume.Id volumeTag; /** - * Specific effect parameter tag. + * Non-nested parameter tag. Can be used to get any parameter defined in Union Parameter + * directly. */ - Specific.Id specificId; + Parameter.Tag commonTag; } /** @@ -85,7 +115,7 @@ union Parameter { * Used by audio framework to set the device type to effect engine. * Effect must implement setParameter(device) if Flags.deviceIndication set to true. */ - AudioDeviceType device; + AudioDeviceDescription deviceDescription; /** * Used by audio framework to set the audio mode to effect engine. * Effect must implement setParameter(mode) if Flags.audioModeIndication set to true. @@ -101,7 +131,7 @@ union Parameter { * The volume gain for left and right channel, left and right equals to same value if it's mono. */ @VintfStability - parcelable Volume { + parcelable VolumeStereo { float left; float right; } @@ -109,38 +139,24 @@ union Parameter { * Used by audio framework to delegate volume control to effect engine. * Effect must implement setParameter(volume) if Flags.volume set to Volume.IND. */ - Volume volume; - - /** - * Used by audio framework to delegate offload information to effect engine. - * Effect must implement setParameter(offload) if Flags.offloadSupported set to true. - */ - boolean offload; - - /** - * Parameters for vendor extension effect implementation usage. - */ - @VintfStability - parcelable VendorEffectParameter { - ParcelableHolder extension; - } - VendorEffectParameter vendorEffect; + VolumeStereo volumeStereo; /** * Parameters MUST be supported by a Specific type of effect. */ @VintfStability union Specific { - @VintfStability - union Id { - /** - * Equalizer.Tag to identify the parameters in Equalizer. - */ - Equalizer.Tag equalizerTag = Equalizer.Tag.vendor; - } - Id id; - + VendorExtension vendorEffect; + BassBoost bassBoost; + Downmix downmix; + DynamicsProcessing dynamicsProcessing; Equalizer equalizer; + LoudnessEnhancer loudnessEnhancer; + HapticGenerator hapticGenerator; + Reverb reverb; + Virtualizer virtualizer; + Visualizer visualizer; + Volume volume; } Specific specific; } diff --git a/audio/aidl/android/hardware/audio/effect/Reverb.aidl b/audio/aidl/android/hardware/audio/effect/Reverb.aidl new file mode 100644 index 0000000000..f60c2ea56c --- /dev/null +++ b/audio/aidl/android/hardware/audio/effect/Reverb.aidl @@ -0,0 +1,92 @@ +/* + * 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. + */ + +package android.hardware.audio.effect; + +import android.hardware.audio.effect.VendorExtension; + +/** + * Reverb specific definitions. + * + * All parameters defined in union Reverb must be gettable and settable. The capabilities defined in + * Reverb.Capability can only acquired with IEffect.getDescriptor() and not settable. + */ +@VintfStability +union Reverb { + /** + * Effect parameter tag to identify the parameters for getParameter(). + */ + @VintfStability + union Id { + int vendorExtensionTag; + Reverb.Tag commonTag; + } + + /** + * Vendor Reverb implementation definition for additional parameters. + */ + VendorExtension vendor; + + /** + * Capability supported by effect implementation. + */ + @VintfStability + parcelable Capability { + VendorExtension extension; + + /** + * Max decay time supported in millisecond. + */ + int maxDecayTimeMs; + } + + /** + * Room level apply to the reverb effect in millibels. + */ + int roomLevelMb; + /** + * Room HF level apply to the reverb effect in millibels. + */ + int roomHfLevelMb; + /** + * Delay time apply to the reverb effect in milliseconds. + */ + int decayTimeMs; + /** + * HF decay ratio in permilles. + */ + int decayHfRatioPm; + /** + * Reverb level in millibels. + */ + int levelMb; + /** + * Reverb delay in milliseconds. + */ + int delayMs; + /** + * Diffusion in permilles. + */ + int diffusionPm; + /** + * Density in permilles. + */ + int densityPm; + /** + * Bypass reverb and copy input to output if set to true. + */ + boolean bypass; +} diff --git a/audio/aidl/android/hardware/audio/effect/VendorExtension.aidl b/audio/aidl/android/hardware/audio/effect/VendorExtension.aidl new file mode 100644 index 0000000000..c60f01a5f1 --- /dev/null +++ b/audio/aidl/android/hardware/audio/effect/VendorExtension.aidl @@ -0,0 +1,25 @@ +/* + * 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. + */ + +package android.hardware.audio.effect; + +/** + * Vendor exntension implementation definition, can be used for additional parameters. + */ +@VintfStability +parcelable VendorExtension { + ParcelableHolder extension; +} diff --git a/audio/aidl/android/hardware/audio/effect/Virtualizer.aidl b/audio/aidl/android/hardware/audio/effect/Virtualizer.aidl new file mode 100644 index 0000000000..9d039bc58f --- /dev/null +++ b/audio/aidl/android/hardware/audio/effect/Virtualizer.aidl @@ -0,0 +1,72 @@ +/* + * 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. + */ + +package android.hardware.audio.effect; + +import android.hardware.audio.effect.VendorExtension; + +/** + * Virtualizer specific definitions. An audio virtualizer is a general name for an effect to + * spatialize audio channels. + * + * All parameters defined in union Virtualizer must be gettable and settable. The capabilities + * defined in Virtualizer.Capability can only acquired with IEffect.getDescriptor() and not + * settable. + */ +@VintfStability +union Virtualizer { + /** + * Effect parameter tag to identify the parameters for getParameter(). + */ + @VintfStability + union Id { + int vendorExtensionTag; + Virtualizer.Tag commonTag; + } + + /** + * Vendor Virtualizer implementation definition for additional parameters. + */ + VendorExtension vendor; + + /** + * Capability supported by Virtualizer implementation. + */ + @VintfStability + parcelable Capability { + /** + * Virtualizer capability extension, vendor can use this extension in case existing + * capability definition not enough. + */ + VendorExtension extension; + /** + * Indicates whether setting strength is supported. False value indicates only one strength + * is supported and setParameter() method will always return EX_ILLEGAL_ARGUMENT. + */ + boolean strengthSupported; + } + + /** + * The per mille strength of the virtualizer effect. + * + * If the implementation does not support per mille accuracy for setting the strength, it is + * allowed to round the given strength to the nearest supported value. In this case {@link + * #IEffect.getParameter()} method should return the rounded value that was actually set. + * + * The valid range for strength is [0, 1000]. + */ + int strengthPm; +} diff --git a/audio/aidl/android/hardware/audio/effect/Visualizer.aidl b/audio/aidl/android/hardware/audio/effect/Visualizer.aidl new file mode 100644 index 0000000000..4c1b71aa1e --- /dev/null +++ b/audio/aidl/android/hardware/audio/effect/Visualizer.aidl @@ -0,0 +1,167 @@ +/* + * 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. + */ + +package android.hardware.audio.effect; + +import android.hardware.audio.effect.VendorExtension; + +/** + * Visualizer specific definitions. Visualizer enables application to retrieve part of the currently + * playing audio for visualization purpose + * + * All parameters defined in union Visualizer other than these in GetOnlyParameters and + * SetOnlyParameters must be gettable and settable. The capabilities defined in + * Visualizer.Capability can only acquired with IEffect.getDescriptor() and not settable. + * + */ +@VintfStability +union Visualizer { + /** + * Effect parameter tag to identify the parameters for getParameter(). + */ + @VintfStability + union Id { + int vendorExtensionTag; + GetOnlyParameters.Tag getOnlyParamTag; + SetOnlyParameters.Tag setOnlyParamTag; + Visualizer.Tag commonTag; + } + Id id; + + /** + * Vendor Visualizer implementation definition for additional parameters. + */ + VendorExtension vendor; + + /** + * Capability supported by Visualizer implementation. + */ + @VintfStability + parcelable Capability { + /** + * Visualizer capability extension, vendor can use this extension in case existing + * capability definition not enough. + */ + VendorExtension extension; + /** + * Max latency supported in millseconds. + */ + int maxLatencyMs; + /** + * Capture size range. + */ + CaptureSizeRange captureSizeRange; + } + + /** + * Supported capture size range in bytes. + */ + @VintfStability + parcelable CaptureSizeRange { + int minBytes; + int maxBytes; + } + + /** + * Type of scaling applied on the captured visualization data. + */ + @VintfStability + enum ScalingMode { + /** + * Defines a capture mode where amplification is applied based on the content of the + * captured data. This is the default Visualizer mode, and is suitable for music + * visualization. + */ + NORMALIZED = 0, + /** + * Defines a capture mode where the playback volume will affect (scale) the range of the + * captured data. A low playback volume will lead to low sample and fft values, and + * vice-versa. + */ + AS_PLAYED, + } + + /** + * Measurement modes to be performed. + */ + @VintfStability + enum MeasurementMode { + /** + * No measurements are performed. + */ + NONE = 0, + /** + * Defines a measurement mode which computes the peak and RMS value in mB below the "full + * scale", where 0mB is normally the maximum sample value (but see the note below). Minimum + * value depends on the resolution of audio samples used by the audio framework. The value + * of -9600mB is the minimum value for 16-bit audio systems and -14400mB or below for "high + * resolution" systems. Values for peak and RMS can be retrieved with {@link + * #getMeasurementPeakRms(MeasurementPeakRms)}. + */ + PEAK_RMS, + } + + /** + * Any parameter defined in this union must be gettable via getParameter(), but must not + * settable. + */ + @VintfStability + union GetOnlyParameters { + /** + * Get the current measurements. + */ + @VintfStability + parcelable Measurement { + int rms; + int peak; + } + Measurement measurement; + + /** + * Gets the latest PCM capture, size of returned vector equals to @c captureSize. + */ + byte[] captureBytes; + } + GetOnlyParameters getOnlyParameters; + + /** + * Any parameter defined in this union must be settable via setParameter(), but must not + * gettable. + */ + @VintfStability + union SetOnlyParameters { + /** + * Used by framework to inform the visualizer about the downstream latency (audio hardware + * driver estimated latency in milliseconds). + */ + int latencyMs; + } + SetOnlyParameters setOnlyParameters; + + /** + * Current capture size in bytes. The capture size must be a power of 2 in the range + * Capability.captureSizeRange. + */ + int captureSizeBytes; + /** + * Visualizer capture mode + */ + ScalingMode scalingMode; + /** + * Visualizer measurement mode. + */ + MeasurementMode measurementMode; +} diff --git a/audio/aidl/android/hardware/audio/effect/Volume.aidl b/audio/aidl/android/hardware/audio/effect/Volume.aidl new file mode 100644 index 0000000000..a3ce2f6821 --- /dev/null +++ b/audio/aidl/android/hardware/audio/effect/Volume.aidl @@ -0,0 +1,69 @@ +/* + * 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. + */ + +package android.hardware.audio.effect; + +import android.hardware.audio.effect.VendorExtension; + +/** + * Volume specific definitions. Volume effect provide volume control and mute/unmute functionality. + * + * All parameters defined in union Volume must be gettable and settable. The capabilities defined in + * Volume.Capability can only acquired with IEffect.getDescriptor() and not settable. + */ +@VintfStability +union Volume { + /** + * Effect parameter tag to identify the parameters for getParameter(). + */ + @VintfStability + union Id { + int vendorExtensionTag; + Volume.Tag commonTag; + } + + /** + * Vendor Volume implementation definition for additional parameters. + */ + VendorExtension vendor; + + /** + * Capability supported by Volume implementation. + */ + @VintfStability + parcelable Capability { + /** + * Volume capability extension, vendor can use this extension in case existing capability + * definition not enough. + */ + VendorExtension extension; + + /** + * Volume strength supported in dB. + */ + int maxLevel; + } + + /** + * Current level in dB. + */ + int levelDb; + /** + * Mute volume if true, when volume set to mute, the current level still saved and take effect + * when unmute. + */ + boolean mute; +} From 6afc855087fe87956eb5a7db2202d53495a2f4bc Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Wed, 26 Oct 2022 22:47:20 +0000 Subject: [PATCH 2/2] AIDL effect: Add all aosp effects default implementation Bug: 238913361 Test: atest VtsHalAudioEffectTargetTest atest VtsHalAudioEffectFactoryTargetTest atest VtsHalEqualizerTargetTest Change-Id: I6825ba77ae0707f97e852f0faa52ce3486ba2af5 --- audio/aidl/default/Android.bp | 49 +-- audio/aidl/default/EffectFactory.cpp | 141 ++++---- audio/aidl/default/EffectImpl.cpp | 256 +++++++++++++++ audio/aidl/default/bassboost/Android.bp | 40 +++ audio/aidl/default/bassboost/BassBoostSw.cpp | 118 +++++++ audio/aidl/default/bassboost/BassBoostSw.h | 72 ++++ .../aidl/default/dynamicProcessing/Android.bp | 40 +++ .../DynamicsProcessingSw.cpp | 119 +++++++ .../dynamicProcessing/DynamicsProcessingSw.h | 72 ++++ audio/aidl/default/equalizer/Android.bp | 16 +- audio/aidl/default/equalizer/Equalizer.cpp | 310 +++++------------- audio/aidl/default/hapticGenerator/Android.bp | 40 +++ .../hapticGenerator/HapticGeneratorSw.cpp | 118 +++++++ .../hapticGenerator/HapticGeneratorSw.h | 72 ++++ .../include/effect-impl/EffectContext.h | 118 ++++++- .../default/include/effect-impl/EffectImpl.h | 86 +++++ .../default/include/effect-impl/EffectTypes.h | 55 +++- .../default/include/effect-impl/EffectUUID.h | 125 ++++++- .../include/effect-impl/EffectWorker.h | 29 +- .../effectFactory-impl/EffectFactory.h | 16 +- .../include/equalizer-impl/EqualizerSw.h | 119 ++++--- .../aidl/default/loudnessEnhancer/Android.bp | 40 +++ .../loudnessEnhancer/LoudnessEnhancerSw.cpp | 118 +++++++ .../loudnessEnhancer/LoudnessEnhancerSw.h | 72 ++++ audio/aidl/default/reverb/Android.bp | 40 +++ audio/aidl/default/reverb/ReverbSw.cpp | 118 +++++++ audio/aidl/default/reverb/ReverbSw.h | 72 ++++ audio/aidl/default/virtualizer/Android.bp | 40 +++ .../default/virtualizer/VirtualizerSw.cpp | 118 +++++++ .../aidl/default/virtualizer/VirtualizerSw.h | 72 ++++ audio/aidl/default/visualizer/Android.bp | 40 +++ .../aidl/default/visualizer/VisualizerSw.cpp | 118 +++++++ audio/aidl/default/visualizer/VisualizerSw.h | 72 ++++ audio/aidl/default/volume/Android.bp | 40 +++ audio/aidl/default/volume/VolumeSw.cpp | 118 +++++++ audio/aidl/default/volume/VolumeSw.h | 72 ++++ audio/aidl/vts/EffectFactoryHelper.h | 11 +- audio/aidl/vts/EffectHelper.h | 53 +-- .../VtsHalAudioEffectFactoryTargetTest.cpp | 20 +- .../aidl/vts/VtsHalAudioEffectTargetTest.cpp | 24 +- audio/aidl/vts/VtsHalEqualizerTargetTest.cpp | 54 ++- 41 files changed, 2851 insertions(+), 472 deletions(-) create mode 100644 audio/aidl/default/EffectImpl.cpp create mode 100644 audio/aidl/default/bassboost/Android.bp create mode 100644 audio/aidl/default/bassboost/BassBoostSw.cpp create mode 100644 audio/aidl/default/bassboost/BassBoostSw.h create mode 100644 audio/aidl/default/dynamicProcessing/Android.bp create mode 100644 audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp create mode 100644 audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h create mode 100644 audio/aidl/default/hapticGenerator/Android.bp create mode 100644 audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp create mode 100644 audio/aidl/default/hapticGenerator/HapticGeneratorSw.h create mode 100644 audio/aidl/default/include/effect-impl/EffectImpl.h create mode 100644 audio/aidl/default/loudnessEnhancer/Android.bp create mode 100644 audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.cpp create mode 100644 audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.h create mode 100644 audio/aidl/default/reverb/Android.bp create mode 100644 audio/aidl/default/reverb/ReverbSw.cpp create mode 100644 audio/aidl/default/reverb/ReverbSw.h create mode 100644 audio/aidl/default/virtualizer/Android.bp create mode 100644 audio/aidl/default/virtualizer/VirtualizerSw.cpp create mode 100644 audio/aidl/default/virtualizer/VirtualizerSw.h create mode 100644 audio/aidl/default/visualizer/Android.bp create mode 100644 audio/aidl/default/visualizer/VisualizerSw.cpp create mode 100644 audio/aidl/default/visualizer/VisualizerSw.h create mode 100644 audio/aidl/default/volume/Android.bp create mode 100644 audio/aidl/default/volume/VolumeSw.cpp create mode 100644 audio/aidl/default/volume/VolumeSw.h diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp index e64b90cf1f..d34d68c88b 100644 --- a/audio/aidl/default/Android.bp +++ b/audio/aidl/default/Android.bp @@ -68,10 +68,20 @@ cc_defaults { ], vendor: true, shared_libs: [ + "libaudioaidlcommon", "libbase", "libbinder_ndk", + "libcutils", + "libfmq", + "liblog", + "libutils", + "android.hardware.common-V2-ndk", + "android.hardware.common.fmq-V1-ndk", "android.hardware.audio.effect-V1-ndk", - "libequalizer", + ], + header_libs: [ + "libaudioaidl_headers", + "libsystem_headers", ], cflags: [ "-Wall", @@ -81,24 +91,12 @@ cc_defaults { ], } -cc_library_static { - name: "libaudioeffectserviceexampleimpl", - defaults: ["aidlaudioeffectservice_defaults"], - export_include_dirs: ["include"], - srcs: [ - "EffectFactory.cpp", - ], - header_libs: [ - "libsystem_headers", - ], - visibility: [ - ":__subpackages__", - ], -} - filegroup { name: "effectCommonFile", - srcs: ["EffectThread.cpp"], + srcs: [ + "EffectThread.cpp", + "EffectImpl.cpp", + ], } cc_binary { @@ -107,10 +105,21 @@ cc_binary { init_rc: ["android.hardware.audio.effect.service-aidl.example.rc"], vintf_fragments: ["android.hardware.audio.effect.service-aidl.xml"], defaults: ["aidlaudioeffectservice_defaults"], - static_libs: [ - "libaudioeffectserviceexampleimpl", + shared_libs: [ + "libbassboostsw", + "libdynamicsprocessingsw", + "libequalizersw", + "libhapticgeneratorsw", + "libloudnessenhancersw", + "libreverbsw", + "libvirtualizersw", + "libvisualizersw", + "libvolumesw", + ], + srcs: [ + "EffectMain.cpp", + "EffectFactory.cpp", ], - srcs: ["EffectMain.cpp"], } cc_library_headers { diff --git a/audio/aidl/default/EffectFactory.cpp b/audio/aidl/default/EffectFactory.cpp index 8e107a2bca..e03dda378f 100644 --- a/audio/aidl/default/EffectFactory.cpp +++ b/audio/aidl/default/EffectFactory.cpp @@ -18,6 +18,7 @@ #include #include +#include "effect-impl/EffectTypes.h" #include "effect-impl/EffectUUID.h" #include "effectFactory-impl/EffectFactory.h" @@ -26,27 +27,21 @@ using aidl::android::media::audio::common::AudioUuid; namespace aidl::android::hardware::audio::effect { Factory::Factory() { - std::function dlClose = [](void* handle) -> void { - if (handle && dlclose(handle)) { - LOG(ERROR) << "dlclose failed " << dlerror(); - } - }; - // TODO: implement this with audio_effect.xml. - auto libHandle = - std::unique_ptr{dlopen("libequalizer.so", RTLD_LAZY), dlClose}; - if (!libHandle) { - LOG(ERROR) << __func__ << ": dlopen failed, err: " << dlerror(); - return; - } - - LOG(DEBUG) << __func__ << " dlopen uuid: " << EqualizerSwImplUUID.toString() << " handle " - << libHandle; - mEffectLibMap.insert({EqualizerSwImplUUID, std::make_pair(std::move(libHandle), nullptr)}); - - Descriptor::Identity id; - id.type = EqualizerTypeUUID; - id.uuid = EqualizerSwImplUUID; - mIdentityList.push_back(id); + // TODO: get list of library UUID and name from audio_effect.xml. + openEffectLibrary(EqualizerTypeUUID, EqualizerSwImplUUID, std::nullopt, "libequalizersw.so"); + openEffectLibrary(EqualizerTypeUUID, EqualizerBundleImplUUID, std::nullopt, "libbundleaidl.so"); + openEffectLibrary(BassBoostTypeUUID, BassBoostSwImplUUID, std::nullopt, "libbassboostsw.so"); + openEffectLibrary(DynamicsProcessingTypeUUID, DynamicsProcessingSwImplUUID, std::nullopt, + "libdynamicsprocessingsw.so"); + openEffectLibrary(HapticGeneratorTypeUUID, HapticGeneratorSwImplUUID, std::nullopt, + "libhapticgeneratorsw.so"); + openEffectLibrary(LoudnessEnhancerTypeUUID, LoudnessEnhancerSwImplUUID, std::nullopt, + "libloudnessenhancersw.so"); + openEffectLibrary(ReverbTypeUUID, ReverbSwImplUUID, std::nullopt, "libreverbsw.so"); + openEffectLibrary(VirtualizerTypeUUID, VirtualizerSwImplUUID, std::nullopt, + "libvirtualizersw.so"); + openEffectLibrary(VisualizerTypeUUID, VisualizerSwImplUUID, std::nullopt, "libvisualizersw.so"); + openEffectLibrary(VolumeTypeUUID, VolumeSwImplUUID, std::nullopt, "libvolumesw.so"); } Factory::~Factory() { @@ -64,12 +59,16 @@ Factory::~Factory() { ndk::ScopedAStatus Factory::queryEffects(const std::optional& in_type_uuid, const std::optional& in_impl_uuid, + const std::optional& in_proxy_uuid, std::vector* _aidl_return) { - std::copy_if(mIdentityList.begin(), mIdentityList.end(), std::back_inserter(*_aidl_return), - [&](auto& desc) { - return (!in_type_uuid.has_value() || in_type_uuid.value() == desc.type) && - (!in_impl_uuid.has_value() || in_impl_uuid.value() == desc.uuid); - }); + std::copy_if( + mIdentityList.begin(), mIdentityList.end(), std::back_inserter(*_aidl_return), + [&](auto& desc) { + return (!in_type_uuid.has_value() || in_type_uuid.value() == desc.type) && + (!in_impl_uuid.has_value() || in_impl_uuid.value() == desc.uuid) && + (!in_proxy_uuid.has_value() || + (desc.proxy.has_value() && in_proxy_uuid.value() == desc.proxy.value())); + }); return ndk::ScopedAStatus::ok(); } @@ -96,43 +95,37 @@ ndk::ScopedAStatus Factory::queryProcessing(const std::optional* _aidl_return) { LOG(DEBUG) << __func__ << ": UUID " << in_impl_uuid.toString(); - if (in_impl_uuid == EqualizerSwImplUUID) { - if (mEffectLibMap.count(in_impl_uuid)) { - auto& lib = mEffectLibMap[in_impl_uuid]; - // didn't do dlsym yet - if (nullptr == lib.second) { - void* libHandle = lib.first.get(); - struct effect_interface_s intf = { - .createEffectFunc = (EffectCreateFunctor)dlsym(libHandle, "createEffect"), - .destroyEffectFunc = - (EffectDestroyFunctor)dlsym(libHandle, "destroyEffect")}; - auto dlInterface = std::make_unique(intf); - if (!dlInterface->createEffectFunc || !dlInterface->destroyEffectFunc) { - LOG(ERROR) << __func__ - << ": create or destroy symbol not exist in library: " << libHandle - << "!"; - return ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED); - } - lib.second = std::move(dlInterface); - } - - auto& libInterface = lib.second; - std::shared_ptr effectSp; - RETURN_IF_BINDER_EXCEPTION(libInterface->createEffectFunc(&effectSp)); - if (!effectSp) { - LOG(ERROR) << __func__ << ": library created null instance without return error!"; + if (mEffectLibMap.count(in_impl_uuid)) { + auto& lib = mEffectLibMap[in_impl_uuid]; + // didn't do dlsym yet + if (nullptr == lib.second) { + void* libHandle = lib.first.get(); + auto dlInterface = std::make_unique(); + dlInterface->createEffectFunc = (EffectCreateFunctor)dlsym(libHandle, "createEffect"); + dlInterface->destroyEffectFunc = + (EffectDestroyFunctor)dlsym(libHandle, "destroyEffect"); + if (!dlInterface->createEffectFunc || !dlInterface->destroyEffectFunc) { + LOG(ERROR) << __func__ + << ": create or destroy symbol not exist in library: " << libHandle + << " with dlerror: " << dlerror(); return ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED); } - *_aidl_return = effectSp; - mEffectUuidMap[std::weak_ptr(effectSp)] = in_impl_uuid; - LOG(DEBUG) << __func__ << ": instance " << effectSp.get() << " created successfully"; - return ndk::ScopedAStatus::ok(); - } else { - LOG(ERROR) << __func__ << ": library doesn't exist"; - return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + lib.second = std::move(dlInterface); } + + auto& libInterface = lib.second; + std::shared_ptr effectSp; + RETURN_IF_BINDER_EXCEPTION(libInterface->createEffectFunc(&in_impl_uuid, &effectSp)); + if (!effectSp) { + LOG(ERROR) << __func__ << ": library created null instance without return error!"; + return ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED); + } + *_aidl_return = effectSp; + mEffectUuidMap[std::weak_ptr(effectSp)] = in_impl_uuid; + LOG(DEBUG) << __func__ << ": instance " << effectSp.get() << " created successfully"; + return ndk::ScopedAStatus::ok(); } else { - LOG(ERROR) << __func__ << ": UUID not supported"; + LOG(ERROR) << __func__ << ": library doesn't exist"; return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } return ndk::ScopedAStatus::ok(); @@ -179,4 +172,34 @@ ndk::ScopedAStatus Factory::destroyEffect(const std::shared_ptr& in_han return status; } +void Factory::openEffectLibrary(const AudioUuid& type, const AudioUuid& impl, + const std::optional& proxy, const std::string& libName) { + std::function dlClose = [](void* handle) -> void { + if (handle && dlclose(handle)) { + LOG(ERROR) << "dlclose failed " << dlerror(); + } + }; + + auto libHandle = + std::unique_ptr{dlopen(libName.c_str(), RTLD_LAZY), dlClose}; + if (!libHandle) { + LOG(ERROR) << __func__ << ": dlopen failed, err: " << dlerror(); + return; + } + + LOG(DEBUG) << __func__ << " dlopen lib:" << libName << " for uuid:\ntype:" << type.toString() + << "\nimpl:" << impl.toString() + << "\nproxy:" << (proxy.has_value() ? proxy.value().toString() : "null") + << "\nhandle:" << libHandle; + mEffectLibMap.insert({impl, std::make_pair(std::move(libHandle), nullptr)}); + + Descriptor::Identity id; + id.type = type; + id.uuid = impl; + if (proxy.has_value()) { + id.proxy = proxy.value(); + } + mIdentityList.push_back(id); +} + } // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/EffectImpl.cpp b/audio/aidl/default/EffectImpl.cpp new file mode 100644 index 0000000000..2754bb62e9 --- /dev/null +++ b/audio/aidl/default/EffectImpl.cpp @@ -0,0 +1,256 @@ +/* + * 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 "AHAL_EffectImpl" +#include "effect-impl/EffectImpl.h" +#include "effect-impl/EffectTypes.h" +#include "include/effect-impl/EffectTypes.h" + +namespace aidl::android::hardware::audio::effect { + +ndk::ScopedAStatus EffectImpl::open(const Parameter::Common& common, + const std::optional& specific, + OpenEffectReturn* ret) { + LOG(DEBUG) << __func__; + { + std::lock_guard lg(mMutex); + RETURN_OK_IF(mState != State::INIT); + mContext = createContext(common); + RETURN_IF(!mContext, EX_ILLEGAL_ARGUMENT, "createContextFailed"); + setContext(mContext); + } + + RETURN_IF_ASTATUS_NOT_OK(setParameterCommon(common), "setCommParamErr"); + if (specific.has_value()) { + RETURN_IF_ASTATUS_NOT_OK(setParameterSpecific(specific.value()), "setSpecParamErr"); + } + + RETURN_IF(createThread(LOG_TAG) != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION, + "FailedToCreateWorker"); + + { + std::lock_guard lg(mMutex); + mContext->dupeFmq(ret); + mState = State::IDLE; + } + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus EffectImpl::close() { + std::lock_guard lg(mMutex); + RETURN_OK_IF(mState == State::INIT); + RETURN_IF(mState == State::PROCESSING, EX_ILLEGAL_STATE, "closeAtProcessing"); + + // stop the worker thread, ignore the return code + RETURN_IF(destroyThread() != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION, + "FailedToDestroyWorker"); + RETURN_IF(releaseContext() != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION, + "FailedToCreateWorker"); + mState = State::INIT; + LOG(DEBUG) << __func__; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus EffectImpl::setParameter(const Parameter& param) { + LOG(DEBUG) << __func__ << " with: " << param.toString(); + + auto tag = param.getTag(); + switch (tag) { + case Parameter::common: + case Parameter::deviceDescription: + case Parameter::mode: + case Parameter::source: + FALLTHROUGH_INTENDED; + case Parameter::volumeStereo: + return setParameterCommon(param); + case Parameter::specific: { + return setParameterSpecific(param.get()); + } + default: { + LOG(ERROR) << __func__ << " unsupportedParameterTag " << toString(tag); + return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, + "ParameterNotSupported"); + } + } +} + +ndk::ScopedAStatus EffectImpl::getParameter(const Parameter::Id& id, Parameter* param) { + LOG(DEBUG) << __func__ << id.toString(); + auto tag = id.getTag(); + switch (tag) { + case Parameter::Id::commonTag: { + RETURN_IF_ASTATUS_NOT_OK(getParameterCommon(id.get(), param), + "CommonParamNotSupported"); + break; + } + case Parameter::Id::vendorEffectTag: { + LOG(DEBUG) << __func__ << " noop for vendor tag"; + return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, + "vendortagNotSupported"); + } + default: { + Parameter::Specific specific; + RETURN_IF_ASTATUS_NOT_OK(getParameterSpecific(id, &specific), "SpecParamNotSupported"); + param->set(specific); + break; + } + } + LOG(DEBUG) << __func__ << param->toString(); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus EffectImpl::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()) != RetCode::SUCCESS, + EX_ILLEGAL_ARGUMENT, "setCommFailed"); + break; + case Parameter::deviceDescription: + RETURN_IF(mContext->setOutputDevice(param.get()) != + RetCode::SUCCESS, + EX_ILLEGAL_ARGUMENT, "setDeviceFailed"); + break; + case Parameter::mode: + RETURN_IF(mContext->setAudioMode(param.get()) != RetCode::SUCCESS, + EX_ILLEGAL_ARGUMENT, "setModeFailed"); + break; + case Parameter::source: + RETURN_IF(mContext->setAudioSource(param.get()) != RetCode::SUCCESS, + EX_ILLEGAL_ARGUMENT, "setSourceFailed"); + break; + case Parameter::volumeStereo: + RETURN_IF(mContext->setVolumeStereo(param.get()) != + 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 EffectImpl::getParameterCommon(const Parameter::Tag& tag, Parameter* param) { + std::lock_guard lg(mMutex); + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); + switch (tag) { + case Parameter::common: { + param->set(mContext->getCommon()); + break; + } + case Parameter::deviceDescription: { + param->set(mContext->getOutputDevice()); + break; + } + case Parameter::mode: { + param->set(mContext->getAudioMode()); + break; + } + case Parameter::source: { + param->set(mContext->getAudioSource()); + break; + } + case Parameter::volumeStereo: { + param->set(mContext->getVolumeStereo()); + break; + } + default: { + LOG(DEBUG) << __func__ << " unsupported tag " << toString(tag); + return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, + "tagNotSupported"); + } + } + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus EffectImpl::getState(State* state) { + std::lock_guard lg(mMutex); + *state = mState; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus EffectImpl::command(CommandId command) { + std::lock_guard lg(mMutex); + LOG(DEBUG) << __func__ << ": receive command: " << toString(command) << " at state " + << toString(mState); + RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "CommandStateError"); + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); + + switch (command) { + case CommandId::START: + RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "instanceNotOpen"); + RETURN_OK_IF(mState == State::PROCESSING); + RETURN_IF_ASTATUS_NOT_OK(commandStart(), "commandStartFailed"); + mState = State::PROCESSING; + startThread(); + return ndk::ScopedAStatus::ok(); + case CommandId::STOP: + RETURN_OK_IF(mState == State::IDLE); + mState = State::IDLE; + RETURN_IF_ASTATUS_NOT_OK(commandStop(), "commandStopFailed"); + stopThread(); + return ndk::ScopedAStatus::ok(); + case CommandId::RESET: + RETURN_OK_IF(mState == State::IDLE); + mState = State::IDLE; + RETURN_IF_ASTATUS_NOT_OK(commandStop(), "commandStopFailed"); + stopThread(); + mContext->resetBuffer(); + return ndk::ScopedAStatus::ok(); + default: + LOG(ERROR) << __func__ << " instance still processing"; + return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, + "CommandIdNotSupported"); + } + LOG(DEBUG) << __func__ << " transfer to state: " << toString(mState); + return ndk::ScopedAStatus::ok(); +} + +void EffectImpl::cleanUp() { + command(CommandId::STOP); + close(); +} + +IEffect::Status EffectImpl::status(binder_status_t status, size_t consumed, size_t produced) { + IEffect::Status ret; + ret.status = status; + ret.fmqConsumed = consumed; + ret.fmqProduced = produced; + return ret; +} + +// A placeholder processing implementation to copy samples from input to output +IEffect::Status EffectImpl::effectProcessImpl(float* in, float* out, int processSamples) { + // lock before access context/parameters + std::lock_guard lg(mMutex); + IEffect::Status status = {EX_NULL_POINTER, 0, 0}; + RETURN_VALUE_IF(!mContext, status, "nullContext"); + auto frameSize = mContext->getInputFrameSize(); + RETURN_VALUE_IF(0 == frameSize, status, "frameSizeIs0"); + LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << processSamples + << " frames " << processSamples * sizeof(float) / frameSize; + for (int i = 0; i < processSamples; i++) { + *out++ = *in++; + } + LOG(DEBUG) << __func__ << " done processing " << processSamples << " samples"; + return {STATUS_OK, processSamples, processSamples}; +} +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/bassboost/Android.bp b/audio/aidl/default/bassboost/Android.bp new file mode 100644 index 0000000000..f22eb952f4 --- /dev/null +++ b/audio/aidl/default/bassboost/Android.bp @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library_shared { + name: "libbassboostsw", + defaults: [ + "aidlaudioeffectservice_defaults", + "latest_android_media_audio_common_types_ndk_shared", + "latest_android_hardware_audio_effect_ndk_shared", + ], + srcs: [ + "BassBoostSw.cpp", + ":effectCommonFile", + ], + visibility: [ + "//hardware/interfaces/audio/aidl/default", + ], +} diff --git a/audio/aidl/default/bassboost/BassBoostSw.cpp b/audio/aidl/default/bassboost/BassBoostSw.cpp new file mode 100644 index 0000000000..3c39824445 --- /dev/null +++ b/audio/aidl/default/bassboost/BassBoostSw.cpp @@ -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. + */ + +#include +#define LOG_TAG "AHAL_BassBoostSw" +#include +#include +#include + +#include +#include + +#include "BassBoostSw.h" + +using aidl::android::hardware::audio::effect::BassBoostSw; +using aidl::android::hardware::audio::effect::BassBoostSwImplUUID; +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* in_impl_uuid, + std::shared_ptr* instanceSpp) { + if (!in_impl_uuid || *in_impl_uuid != BassBoostSwImplUUID) { + LOG(ERROR) << __func__ << "uuid not supported"; + return EX_ILLEGAL_ARGUMENT; + } + if (instanceSpp) { + *instanceSpp = ndk::SharedRefBase::make(); + 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& instanceSp) { + if (!instanceSp) { + return EX_NONE; + } + 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 { + +ndk::ScopedAStatus BassBoostSw::getDescriptor(Descriptor* _aidl_return) { + LOG(DEBUG) << __func__ << kDescriptor.toString(); + *_aidl_return = kDescriptor; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus BassBoostSw::setParameterSpecific(const Parameter::Specific& specific) { + RETURN_IF(Parameter::Specific::bassBoost != specific.getTag(), EX_ILLEGAL_ARGUMENT, + "EffectNotSupported"); + std::lock_guard lg(mMutex); + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); + + mSpecificParam = specific.get(); + LOG(DEBUG) << __func__ << " success with: " << specific.toString(); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus BassBoostSw::getParameterSpecific(const Parameter::Id& id, + Parameter::Specific* specific) { + auto tag = id.getTag(); + RETURN_IF(Parameter::Id::bassBoostTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag"); + specific->set(mSpecificParam); + return ndk::ScopedAStatus::ok(); +} + +std::shared_ptr BassBoostSw::createContext(const Parameter::Common& common) { + if (mContext) { + LOG(DEBUG) << __func__ << " context already exist"; + return mContext; + } + mContext = std::make_shared(1 /* statusFmqDepth */, common); + return mContext; +} + +RetCode BassBoostSw::releaseContext() { + if (mContext) { + mContext.reset(); + } + return RetCode::SUCCESS; +} + +// Processing method running in EffectWorker thread. +IEffect::Status BassBoostSw::effectProcessImpl(float* in, float* out, int process) { + // TODO: get data buffer and process. + LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process; + for (int i = 0; i < process; i++) { + *out++ = *in++; + } + return {STATUS_OK, process, process}; +} + +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/bassboost/BassBoostSw.h b/audio/aidl/default/bassboost/BassBoostSw.h new file mode 100644 index 0000000000..b44e968197 --- /dev/null +++ b/audio/aidl/default/bassboost/BassBoostSw.h @@ -0,0 +1,72 @@ +/* + * 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 +#include +#include +#include + +#include "effect-impl/EffectImpl.h" +#include "effect-impl/EffectUUID.h" + +namespace aidl::android::hardware::audio::effect { + +class BassBoostSwContext : public EffectContext { + public: + BassBoostSwContext(int statusDepth, const Parameter::Common& common) + : EffectContext(statusDepth, common) { + LOG(DEBUG) << __func__; + } + // TODO: add specific context here +}; + +class BassBoostSw : public EffectImpl { + public: + BassBoostSw() { LOG(DEBUG) << __func__; } + ~BassBoostSw() { + LOG(DEBUG) << __func__; + releaseContext(); + } + + ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) 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 createContext(const Parameter::Common& common) override; + RetCode releaseContext() override; + + private: + std::shared_ptr mContext; + /* capabilities */ + const BassBoost::Capability kCapability; + /* Effect descriptor */ + const Descriptor kDescriptor = { + .common = {.id = {.type = BassBoostTypeUUID, + .uuid = BassBoostSwImplUUID, + .proxy = std::nullopt}, + .flags = {.type = Flags::Type::INSERT, + .insert = Flags::Insert::FIRST, + .volume = Flags::Volume::CTRL}, + .name = "BassBoostSw"}, + .capability = Capability::make(kCapability)}; + + /* parameters */ + BassBoost mSpecificParam; +}; +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/dynamicProcessing/Android.bp b/audio/aidl/default/dynamicProcessing/Android.bp new file mode 100644 index 0000000000..3697ba36ff --- /dev/null +++ b/audio/aidl/default/dynamicProcessing/Android.bp @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library_shared { + name: "libdynamicsprocessingsw", + defaults: [ + "aidlaudioeffectservice_defaults", + "latest_android_media_audio_common_types_ndk_shared", + "latest_android_hardware_audio_effect_ndk_shared", + ], + srcs: [ + "DynamicsProcessingSw.cpp", + ":effectCommonFile", + ], + visibility: [ + "//hardware/interfaces/audio/aidl/default", + ], +} diff --git a/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp new file mode 100644 index 0000000000..52403e17c7 --- /dev/null +++ b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp @@ -0,0 +1,119 @@ +/* + * 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. + */ + +#include +#define LOG_TAG "AHAL_DynamicsProcessingSw" +#include +#include +#include + +#include +#include + +#include "DynamicsProcessingSw.h" + +using aidl::android::hardware::audio::effect::DynamicsProcessingSw; +using aidl::android::hardware::audio::effect::DynamicsProcessingSwImplUUID; +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* in_impl_uuid, + std::shared_ptr* instanceSpp) { + if (!in_impl_uuid || *in_impl_uuid != DynamicsProcessingSwImplUUID) { + LOG(ERROR) << __func__ << "uuid not supported"; + return EX_ILLEGAL_ARGUMENT; + } + if (instanceSpp) { + *instanceSpp = ndk::SharedRefBase::make(); + 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& instanceSp) { + if (!instanceSp) { + return EX_NONE; + } + 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 { + +ndk::ScopedAStatus DynamicsProcessingSw::getDescriptor(Descriptor* _aidl_return) { + LOG(DEBUG) << __func__ << kDescriptor.toString(); + *_aidl_return = kDescriptor; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus DynamicsProcessingSw::setParameterSpecific(const Parameter::Specific& specific) { + RETURN_IF(Parameter::Specific::dynamicsProcessing != specific.getTag(), EX_ILLEGAL_ARGUMENT, + "EffectNotSupported"); + std::lock_guard lg(mMutex); + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); + + mSpecificParam = specific.get(); + LOG(DEBUG) << __func__ << " success with: " << specific.toString(); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus DynamicsProcessingSw::getParameterSpecific(const Parameter::Id& id, + Parameter::Specific* specific) { + auto tag = id.getTag(); + RETURN_IF(Parameter::Id::dynamicsProcessingTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag"); + specific->set(mSpecificParam); + return ndk::ScopedAStatus::ok(); +} + +std::shared_ptr DynamicsProcessingSw::createContext( + const Parameter::Common& common) { + if (mContext) { + LOG(DEBUG) << __func__ << " context already exist"; + return mContext; + } + mContext = std::make_shared(1 /* statusFmqDepth */, common); + return mContext; +} + +RetCode DynamicsProcessingSw::releaseContext() { + if (mContext) { + mContext.reset(); + } + return RetCode::SUCCESS; +} + +// Processing method running in EffectWorker thread. +IEffect::Status DynamicsProcessingSw::effectProcessImpl(float* in, float* out, int process) { + // TODO: get data buffer and process. + LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process; + for (int i = 0; i < process; i++) { + *out++ = *in++; + } + return {STATUS_OK, process, process}; +} + +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h new file mode 100644 index 0000000000..ef94e32b4b --- /dev/null +++ b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h @@ -0,0 +1,72 @@ +/* + * 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 +#include +#include +#include + +#include "effect-impl/EffectImpl.h" +#include "effect-impl/EffectUUID.h" + +namespace aidl::android::hardware::audio::effect { + +class DynamicsProcessingSwContext : public EffectContext { + public: + DynamicsProcessingSwContext(int statusDepth, const Parameter::Common& common) + : EffectContext(statusDepth, common) { + LOG(DEBUG) << __func__; + } + // TODO: add specific context here +}; + +class DynamicsProcessingSw : public EffectImpl { + public: + DynamicsProcessingSw() { LOG(DEBUG) << __func__; } + ~DynamicsProcessingSw() { + LOG(DEBUG) << __func__; + releaseContext(); + } + + ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) 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 createContext(const Parameter::Common& common) override; + RetCode releaseContext() override; + + private: + std::shared_ptr mContext; + /* capabilities */ + const DynamicsProcessing::Capability kCapability; + /* Effect descriptor */ + const Descriptor kDescriptor = { + .common = {.id = {.type = DynamicsProcessingTypeUUID, + .uuid = DynamicsProcessingSwImplUUID, + .proxy = std::nullopt}, + .flags = {.type = Flags::Type::INSERT, + .insert = Flags::Insert::FIRST, + .volume = Flags::Volume::CTRL}, + .name = "DynamicsProcessingSw"}, + .capability = Capability::make(kCapability)}; + + /* parameters */ + DynamicsProcessing mSpecificParam; +}; +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/equalizer/Android.bp b/audio/aidl/default/equalizer/Android.bp index 2a2ddbc92c..69d7450ea0 100644 --- a/audio/aidl/default/equalizer/Android.bp +++ b/audio/aidl/default/equalizer/Android.bp @@ -24,15 +24,9 @@ package { } cc_library_shared { - name: "libequalizer", - vendor: true, - shared_libs: [ - "libaudioaidlcommon", - "libbase", - "android.hardware.common-V2-ndk", - ], + name: "libequalizersw", defaults: [ - "aidlaudioservice_defaults", + "aidlaudioeffectservice_defaults", "latest_android_media_audio_common_types_ndk_shared", "latest_android_hardware_audio_effect_ndk_shared", ], @@ -40,12 +34,6 @@ cc_library_shared { "Equalizer.cpp", ":effectCommonFile", ], - cflags: [ - "-Wall", - "-Wextra", - "-Werror", - "-Wthread-safety", - ], visibility: [ "//hardware/interfaces/audio/aidl/default", ], diff --git a/audio/aidl/default/equalizer/Equalizer.cpp b/audio/aidl/default/equalizer/Equalizer.cpp index 43fa206151..0e07d3981f 100644 --- a/audio/aidl/default/equalizer/Equalizer.cpp +++ b/audio/aidl/default/equalizer/Equalizer.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #define LOG_TAG "AHAL_EqualizerSw" #include #include @@ -24,11 +25,18 @@ #include "equalizer-impl/EqualizerSw.h" -using android::hardware::audio::common::getFrameSizeInBytes; +using aidl::android::hardware::audio::effect::EqualizerSw; +using aidl::android::hardware::audio::effect::EqualizerSwImplUUID; +using aidl::android::hardware::audio::effect::IEffect; +using aidl::android::hardware::audio::effect::State; +using aidl::android::media::audio::common::AudioUuid; -namespace aidl::android::hardware::audio::effect { - -extern "C" binder_exception_t createEffect(std::shared_ptr* instanceSpp) { +extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid, + std::shared_ptr* instanceSpp) { + if (!in_impl_uuid || *in_impl_uuid != EqualizerSwImplUUID) { + LOG(ERROR) << __func__ << "uuid not supported"; + return EX_ILLEGAL_ARGUMENT; + } if (instanceSpp) { *instanceSpp = ndk::SharedRefBase::make(); LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created"; @@ -51,212 +59,39 @@ extern "C" binder_exception_t destroyEffect(const std::shared_ptr& inst return EX_NONE; } -ndk::ScopedAStatus EqualizerSw::open(const Parameter::Common& common, - const Parameter::Specific& specific, - OpenEffectReturn* _aidl_return) { - LOG(DEBUG) << __func__; - if (mState != State::INIT) { - LOG(WARNING) << __func__ << " eq already open"; - return ndk::ScopedAStatus::ok(); - } - - // Set essential parameters before create worker thread. - setCommonParameter(common); - setSpecificParameter(specific); - - LOG(DEBUG) << " common: " << common.toString() << " specific " << specific.toString(); - - auto& input = common.input; - auto& output = common.output; - size_t inputFrameSize = getFrameSizeInBytes(input.base.format, input.base.channelMask); - size_t outputFrameSize = getFrameSizeInBytes(output.base.format, output.base.channelMask); - mContext = std::make_shared(1, input.frameCount * inputFrameSize, - output.frameCount * outputFrameSize); - if (!mContext) { - LOG(ERROR) << __func__ << " created EqualizerSwContext failed"; - return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_UNSUPPORTED_OPERATION, - "FailedToCreateFmq"); - } - setContext(mContext); - - // create the worker thread - if (RetCode::SUCCESS != createThread(LOG_TAG)) { - LOG(ERROR) << __func__ << " created worker thread failed"; - mContext.reset(); - return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_UNSUPPORTED_OPERATION, - "FailedToCreateWorker"); - } - - _aidl_return->statusMQ = mContext->getStatusFmq()->dupeDesc(); - _aidl_return->inputDataMQ = mContext->getInputDataFmq()->dupeDesc(); - _aidl_return->outputDataMQ = mContext->getOutputDataFmq()->dupeDesc(); - mState = State::IDLE; - return ndk::ScopedAStatus::ok(); -} - -ndk::ScopedAStatus EqualizerSw::close() { - if (mState == State::INIT) { - LOG(WARNING) << __func__ << " instance already closed"; - return ndk::ScopedAStatus::ok(); - } else if (mState == State::PROCESSING) { - LOG(ERROR) << __func__ << " instance still processing"; - return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE, - "EqInstanceProcessing"); - } - - // stop the worker thread - mState = State::INIT; - destroyThread(); - mContext.reset(); - - LOG(DEBUG) << __func__; - return ndk::ScopedAStatus::ok(); -} +namespace aidl::android::hardware::audio::effect { ndk::ScopedAStatus EqualizerSw::getDescriptor(Descriptor* _aidl_return) { - LOG(DEBUG) << __func__ << mDesc.toString(); - *_aidl_return = mDesc; + LOG(DEBUG) << __func__ << kDesc.toString(); + *_aidl_return = kDesc; return ndk::ScopedAStatus::ok(); } -ndk::ScopedAStatus EqualizerSw::command(CommandId in_commandId) { - LOG(DEBUG) << __func__ << ": receive command:" << toString(in_commandId); - if (mState == State::INIT) { - LOG(ERROR) << __func__ << ": instance not open yet"; - return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE, - "CommandStateError"); - } - switch (in_commandId) { - case CommandId::START: - // start processing. - mState = State::PROCESSING; - startThread(); - LOG(DEBUG) << __func__ << " state: " << toString(mState); - return ndk::ScopedAStatus::ok(); - case CommandId::STOP: - // stop processing. - mState = State::IDLE; - stopThread(); - LOG(DEBUG) << __func__ << " state: " << toString(mState); - return ndk::ScopedAStatus::ok(); - case CommandId::RESET: - // TODO: reset buffer status. - mState = State::IDLE; - stopThread(); - LOG(DEBUG) << __func__ << " state: " << toString(mState); - return ndk::ScopedAStatus::ok(); - default: - return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, - "CommandIdNotSupported"); - } - return ndk::ScopedAStatus::ok(); -} - -ndk::ScopedAStatus EqualizerSw::setParameter(const Parameter& in_param) { - if (mState == State::INIT) { - LOG(ERROR) << __func__ << ": instance not open yet"; - return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE, "StateError"); - } - LOG(DEBUG) << __func__ << " with: " << in_param.toString(); - auto tag = in_param.getTag(); - switch (tag) { - case Parameter::common: { - return setCommonParameter(in_param.get()); - } - case Parameter::specific: { - return setSpecificParameter(in_param.get()); - } - default: - return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, - "ParameterNotSupported"); - } -} - -ndk::ScopedAStatus EqualizerSw::getParameter(const Parameter::Id& in_paramId, - Parameter* _aidl_return) { - LOG(DEBUG) << __func__ << in_paramId.toString(); - auto tag = in_paramId.getTag(); - switch (tag) { - case Parameter::Id::commonTag: { - _aidl_return->set(mCommonParam); - LOG(DEBUG) << __func__ << " get: " << _aidl_return->toString(); - return ndk::ScopedAStatus::ok(); - } - case Parameter::Id::specificId: { - auto& id = in_paramId.get(); - Parameter::Specific specific; - ndk::ScopedAStatus status = getSpecificParameter(id, &specific); - if (!status.isOk()) { - LOG(ERROR) << __func__ - << " getSpecificParameter error: " << status.getDescription(); - return status; - } - _aidl_return->set(specific); - LOG(DEBUG) << __func__ << _aidl_return->toString(); - return ndk::ScopedAStatus::ok(); - } - case Parameter::Id::vendorTag: { - LOG(DEBUG) << __func__ << " noop for vendor tag now"; - return ndk::ScopedAStatus::ok(); - } - } - LOG(ERROR) << " unsupported tag: " << toString(tag); - return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, - "Parameter:IdNotSupported"); -} - -ndk::ScopedAStatus EqualizerSw::getState(State* _aidl_return) { - *_aidl_return = mState; - return ndk::ScopedAStatus::ok(); -} - -/// Private methods. -ndk::ScopedAStatus EqualizerSw::setCommonParameter(const Parameter::Common& common) { - mCommonParam = common; - LOG(DEBUG) << __func__ << " set: " << mCommonParam.toString(); - return ndk::ScopedAStatus::ok(); -} - -ndk::ScopedAStatus EqualizerSw::setSpecificParameter(const Parameter::Specific& specific) { - if (Parameter::Specific::equalizer != specific.getTag()) { - LOG(ERROR) << " unsupported effect: " << specific.toString(); - return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, - "EffectNotSupported"); - } +ndk::ScopedAStatus EqualizerSw::setParameterSpecific(const Parameter::Specific& specific) { + RETURN_IF(Parameter::Specific::equalizer != specific.getTag(), EX_ILLEGAL_ARGUMENT, + "EffectNotSupported"); + std::lock_guard lg(mMutex); + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); auto& eqParam = specific.get(); auto tag = eqParam.getTag(); switch (tag) { - case Equalizer::bandLevels: { - auto& bandLevels = eqParam.get(); - const auto& [minItem, maxItem] = std::minmax_element( - bandLevels.begin(), bandLevels.end(), - [](const auto& a, const auto& b) { return a.index < b.index; }); - if (bandLevels.size() >= NUM_OF_BANDS || minItem->index < 0 || - maxItem->index >= NUM_OF_BANDS) { - LOG(ERROR) << " bandLevels " << bandLevels.size() << "minIndex " << minItem->index - << "maxIndex " << maxItem->index << " illegal "; - return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, - "ExceedMaxBandNum"); - } - mBandLevels = bandLevels; - return ndk::ScopedAStatus::ok(); - } case Equalizer::preset: { - int preset = eqParam.get(); - if (preset < 0 || preset >= NUM_OF_PRESETS) { - LOG(ERROR) << " preset: " << preset << " invalid"; - return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, - "ExceedMaxBandNum"); - } - mPreset = preset; - LOG(DEBUG) << __func__ << " preset set to " << mPreset; + RETURN_IF(mContext->setEqPreset(eqParam.get()) != RetCode::SUCCESS, + EX_ILLEGAL_ARGUMENT, "setBandLevelsFailed"); return ndk::ScopedAStatus::ok(); } - case Equalizer::vendor: { - LOG(DEBUG) << __func__ << " noop for vendor tag now"; + case Equalizer::bandLevels: { + RETURN_IF(mContext->setEqBandLevels(eqParam.get()) != + RetCode::SUCCESS, + EX_ILLEGAL_ARGUMENT, "setBandLevelsFailed"); return ndk::ScopedAStatus::ok(); } + default: { + LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); + return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, + "EqTagNotSupported"); + } } LOG(ERROR) << __func__ << " unsupported eq param tag: " << toString(tag); @@ -264,59 +99,72 @@ ndk::ScopedAStatus EqualizerSw::setSpecificParameter(const Parameter::Specific& "ParamNotSupported"); } -ndk::ScopedAStatus EqualizerSw::getSpecificParameter(Parameter::Specific::Id id, +ndk::ScopedAStatus EqualizerSw::getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific) { - Equalizer eqParam; auto tag = id.getTag(); - if (tag != Parameter::Specific::Id::equalizerTag) { - LOG(ERROR) << " invalid tag: " << toString(tag); - return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, - "UnsupportedTag"); + RETURN_IF(Parameter::Id::equalizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag"); + auto eqId = id.get(); + auto eqIdTag = eqId.getTag(); + switch (eqIdTag) { + case Equalizer::Id::commonTag: + return getParameterEqualizer(eqId.get(), specific); + default: + LOG(ERROR) << __func__ << " tag " << toString(eqIdTag) << " not supported"; + return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, + "EqualizerTagNotSupported"); } - auto eqTag = id.get(); - switch (eqTag) { +} + +ndk::ScopedAStatus EqualizerSw::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(mBandLevels); - specific->set(eqParam); - return ndk::ScopedAStatus::ok(); + eqParam.set(mContext->getEqBandLevels()); + break; } case Equalizer::preset: { - eqParam.set(mPreset); - LOG(DEBUG) << __func__ << " preset " << mPreset; - specific->set(eqParam); - return ndk::ScopedAStatus::ok(); + eqParam.set(mContext->getEqPreset()); + break; } - case Equalizer::vendor: { - LOG(DEBUG) << __func__ << " noop for vendor tag now"; - return ndk::ScopedAStatus::ok(); + default: { + LOG(ERROR) << __func__ << " not handled tag: " << toString(tag); + return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, + "unsupportedTag"); } } - LOG(ERROR) << __func__ << " unsupported eq param: " << toString(eqTag); - return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, - "ParamNotSupported"); + + specific->set(eqParam); + return ndk::ScopedAStatus::ok(); } -void EqualizerSw::cleanUp() { - if (State::PROCESSING == mState) { - command(CommandId::STOP); - } - if (State::INIT != mState) { - close(); +std::shared_ptr EqualizerSw::createContext(const Parameter::Common& common) { + if (mContext) { + LOG(DEBUG) << __func__ << " context already exist"; + return mContext; } + mContext = std::make_shared(1 /* statusFmqDepth */, common); + return mContext; } -IEffect::Status EqualizerSw::status(binder_status_t status, size_t consumed, size_t produced) { - IEffect::Status ret; - ret.status = status; - ret.fmqByteConsumed = consumed; - ret.fmqByteProduced = produced; - return ret; +RetCode EqualizerSw::releaseContext() { + if (mContext) { + mContext.reset(); + } + return RetCode::SUCCESS; } // Processing method running in EffectWorker thread. -IEffect::Status EqualizerSw::effectProcessImpl() { +IEffect::Status EqualizerSw::effectProcessImpl(float* in, float* out, int process) { // TODO: get data buffer and process. - return status(STATUS_OK, mContext->availableToRead(), mContext->availableToWrite()); + LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process; + for (int i = 0; i < process; i++) { + *out++ = *in++; + } + return {STATUS_OK, process, process}; } } // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/hapticGenerator/Android.bp b/audio/aidl/default/hapticGenerator/Android.bp new file mode 100644 index 0000000000..a632130c1a --- /dev/null +++ b/audio/aidl/default/hapticGenerator/Android.bp @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library_shared { + name: "libhapticgeneratorsw", + defaults: [ + "aidlaudioeffectservice_defaults", + "latest_android_media_audio_common_types_ndk_shared", + "latest_android_hardware_audio_effect_ndk_shared", + ], + srcs: [ + "HapticGeneratorSw.cpp", + ":effectCommonFile", + ], + visibility: [ + "//hardware/interfaces/audio/aidl/default", + ], +} diff --git a/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp new file mode 100644 index 0000000000..90675c2372 --- /dev/null +++ b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp @@ -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. + */ + +#include +#define LOG_TAG "AHAL_HapticGeneratorSw" +#include +#include +#include + +#include +#include + +#include "HapticGeneratorSw.h" + +using aidl::android::hardware::audio::effect::HapticGeneratorSw; +using aidl::android::hardware::audio::effect::HapticGeneratorSwImplUUID; +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* in_impl_uuid, + std::shared_ptr* instanceSpp) { + if (!in_impl_uuid || *in_impl_uuid != HapticGeneratorSwImplUUID) { + LOG(ERROR) << __func__ << "uuid not supported"; + return EX_ILLEGAL_ARGUMENT; + } + if (instanceSpp) { + *instanceSpp = ndk::SharedRefBase::make(); + 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& instanceSp) { + if (!instanceSp) { + return EX_NONE; + } + 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 { + +ndk::ScopedAStatus HapticGeneratorSw::getDescriptor(Descriptor* _aidl_return) { + LOG(DEBUG) << __func__ << kDescriptor.toString(); + *_aidl_return = kDescriptor; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus HapticGeneratorSw::setParameterSpecific(const Parameter::Specific& specific) { + RETURN_IF(Parameter::Specific::hapticGenerator != specific.getTag(), EX_ILLEGAL_ARGUMENT, + "EffectNotSupported"); + std::lock_guard lg(mMutex); + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); + + mSpecificParam = specific.get(); + LOG(DEBUG) << __func__ << " success with: " << specific.toString(); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus HapticGeneratorSw::getParameterSpecific(const Parameter::Id& id, + Parameter::Specific* specific) { + auto tag = id.getTag(); + RETURN_IF(Parameter::Id::hapticGeneratorTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag"); + specific->set(mSpecificParam); + return ndk::ScopedAStatus::ok(); +} + +std::shared_ptr HapticGeneratorSw::createContext(const Parameter::Common& common) { + if (mContext) { + LOG(DEBUG) << __func__ << " context already exist"; + return mContext; + } + mContext = std::make_shared(1 /* statusFmqDepth */, common); + return mContext; +} + +RetCode HapticGeneratorSw::releaseContext() { + if (mContext) { + mContext.reset(); + } + return RetCode::SUCCESS; +} + +// Processing method running in EffectWorker thread. +IEffect::Status HapticGeneratorSw::effectProcessImpl(float* in, float* out, int process) { + // TODO: get data buffer and process. + LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process; + for (int i = 0; i < process; i++) { + *out++ = *in++; + } + return {STATUS_OK, process, process}; +} + +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h new file mode 100644 index 0000000000..95a8d99bbf --- /dev/null +++ b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h @@ -0,0 +1,72 @@ +/* + * 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 +#include +#include +#include + +#include "effect-impl/EffectImpl.h" +#include "effect-impl/EffectUUID.h" + +namespace aidl::android::hardware::audio::effect { + +class HapticGeneratorSwContext : public EffectContext { + public: + HapticGeneratorSwContext(int statusDepth, const Parameter::Common& common) + : EffectContext(statusDepth, common) { + LOG(DEBUG) << __func__; + } + // TODO: add specific context here +}; + +class HapticGeneratorSw : public EffectImpl { + public: + HapticGeneratorSw() { LOG(DEBUG) << __func__; } + ~HapticGeneratorSw() { + LOG(DEBUG) << __func__; + releaseContext(); + } + + ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) 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 createContext(const Parameter::Common& common) override; + RetCode releaseContext() override; + + private: + std::shared_ptr mContext; + /* capabilities */ + const HapticGenerator::Capability kCapability; + /* Effect descriptor */ + const Descriptor kDescriptor = { + .common = {.id = {.type = HapticGeneratorTypeUUID, + .uuid = HapticGeneratorSwImplUUID, + .proxy = std::nullopt}, + .flags = {.type = Flags::Type::INSERT, + .insert = Flags::Insert::FIRST, + .volume = Flags::Volume::CTRL}, + .name = "HapticGeneratorSw"}, + .capability = Capability::make(kCapability)}; + + /* parameters */ + HapticGenerator mSpecificParam; +}; +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/include/effect-impl/EffectContext.h b/audio/aidl/default/include/effect-impl/EffectContext.h index 36492ec05f..f608e12e1b 100644 --- a/audio/aidl/default/include/effect-impl/EffectContext.h +++ b/audio/aidl/default/include/effect-impl/EffectContext.h @@ -15,6 +15,10 @@ */ #pragma once +#include +#include +#include +#include #include #include #include @@ -22,6 +26,7 @@ #include #include +#include "EffectTypes.h" namespace aidl::android::hardware::audio::effect { @@ -31,35 +36,122 @@ class EffectContext { IEffect::Status, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> StatusMQ; typedef ::android::AidlMessageQueue< - int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> + float, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> DataMQ; - EffectContext(size_t statusDepth, size_t inBufferSize, size_t outBufferSize) { + EffectContext(size_t statusDepth, const Parameter::Common& common) { + mSessionId = common.session; + auto& input = common.input; + auto& output = common.output; + + LOG_ALWAYS_FATAL_IF( + input.base.format.pcm != aidl::android::media::audio::common::PcmType::FLOAT_32_BIT, + "inputFormatNotFloat"); + LOG_ALWAYS_FATAL_IF(output.base.format.pcm != + aidl::android::media::audio::common::PcmType::FLOAT_32_BIT, + "outputFormatNotFloat"); + mInputFrameSize = ::android::hardware::audio::common::getFrameSizeInBytes( + input.base.format, input.base.channelMask); + mOutputFrameSize = ::android::hardware::audio::common::getFrameSizeInBytes( + output.base.format, output.base.channelMask); + // in/outBuffer size in float (FMQ data format defined for DataMQ) + size_t inBufferSizeInFloat = input.frameCount * mInputFrameSize / sizeof(float); + size_t outBufferSizeInFloat = output.frameCount * mOutputFrameSize / sizeof(float); + mStatusMQ = std::make_shared(statusDepth, true /*configureEventFlagWord*/); - mInputMQ = std::make_shared(inBufferSize); - mOutputMQ = std::make_shared(outBufferSize); + mInputMQ = std::make_shared(inBufferSizeInFloat); + mOutputMQ = std::make_shared(outBufferSizeInFloat); if (!mStatusMQ->isValid() || !mInputMQ->isValid() || !mOutputMQ->isValid()) { LOG(ERROR) << __func__ << " created invalid FMQ"; } - mWorkBuffer.reserve(std::max(inBufferSize, outBufferSize)); - }; + mWorkBuffer.reserve(std::max(inBufferSizeInFloat, outBufferSizeInFloat)); + } + virtual ~EffectContext() {} - std::shared_ptr getStatusFmq() { return mStatusMQ; }; - std::shared_ptr getInputDataFmq() { return mInputMQ; }; - std::shared_ptr getOutputDataFmq() { return mOutputMQ; }; + std::shared_ptr getStatusFmq() { return mStatusMQ; } + std::shared_ptr getInputDataFmq() { return mInputMQ; } + std::shared_ptr getOutputDataFmq() { return mOutputMQ; } - int8_t* getWorkBuffer() { return static_cast(mWorkBuffer.data()); }; + float* getWorkBuffer() { return static_cast(mWorkBuffer.data()); } // TODO: update with actual available size - size_t availableToRead() { return mWorkBuffer.capacity(); }; - size_t availableToWrite() { return mWorkBuffer.capacity(); }; + size_t availableToRead() { return mWorkBuffer.capacity(); } + size_t availableToWrite() { return mWorkBuffer.capacity(); } + + // reset buffer status by abandon all data and status in FMQ + void resetBuffer() { + auto buffer = getWorkBuffer(); + std::vector status(mStatusMQ->availableToRead()); + mInputMQ->read(buffer, mInputMQ->availableToRead()); + mOutputMQ->read(buffer, mOutputMQ->availableToRead()); + mStatusMQ->read(status.data(), mStatusMQ->availableToRead()); + } + + void dupeFmq(IEffect::OpenEffectReturn* effectRet) { + if (effectRet) { + effectRet->statusMQ = getStatusFmq()->dupeDesc(); + effectRet->inputDataMQ = getInputDataFmq()->dupeDesc(); + effectRet->outputDataMQ = getOutputDataFmq()->dupeDesc(); + } + } + size_t getInputFrameSize() { return mInputFrameSize; } + size_t getOutputFrameSize() { return mOutputFrameSize; } + int getSessionId() { return mSessionId; } + + virtual RetCode setOutputDevice( + const aidl::android::media::audio::common::AudioDeviceDescription& device) { + mOutputDevice = device; + return RetCode::SUCCESS; + } + virtual aidl::android::media::audio::common::AudioDeviceDescription getOutputDevice() { + return mOutputDevice; + } + + virtual RetCode setAudioMode(const aidl::android::media::audio::common::AudioMode& mode) { + mMode = mode; + return RetCode::SUCCESS; + } + virtual aidl::android::media::audio::common::AudioMode getAudioMode() { return mMode; } + + virtual RetCode setAudioSource(const aidl::android::media::audio::common::AudioSource& source) { + mSource = source; + return RetCode::SUCCESS; + } + virtual aidl::android::media::audio::common::AudioSource getAudioSource() { return mSource; } + + virtual RetCode setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) { + mVolumeStereo = volumeStereo; + return RetCode::SUCCESS; + } + virtual Parameter::VolumeStereo getVolumeStereo() { return mVolumeStereo; } + + virtual RetCode setCommon(const Parameter::Common& common) { + mCommon = common; + LOG(ERROR) << __func__ << mCommon.toString(); + return RetCode::SUCCESS; + } + virtual Parameter::Common getCommon() { + LOG(ERROR) << __func__ << mCommon.toString(); + return mCommon; + } + + protected: + // common parameters + int mSessionId = INVALID_AUDIO_SESSION_ID; + size_t mInputFrameSize, mOutputFrameSize; + Parameter::Common mCommon; + aidl::android::media::audio::common::AudioDeviceDescription mOutputDevice; + aidl::android::media::audio::common::AudioMode mMode; + aidl::android::media::audio::common::AudioSource mSource; + Parameter::VolumeStereo mVolumeStereo; private: + // fmq and buffers std::shared_ptr mStatusMQ; std::shared_ptr mInputMQ; std::shared_ptr mOutputMQ; // TODO handle effect process input and output // work buffer set by effect instances, the access and update are in same thread - std::vector mWorkBuffer; + std::vector mWorkBuffer; }; } // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/include/effect-impl/EffectImpl.h b/audio/aidl/default/include/effect-impl/EffectImpl.h new file mode 100644 index 0000000000..cb395b729a --- /dev/null +++ b/audio/aidl/default/include/effect-impl/EffectImpl.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 +#include +#include +#include +#include + +#include "EffectTypes.h" +#include "effect-impl/EffectContext.h" +#include "effect-impl/EffectTypes.h" +#include "effect-impl/EffectWorker.h" + +namespace aidl::android::hardware::audio::effect { + +class EffectImpl : public BnEffect, public EffectWorker { + public: + EffectImpl() { LOG(DEBUG) << __func__; } + ~EffectImpl() { + cleanUp(); + LOG(DEBUG) << __func__; + } + + /** + * Each effect implementation CAN override these methods if necessary + * If you would like implement IEffect::open completely, override EffectImpl::open(), if you + * want to keep most of EffectImpl logic but have a little customize, try override openImpl(). + * openImpl() will be called at the beginning of EffectImpl::open() without lock protection. + * + * Same for closeImpl(). + */ + virtual ndk::ScopedAStatus open(const Parameter::Common& common, + const std::optional& specific, + OpenEffectReturn* ret) override; + virtual ndk::ScopedAStatus close() override; + virtual ndk::ScopedAStatus command(CommandId id) override; + virtual ndk::ScopedAStatus commandStart() { return ndk::ScopedAStatus::ok(); } + virtual ndk::ScopedAStatus commandStop() { return ndk::ScopedAStatus::ok(); } + virtual ndk::ScopedAStatus commandReset() { return ndk::ScopedAStatus::ok(); } + + virtual ndk::ScopedAStatus getState(State* state) override; + virtual ndk::ScopedAStatus setParameter(const Parameter& param) override; + virtual ndk::ScopedAStatus getParameter(const Parameter::Id& id, Parameter* param) override; + virtual IEffect::Status effectProcessImpl(float* in, float* out, int process) override; + + virtual ndk::ScopedAStatus setParameterCommon(const Parameter& param); + virtual ndk::ScopedAStatus getParameterCommon(const Parameter::Tag& tag, Parameter* param); + + /* Methods MUST be implemented by each effect instances */ + virtual ndk::ScopedAStatus getDescriptor(Descriptor* desc) = 0; + virtual ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) = 0; + virtual ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, + Parameter::Specific* specific) = 0; + virtual std::shared_ptr createContext(const Parameter::Common& common) = 0; + virtual RetCode releaseContext() = 0; + + protected: + /* + * Lock is required if effectProcessImpl (which is running in an independent thread) needs to + * access state and parameters. + */ + std::mutex mMutex; + State mState GUARDED_BY(mMutex) = State::INIT; + + IEffect::Status status(binder_status_t status, size_t consumed, size_t produced); + + private: + void cleanUp(); + std::shared_ptr mContext GUARDED_BY(mMutex); +}; +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/include/effect-impl/EffectTypes.h b/audio/aidl/default/include/effect-impl/EffectTypes.h index 46cfc0cb25..edce26b8ef 100644 --- a/audio/aidl/default/include/effect-impl/EffectTypes.h +++ b/audio/aidl/default/include/effect-impl/EffectTypes.h @@ -18,6 +18,19 @@ #include #include +#include + +typedef binder_exception_t (*EffectCreateFunctor)( + const ::aidl::android::media::audio::common::AudioUuid*, + std::shared_ptr*); +typedef binder_exception_t (*EffectDestroyFunctor)( + const std::shared_ptr&); + +struct effect_dl_interface_s { + EffectCreateFunctor createEffectFunc; + EffectDestroyFunctor destroyEffectFunc; +}; + namespace aidl::android::hardware::audio::effect { enum class RetCode { @@ -26,9 +39,12 @@ enum class RetCode { ERROR_THREAD, /* Effect thread error */ ERROR_NULL_POINTER, /* NULL pointer */ ERROR_ALIGNMENT_ERROR, /* Memory alignment error */ - ERROR_BLOCK_SIZE_EXCEED /* Maximum block size exceeded */ + ERROR_BLOCK_SIZE_EXCEED, /* Maximum block size exceeded */ + ERROR_EFFECT_LIB_ERROR }; +static const int INVALID_AUDIO_SESSION_ID = -1; + inline std::ostream& operator<<(std::ostream& out, const RetCode& code) { switch (code) { case RetCode::SUCCESS: @@ -43,9 +59,46 @@ inline std::ostream& operator<<(std::ostream& out, const RetCode& code) { return out << "ERROR_ALIGNMENT_ERROR"; case RetCode::ERROR_BLOCK_SIZE_EXCEED: return out << "ERROR_BLOCK_SIZE_EXCEED"; + case RetCode::ERROR_EFFECT_LIB_ERROR: + return out << "ERROR_EFFECT_LIB_ERROR"; } return out << "EnumError: " << code; } +#define RETURN_IF_ASTATUS_NOT_OK(status, message) \ + do { \ + const ::ndk::ScopedAStatus curr_status = (status); \ + if (!curr_status.isOk()) { \ + LOG(ERROR) << __func__ << ":" << __LINE__ \ + << "return with status: " << curr_status.getDescription() << (message); \ + return ndk::ScopedAStatus::fromExceptionCodeWithMessage( \ + curr_status.getExceptionCode(), (message)); \ + } \ + } while (0) + +#define RETURN_IF(expr, exception, message) \ + do { \ + if (expr) { \ + LOG(ERROR) << __func__ << ":" << __LINE__ << " return with expr " << #expr; \ + return ndk::ScopedAStatus::fromExceptionCodeWithMessage((exception), (message)); \ + } \ + } while (0) + +#define RETURN_OK_IF(expr) \ + do { \ + if (expr) { \ + LOG(INFO) << __func__ << ":" << __LINE__ << " return with expr " << #expr; \ + return ndk::ScopedAStatus::ok(); \ + } \ + } while (0) + +#define RETURN_VALUE_IF(expr, ret, log) \ + do { \ + if (expr) { \ + LOG(ERROR) << __func__ << ":" << __LINE__ << " return with expr " << #expr << (log); \ + return ret; \ + } \ + } while (0) + } // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/include/effect-impl/EffectUUID.h b/audio/aidl/default/include/effect-impl/EffectUUID.h index 48b7137981..767cf6c053 100644 --- a/audio/aidl/default/include/effect-impl/EffectUUID.h +++ b/audio/aidl/default/include/effect-impl/EffectUUID.h @@ -46,11 +46,124 @@ static const AudioUuid EqualizerSwImplUUID = {static_cast(0x0bed4300), 0xbb17, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}; -// Visualizer type UUID. -static const AudioUuid VisualizerTypeUUID = {static_cast(0x1d4033c0), - 0x8557, - 0x11df, - 0x9f2d, - {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}; +// Equalizer bundle implementation UUID. +static const AudioUuid EqualizerBundleImplUUID = {static_cast(0xce772f20), + 0x847d, + 0x11df, + 0xbb17, + {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}; + +// fa8184a4-588b-11ed-9b6a-0242ac120002 +static const AudioUuid BassBoostTypeUUID = {static_cast(0xfa8184a4), + 0x588b, + 0x11ed, + 0x9b6a, + {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}}; +// fa8181f2-588b-11ed-9b6a-0242ac120002 +static const AudioUuid BassBoostSwImplUUID = {static_cast(0xfa8181f2), + 0x588b, + 0x11ed, + 0x9b6a, + {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}}; +// fa81862a-588b-11ed-9b6a-0242ac120002 +static const AudioUuid DownmixTypeUUID = {static_cast(0xfa81862a), + 0x588b, + 0x11ed, + 0x9b6a, + {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}}; +// fa8187ba-588b-11ed-9b6a-0242ac120002 +static const AudioUuid DownmixSwImplUUID = {static_cast(0xfa8187ba), + 0x588b, + 0x11ed, + 0x9b6a, + {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}}; +// fa818954-588b-11ed-9b6a-0242ac120002 +static const AudioUuid DynamicsProcessingTypeUUID = {static_cast(0xfa818954), + 0x588b, + 0x11ed, + 0x9b6a, + {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}}; +// fa818d78-588b-11ed-9b6a-0242ac120002 +static const AudioUuid DynamicsProcessingSwImplUUID = {static_cast(0xfa818d78), + 0x588b, + 0x11ed, + 0x9b6a, + {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}}; +// fa818f62-588b-11ed-9b6a-0242ac120002 +static const AudioUuid HapticGeneratorTypeUUID = {static_cast(0xfa818f62), + 0x588b, + 0x11ed, + 0x9b6a, + {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}}; +// fa819110-588b-11ed-9b6a-0242ac120002 +static const AudioUuid HapticGeneratorSwImplUUID = {static_cast(0xfa819110), + 0x588b, + 0x11ed, + 0x9b6a, + {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}}; + +// fa8194a8-588b-11ed-9b6a-0242ac120002 +static const AudioUuid LoudnessEnhancerTypeUUID = {static_cast(0xfa8194a8), + 0x588b, + 0x11ed, + 0x9b6a, + {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}}; +// fa819610-588b-11ed-9b6a-0242ac120002 +static const AudioUuid LoudnessEnhancerSwImplUUID = {static_cast(0xfa819610), + 0x588b, + 0x11ed, + 0x9b6a, + {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}}; +// fa819886-588b-11ed-9b6a-0242ac120002 +static const AudioUuid ReverbTypeUUID = {static_cast(0xfa819886), + 0x588b, + 0x11ed, + 0x9b6a, + {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}}; +// fa8199c6-588b-11ed-9b6a-0242ac120002 +static const AudioUuid ReverbSwImplUUID = {static_cast(0xfa8199c6), + 0x588b, + 0x11ed, + 0x9b6a, + {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}}; + +// fa819af2-588b-11ed-9b6a-0242ac120002 +static const AudioUuid VirtualizerTypeUUID = {static_cast(0xfa819af2), + 0x588b, + 0x11ed, + 0x9b6a, + {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}}; +// fa819d86-588b-11ed-9b6a-0242ac120002 +static const AudioUuid VirtualizerSwImplUUID = {static_cast(0xfa819d86), + 0x588b, + 0x11ed, + 0x9b6a, + {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}}; + +// fa819f3e-588b-11ed-9b6a-0242ac120002 +static const AudioUuid VisualizerTypeUUID = {static_cast(0xfa819f3e), + 0x588b, + 0x11ed, + 0x9b6a, + {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}}; +// fa81a0f6-588b-11ed-9b6a-0242ac120002 +static const AudioUuid VisualizerSwImplUUID = {static_cast(0xfa81a0f6), + 0x588b, + 0x11ed, + 0x9b6a, + {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}}; + +// fa81a2b8-588b-11ed-9b6a-0242ac120002 +static const AudioUuid VolumeTypeUUID = {static_cast(0xfa81a2b8), + 0x588b, + 0x11ed, + 0x9b6a, + {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}}; +// fa81a718-588b-11ed-9b6a-0242ac120002 +static const AudioUuid VolumeSwImplUUID = {static_cast(0xfa81a718), + 0x588b, + 0x11ed, + 0x9b6a, + {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}}; } // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/include/effect-impl/EffectWorker.h b/audio/aidl/default/include/effect-impl/EffectWorker.h index 0fe69ff907..a297937734 100644 --- a/audio/aidl/default/include/effect-impl/EffectWorker.h +++ b/audio/aidl/default/include/effect-impl/EffectWorker.h @@ -36,34 +36,33 @@ class EffectWorker : public EffectThread { // handle FMQ and call effect implemented virtual function void process() override { - if (!mContext) { - LOG(ERROR) << __func__ << " invalid context!"; - return; - } + RETURN_VALUE_IF(!mContext, void(), "nullContext"); std::shared_ptr statusMQ = mContext->getStatusFmq(); std::shared_ptr inputMQ = mContext->getInputDataFmq(); std::shared_ptr outputMQ = mContext->getOutputDataFmq(); // Only this worker will read from input data MQ and write to output data MQ. - auto readSize = inputMQ->availableToRead(), writeSize = outputMQ->availableToWrite(); - if (readSize && writeSize) { - LOG(DEBUG) << __func__ << " available to read " << readSize << " available to write " - << writeSize; + auto readSamples = inputMQ->availableToRead(), writeSamples = outputMQ->availableToWrite(); + if (readSamples && writeSamples) { + auto processSamples = std::min(readSamples, writeSamples); + LOG(DEBUG) << __func__ << " available to read " << readSamples << " available to write " + << writeSamples << " process " << processSamples; + auto buffer = mContext->getWorkBuffer(); - inputMQ->read(buffer, readSize); - IEffect::Status status = effectProcessImpl(); - writeSize = std::min((int32_t)writeSize, status.fmqByteProduced); - outputMQ->write(buffer, writeSize); + inputMQ->read(buffer, processSamples); + + IEffect::Status status = effectProcessImpl(buffer, buffer, processSamples); + outputMQ->write(buffer, status.fmqProduced); statusMQ->writeBlocking(&status, 1); - LOG(DEBUG) << __func__ << " done processing, effect consumed " << status.fmqByteConsumed - << " produced " << status.fmqByteProduced; + LOG(DEBUG) << __func__ << " done processing, effect consumed " << status.fmqConsumed + << " produced " << status.fmqProduced; } else { // TODO: maybe add some sleep here to avoid busy waiting } } // must implement by each effect implementation - virtual IEffect::Status effectProcessImpl() = 0; + virtual IEffect::Status effectProcessImpl(float* in, float* out, int processSamples) = 0; private: // make sure the context only set once. diff --git a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h index 6195d8a25e..d50bd63d30 100644 --- a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h +++ b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h @@ -34,12 +34,14 @@ class Factory : public BnFactory { * * @param in_type Type UUID. * @param in_instance Instance UUID. + * @param in_proxy Proxy UUID. * @param out_descriptor List of identities . * @return ndk::ScopedAStatus */ ndk::ScopedAStatus queryEffects( const std::optional<::aidl::android::media::audio::common::AudioUuid>& in_type, const std::optional<::aidl::android::media::audio::common::AudioUuid>& in_instance, + const std::optional<::aidl::android::media::audio::common::AudioUuid>& in_proxy, std::vector* out_descriptor) override; /** @@ -79,16 +81,9 @@ class Factory : public BnFactory { // List of effect descriptors supported by the devices. std::vector mIdentityList; - typedef binder_exception_t (*EffectCreateFunctor)(std::shared_ptr*); - typedef binder_exception_t (*EffectDestroyFunctor)(const std::shared_ptr&); - struct effect_interface_s { - EffectCreateFunctor createEffectFunc; - EffectDestroyFunctor destroyEffectFunc; - }; - std::map> /* dlHandle */, - std::unique_ptr>> + std::unique_ptr>> mEffectLibMap; std::map, aidl::android::media::audio::common::AudioUuid, std::owner_less<>> @@ -96,5 +91,10 @@ class Factory : public BnFactory { ndk::ScopedAStatus destroyEffectImpl(const std::shared_ptr& in_handle); void cleanupEffectMap(); + void openEffectLibrary( + const ::aidl::android::media::audio::common::AudioUuid& type, + const ::aidl::android::media::audio::common::AudioUuid& impl, + const std::optional<::aidl::android::media::audio::common::AudioUuid>& proxy, + const std::string& libName); }; } // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/include/equalizer-impl/EqualizerSw.h b/audio/aidl/default/include/equalizer-impl/EqualizerSw.h index aa3a727040..dad03e1d37 100644 --- a/audio/aidl/default/include/equalizer-impl/EqualizerSw.h +++ b/audio/aidl/default/include/equalizer-impl/EqualizerSw.h @@ -21,85 +21,104 @@ #include #include -#include "effect-impl/EffectContext.h" -#include "effect-impl/EffectTypes.h" +#include "effect-impl/EffectImpl.h" #include "effect-impl/EffectUUID.h" -#include "effect-impl/EffectWorker.h" namespace aidl::android::hardware::audio::effect { class EqualizerSwContext : public EffectContext { public: - EqualizerSwContext(int statusDepth, int inBufferSize, int outBufferSize) - : EffectContext(statusDepth, inBufferSize, outBufferSize) { + EqualizerSwContext(int statusDepth, const Parameter::Common& common) + : EffectContext(statusDepth, common) { LOG(DEBUG) << __func__; } + RetCode setEqPreset(const int& presetIdx) { + if (presetIdx < 0 || presetIdx >= NUM_OF_PRESETS) { + return RetCode::ERROR_ILLEGAL_PARAMETER; + } + mPreset = presetIdx; + return RetCode::SUCCESS; + } + int getEqPreset() { return mPreset; } + + RetCode setEqBandLevels(const std::vector& bandLevels) { + if (bandLevels.size() > NUM_OF_BANDS) { + LOG(ERROR) << __func__ << " return because size exceed " << NUM_OF_BANDS; + return RetCode::ERROR_ILLEGAL_PARAMETER; + } + RetCode ret = RetCode::SUCCESS; + for (auto& it : bandLevels) { + if (it.index >= NUM_OF_BANDS || it.index < 0) { + LOG(ERROR) << __func__ << " index illegal, skip: " << it.index << " - " + << it.levelMb; + ret = RetCode::ERROR_ILLEGAL_PARAMETER; + } + mBandLevels[it.index] = it.levelMb; + } + return ret; + } + + std::vector getEqBandLevels() { + std::vector bandLevels; + for (int i = 0; i < NUM_OF_BANDS; i++) { + bandLevels.push_back({i, mBandLevels[i]}); + } + return bandLevels; + } + private: + static const int NUM_OF_BANDS = 5; + static const int NUM_OF_PRESETS = 10; + static const int PRESET_CUSTOM = -1; + // preset band level + int mPreset = PRESET_CUSTOM; + int32_t mBandLevels[NUM_OF_BANDS] = {3, 0, 0, 0, 3}; + // Add equalizer specific context for processing here }; -class EqualizerSw : public BnEffect, EffectWorker { +class EqualizerSw : public EffectImpl { public: - EqualizerSw() { - Equalizer::Capability eqCap = {.bandFrequencies = mBandFrequency, .presets = mPresets}; - mDesc.capability.set(eqCap); - LOG(DEBUG) << __func__; - }; + EqualizerSw() { LOG(DEBUG) << __func__; } ~EqualizerSw() { - cleanUp(); LOG(DEBUG) << __func__; - }; - ndk::ScopedAStatus open(const Parameter::Common& common, const Parameter::Specific& specific, - OpenEffectReturn* _aidl_return) override; - ndk::ScopedAStatus close() override; + releaseContext(); + } + ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override; - - ndk::ScopedAStatus getState(State* _aidl_return) override; - ndk::ScopedAStatus command(CommandId in_commandId) override; - ndk::ScopedAStatus setParameter(const Parameter& in_param) override; - ndk::ScopedAStatus getParameter(const Parameter::Id& in_paramId, - Parameter* _aidl_return) override; - - IEffect::Status effectProcessImpl() 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 createContext(const Parameter::Common& common) override; + RetCode releaseContext() override; private: - // Effect descriptor. - Descriptor mDesc = {.common = {.id = {.type = EqualizerTypeUUID, .uuid = EqualizerSwImplUUID}}}; - - // Parameters. - Parameter::Common mCommonParam; - Equalizer mEqualizerParam; // TODO: the equalizer parameter needs to update - - // Instance state INIT by default. - State mState = State::INIT; - - int mPreset = PRESET_CUSTOM; // the current preset + std::shared_ptr mContext; + /* capabilities */ const std::vector mBandFrequency = {{0, 30000, 120000}, {1, 120001, 460000}, {2, 460001, 1800000}, {3, 1800001, 7000000}, {4, 7000001, 20000000}}; - // preset band level - std::vector mBandLevels = {{0, 3}, {1, 0}, {2, 0}, {3, 0}, {4, 3}}; // presets supported by the device const std::vector mPresets = { {0, "Normal"}, {1, "Classical"}, {2, "Dance"}, {3, "Flat"}, {4, "Folk"}, {5, "Heavy Metal"}, {6, "Hip Hop"}, {7, "Jazz"}, {8, "Pop"}, {9, "Rock"}}; - static const int NUM_OF_BANDS = 5; - static const int NUM_OF_PRESETS = 10; - static const int PRESET_CUSTOM = -1; - // Equalizer worker context - std::shared_ptr mContext; + const Equalizer::Capability kEqCap = {.bandFrequencies = mBandFrequency, .presets = mPresets}; + // Effect descriptor. + const Descriptor kDesc = {.common = {.id = {.type = EqualizerTypeUUID, + .uuid = EqualizerSwImplUUID, + .proxy = std::nullopt}, + .flags = {.type = Flags::Type::INSERT, + .insert = Flags::Insert::FIRST, + .volume = Flags::Volume::CTRL}, + .name = "EqualizerSw"}, + .capability = Capability::make(kEqCap)}; - ndk::ScopedAStatus setCommonParameter(const Parameter::Common& common_param); - ndk::ScopedAStatus setSpecificParameter(const Parameter::Specific& specific); - ndk::ScopedAStatus getSpecificParameter(Parameter::Specific::Id id, - Parameter::Specific* specific); - - void cleanUp(); - - 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/audio/aidl/default/loudnessEnhancer/Android.bp b/audio/aidl/default/loudnessEnhancer/Android.bp new file mode 100644 index 0000000000..3a0ac73d03 --- /dev/null +++ b/audio/aidl/default/loudnessEnhancer/Android.bp @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library_shared { + name: "libloudnessenhancersw", + defaults: [ + "aidlaudioeffectservice_defaults", + "latest_android_media_audio_common_types_ndk_shared", + "latest_android_hardware_audio_effect_ndk_shared", + ], + srcs: [ + "LoudnessEnhancerSw.cpp", + ":effectCommonFile", + ], + visibility: [ + "//hardware/interfaces/audio/aidl/default", + ], +} diff --git a/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.cpp b/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.cpp new file mode 100644 index 0000000000..51645c761b --- /dev/null +++ b/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.cpp @@ -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. + */ + +#include +#define LOG_TAG "AHAL_LoudnessEnhancerSw" +#include +#include +#include + +#include +#include + +#include "LoudnessEnhancerSw.h" + +using aidl::android::hardware::audio::effect::IEffect; +using aidl::android::hardware::audio::effect::LoudnessEnhancerSw; +using aidl::android::hardware::audio::effect::LoudnessEnhancerSwImplUUID; +using aidl::android::hardware::audio::effect::State; +using aidl::android::media::audio::common::AudioUuid; + +extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid, + std::shared_ptr* instanceSpp) { + if (!in_impl_uuid || *in_impl_uuid != LoudnessEnhancerSwImplUUID) { + LOG(ERROR) << __func__ << "uuid not supported"; + return EX_ILLEGAL_ARGUMENT; + } + if (instanceSpp) { + *instanceSpp = ndk::SharedRefBase::make(); + 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& instanceSp) { + if (!instanceSp) { + return EX_NONE; + } + 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 { + +ndk::ScopedAStatus LoudnessEnhancerSw::getDescriptor(Descriptor* _aidl_return) { + LOG(DEBUG) << __func__ << kDescriptor.toString(); + *_aidl_return = kDescriptor; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus LoudnessEnhancerSw::setParameterSpecific(const Parameter::Specific& specific) { + RETURN_IF(Parameter::Specific::loudnessEnhancer != specific.getTag(), EX_ILLEGAL_ARGUMENT, + "EffectNotSupported"); + std::lock_guard lg(mMutex); + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); + + mSpecificParam = specific.get(); + LOG(DEBUG) << __func__ << " success with: " << specific.toString(); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus LoudnessEnhancerSw::getParameterSpecific(const Parameter::Id& id, + Parameter::Specific* specific) { + auto tag = id.getTag(); + RETURN_IF(Parameter::Id::loudnessEnhancerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag"); + specific->set(mSpecificParam); + return ndk::ScopedAStatus::ok(); +} + +std::shared_ptr LoudnessEnhancerSw::createContext(const Parameter::Common& common) { + if (mContext) { + LOG(DEBUG) << __func__ << " context already exist"; + return mContext; + } + mContext = std::make_shared(1 /* statusFmqDepth */, common); + return mContext; +} + +RetCode LoudnessEnhancerSw::releaseContext() { + if (mContext) { + mContext.reset(); + } + return RetCode::SUCCESS; +} + +// Processing method running in EffectWorker thread. +IEffect::Status LoudnessEnhancerSw::effectProcessImpl(float* in, float* out, int process) { + // TODO: get data buffer and process. + LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process; + for (int i = 0; i < process; i++) { + *out++ = *in++; + } + return {STATUS_OK, process, process}; +} + +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.h b/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.h new file mode 100644 index 0000000000..7d4bb527fb --- /dev/null +++ b/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.h @@ -0,0 +1,72 @@ +/* + * 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 +#include +#include +#include + +#include "effect-impl/EffectImpl.h" +#include "effect-impl/EffectUUID.h" + +namespace aidl::android::hardware::audio::effect { + +class LoudnessEnhancerSwContext : public EffectContext { + public: + LoudnessEnhancerSwContext(int statusDepth, const Parameter::Common& common) + : EffectContext(statusDepth, common) { + LOG(DEBUG) << __func__; + } + // TODO: add specific context here +}; + +class LoudnessEnhancerSw : public EffectImpl { + public: + LoudnessEnhancerSw() { LOG(DEBUG) << __func__; } + ~LoudnessEnhancerSw() { + LOG(DEBUG) << __func__; + releaseContext(); + } + + ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) 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 createContext(const Parameter::Common& common) override; + RetCode releaseContext() override; + + private: + std::shared_ptr mContext; + /* capabilities */ + const LoudnessEnhancer::Capability kCapability; + /* Effect descriptor */ + const Descriptor kDescriptor = { + .common = {.id = {.type = LoudnessEnhancerTypeUUID, + .uuid = LoudnessEnhancerSwImplUUID, + .proxy = std::nullopt}, + .flags = {.type = Flags::Type::INSERT, + .insert = Flags::Insert::FIRST, + .volume = Flags::Volume::CTRL}, + .name = "LoudnessEnhancerSw"}, + .capability = Capability::make(kCapability)}; + + /* parameters */ + LoudnessEnhancer mSpecificParam; +}; +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/reverb/Android.bp b/audio/aidl/default/reverb/Android.bp new file mode 100644 index 0000000000..955038cdb2 --- /dev/null +++ b/audio/aidl/default/reverb/Android.bp @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library_shared { + name: "libreverbsw", + defaults: [ + "aidlaudioeffectservice_defaults", + "latest_android_media_audio_common_types_ndk_shared", + "latest_android_hardware_audio_effect_ndk_shared", + ], + srcs: [ + "ReverbSw.cpp", + ":effectCommonFile", + ], + visibility: [ + "//hardware/interfaces/audio/aidl/default", + ], +} diff --git a/audio/aidl/default/reverb/ReverbSw.cpp b/audio/aidl/default/reverb/ReverbSw.cpp new file mode 100644 index 0000000000..639f1a2e76 --- /dev/null +++ b/audio/aidl/default/reverb/ReverbSw.cpp @@ -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. + */ + +#include +#define LOG_TAG "AHAL_ReverbSw" +#include +#include +#include + +#include +#include + +#include "ReverbSw.h" + +using aidl::android::hardware::audio::effect::IEffect; +using aidl::android::hardware::audio::effect::ReverbSw; +using aidl::android::hardware::audio::effect::ReverbSwImplUUID; +using aidl::android::hardware::audio::effect::State; +using aidl::android::media::audio::common::AudioUuid; + +extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid, + std::shared_ptr* instanceSpp) { + if (!in_impl_uuid || *in_impl_uuid != ReverbSwImplUUID) { + LOG(ERROR) << __func__ << "uuid not supported"; + return EX_ILLEGAL_ARGUMENT; + } + if (instanceSpp) { + *instanceSpp = ndk::SharedRefBase::make(); + 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& instanceSp) { + if (!instanceSp) { + return EX_NONE; + } + 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 { + +ndk::ScopedAStatus ReverbSw::getDescriptor(Descriptor* _aidl_return) { + LOG(DEBUG) << __func__ << kDescriptor.toString(); + *_aidl_return = kDescriptor; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus ReverbSw::setParameterSpecific(const Parameter::Specific& specific) { + RETURN_IF(Parameter::Specific::reverb != specific.getTag(), EX_ILLEGAL_ARGUMENT, + "EffectNotSupported"); + std::lock_guard lg(mMutex); + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); + + mSpecificParam = specific.get(); + LOG(DEBUG) << __func__ << " success with: " << specific.toString(); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus ReverbSw::getParameterSpecific(const Parameter::Id& id, + Parameter::Specific* specific) { + auto tag = id.getTag(); + RETURN_IF(Parameter::Id::reverbTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag"); + specific->set(mSpecificParam); + return ndk::ScopedAStatus::ok(); +} + +std::shared_ptr ReverbSw::createContext(const Parameter::Common& common) { + if (mContext) { + LOG(DEBUG) << __func__ << " context already exist"; + return mContext; + } + mContext = std::make_shared(1 /* statusFmqDepth */, common); + return mContext; +} + +RetCode ReverbSw::releaseContext() { + if (mContext) { + mContext.reset(); + } + return RetCode::SUCCESS; +} + +// Processing method running in EffectWorker thread. +IEffect::Status ReverbSw::effectProcessImpl(float* in, float* out, int process) { + // TODO: get data buffer and process. + LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process; + for (int i = 0; i < process; i++) { + *out++ = *in++; + } + return {STATUS_OK, process, process}; +} + +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/reverb/ReverbSw.h b/audio/aidl/default/reverb/ReverbSw.h new file mode 100644 index 0000000000..9457ab344d --- /dev/null +++ b/audio/aidl/default/reverb/ReverbSw.h @@ -0,0 +1,72 @@ +/* + * 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 +#include +#include +#include + +#include "effect-impl/EffectImpl.h" +#include "effect-impl/EffectUUID.h" + +namespace aidl::android::hardware::audio::effect { + +class ReverbSwContext : public EffectContext { + public: + ReverbSwContext(int statusDepth, const Parameter::Common& common) + : EffectContext(statusDepth, common) { + LOG(DEBUG) << __func__; + } + // TODO: add specific context here +}; + +class ReverbSw : public EffectImpl { + public: + ReverbSw() { LOG(DEBUG) << __func__; } + ~ReverbSw() { + LOG(DEBUG) << __func__; + releaseContext(); + } + + ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) 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 createContext(const Parameter::Common& common) override; + RetCode releaseContext() override; + + private: + std::shared_ptr mContext; + /* capabilities */ + const Reverb::Capability kCapability; + /* Effect descriptor */ + const Descriptor kDescriptor = { + .common = {.id = {.type = ReverbTypeUUID, + .uuid = ReverbSwImplUUID, + .proxy = std::nullopt}, + .flags = {.type = Flags::Type::INSERT, + .insert = Flags::Insert::FIRST, + .volume = Flags::Volume::CTRL}, + .name = "ReverbSw"}, + .capability = Capability::make(kCapability)}; + + /* parameters */ + Reverb mSpecificParam; +}; +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/virtualizer/Android.bp b/audio/aidl/default/virtualizer/Android.bp new file mode 100644 index 0000000000..ba38f5c1a8 --- /dev/null +++ b/audio/aidl/default/virtualizer/Android.bp @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library_shared { + name: "libvirtualizersw", + defaults: [ + "aidlaudioeffectservice_defaults", + "latest_android_media_audio_common_types_ndk_shared", + "latest_android_hardware_audio_effect_ndk_shared", + ], + srcs: [ + "VirtualizerSw.cpp", + ":effectCommonFile", + ], + visibility: [ + "//hardware/interfaces/audio/aidl/default", + ], +} diff --git a/audio/aidl/default/virtualizer/VirtualizerSw.cpp b/audio/aidl/default/virtualizer/VirtualizerSw.cpp new file mode 100644 index 0000000000..ccb7b4bd5b --- /dev/null +++ b/audio/aidl/default/virtualizer/VirtualizerSw.cpp @@ -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. + */ + +#include +#define LOG_TAG "AHAL_VirtualizerSw" +#include +#include +#include + +#include +#include + +#include "VirtualizerSw.h" + +using aidl::android::hardware::audio::effect::IEffect; +using aidl::android::hardware::audio::effect::State; +using aidl::android::hardware::audio::effect::VirtualizerSw; +using aidl::android::hardware::audio::effect::VirtualizerSwImplUUID; +using aidl::android::media::audio::common::AudioUuid; + +extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid, + std::shared_ptr* instanceSpp) { + if (!in_impl_uuid || *in_impl_uuid != VirtualizerSwImplUUID) { + LOG(ERROR) << __func__ << "uuid not supported"; + return EX_ILLEGAL_ARGUMENT; + } + if (instanceSpp) { + *instanceSpp = ndk::SharedRefBase::make(); + 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& instanceSp) { + if (!instanceSp) { + return EX_NONE; + } + 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 { + +ndk::ScopedAStatus VirtualizerSw::getDescriptor(Descriptor* _aidl_return) { + LOG(DEBUG) << __func__ << kDescriptor.toString(); + *_aidl_return = kDescriptor; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus VirtualizerSw::setParameterSpecific(const Parameter::Specific& specific) { + RETURN_IF(Parameter::Specific::virtualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT, + "EffectNotSupported"); + std::lock_guard lg(mMutex); + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); + + mSpecificParam = specific.get(); + LOG(DEBUG) << __func__ << " success with: " << specific.toString(); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus VirtualizerSw::getParameterSpecific(const Parameter::Id& id, + Parameter::Specific* specific) { + auto tag = id.getTag(); + RETURN_IF(Parameter::Id::virtualizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag"); + specific->set(mSpecificParam); + return ndk::ScopedAStatus::ok(); +} + +std::shared_ptr VirtualizerSw::createContext(const Parameter::Common& common) { + if (mContext) { + LOG(DEBUG) << __func__ << " context already exist"; + return mContext; + } + mContext = std::make_shared(1 /* statusFmqDepth */, common); + return mContext; +} + +RetCode VirtualizerSw::releaseContext() { + if (mContext) { + mContext.reset(); + } + return RetCode::SUCCESS; +} + +// Processing method running in EffectWorker thread. +IEffect::Status VirtualizerSw::effectProcessImpl(float* in, float* out, int process) { + // TODO: get data buffer and process. + LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process; + for (int i = 0; i < process; i++) { + *out++ = *in++; + } + return {STATUS_OK, process, process}; +} + +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/virtualizer/VirtualizerSw.h b/audio/aidl/default/virtualizer/VirtualizerSw.h new file mode 100644 index 0000000000..86f442d657 --- /dev/null +++ b/audio/aidl/default/virtualizer/VirtualizerSw.h @@ -0,0 +1,72 @@ +/* + * 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 +#include +#include +#include + +#include "effect-impl/EffectImpl.h" +#include "effect-impl/EffectUUID.h" + +namespace aidl::android::hardware::audio::effect { + +class VirtualizerSwContext : public EffectContext { + public: + VirtualizerSwContext(int statusDepth, const Parameter::Common& common) + : EffectContext(statusDepth, common) { + LOG(DEBUG) << __func__; + } + // TODO: add specific context here +}; + +class VirtualizerSw : public EffectImpl { + public: + VirtualizerSw() { LOG(DEBUG) << __func__; } + ~VirtualizerSw() { + LOG(DEBUG) << __func__; + releaseContext(); + } + + ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) 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 createContext(const Parameter::Common& common) override; + RetCode releaseContext() override; + + private: + std::shared_ptr mContext; + /* capabilities */ + const Virtualizer::Capability kCapability; + /* Effect descriptor */ + const Descriptor kDescriptor = { + .common = {.id = {.type = VirtualizerTypeUUID, + .uuid = VirtualizerSwImplUUID, + .proxy = std::nullopt}, + .flags = {.type = Flags::Type::INSERT, + .insert = Flags::Insert::FIRST, + .volume = Flags::Volume::CTRL}, + .name = "VirtualizerSw"}, + .capability = Capability::make(kCapability)}; + + /* parameters */ + Virtualizer mSpecificParam; +}; +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/visualizer/Android.bp b/audio/aidl/default/visualizer/Android.bp new file mode 100644 index 0000000000..5041be8344 --- /dev/null +++ b/audio/aidl/default/visualizer/Android.bp @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library_shared { + name: "libvisualizersw", + defaults: [ + "aidlaudioeffectservice_defaults", + "latest_android_media_audio_common_types_ndk_shared", + "latest_android_hardware_audio_effect_ndk_shared", + ], + srcs: [ + "VisualizerSw.cpp", + ":effectCommonFile", + ], + visibility: [ + "//hardware/interfaces/audio/aidl/default", + ], +} diff --git a/audio/aidl/default/visualizer/VisualizerSw.cpp b/audio/aidl/default/visualizer/VisualizerSw.cpp new file mode 100644 index 0000000000..5a24f18950 --- /dev/null +++ b/audio/aidl/default/visualizer/VisualizerSw.cpp @@ -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. + */ + +#include +#define LOG_TAG "AHAL_VisualizerSw" +#include +#include +#include + +#include +#include + +#include "VisualizerSw.h" + +using aidl::android::hardware::audio::effect::IEffect; +using aidl::android::hardware::audio::effect::State; +using aidl::android::hardware::audio::effect::VisualizerSw; +using aidl::android::hardware::audio::effect::VisualizerSwImplUUID; +using aidl::android::media::audio::common::AudioUuid; + +extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid, + std::shared_ptr* instanceSpp) { + if (!in_impl_uuid || *in_impl_uuid != VisualizerSwImplUUID) { + LOG(ERROR) << __func__ << "uuid not supported"; + return EX_ILLEGAL_ARGUMENT; + } + if (instanceSpp) { + *instanceSpp = ndk::SharedRefBase::make(); + 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& instanceSp) { + if (!instanceSp) { + return EX_NONE; + } + 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 { + +ndk::ScopedAStatus VisualizerSw::getDescriptor(Descriptor* _aidl_return) { + LOG(DEBUG) << __func__ << kDescriptor.toString(); + *_aidl_return = kDescriptor; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus VisualizerSw::setParameterSpecific(const Parameter::Specific& specific) { + RETURN_IF(Parameter::Specific::visualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT, + "EffectNotSupported"); + std::lock_guard lg(mMutex); + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); + + mSpecificParam = specific.get(); + LOG(DEBUG) << __func__ << " success with: " << specific.toString(); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus VisualizerSw::getParameterSpecific(const Parameter::Id& id, + Parameter::Specific* specific) { + auto tag = id.getTag(); + RETURN_IF(Parameter::Id::visualizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag"); + specific->set(mSpecificParam); + return ndk::ScopedAStatus::ok(); +} + +std::shared_ptr VisualizerSw::createContext(const Parameter::Common& common) { + if (mContext) { + LOG(DEBUG) << __func__ << " context already exist"; + return mContext; + } + mContext = std::make_shared(1 /* statusFmqDepth */, common); + return mContext; +} + +RetCode VisualizerSw::releaseContext() { + if (mContext) { + mContext.reset(); + } + return RetCode::SUCCESS; +} + +// Processing method running in EffectWorker thread. +IEffect::Status VisualizerSw::effectProcessImpl(float* in, float* out, int process) { + // TODO: get data buffer and process. + LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process; + for (int i = 0; i < process; i++) { + *out++ = *in++; + } + return {STATUS_OK, process, process}; +} + +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/visualizer/VisualizerSw.h b/audio/aidl/default/visualizer/VisualizerSw.h new file mode 100644 index 0000000000..e9baece2c6 --- /dev/null +++ b/audio/aidl/default/visualizer/VisualizerSw.h @@ -0,0 +1,72 @@ +/* + * 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 +#include +#include +#include + +#include "effect-impl/EffectImpl.h" +#include "effect-impl/EffectUUID.h" + +namespace aidl::android::hardware::audio::effect { + +class VisualizerSwContext : public EffectContext { + public: + VisualizerSwContext(int statusDepth, const Parameter::Common& common) + : EffectContext(statusDepth, common) { + LOG(DEBUG) << __func__; + } + // TODO: add specific context here +}; + +class VisualizerSw : public EffectImpl { + public: + VisualizerSw() { LOG(DEBUG) << __func__; } + ~VisualizerSw() { + LOG(DEBUG) << __func__; + releaseContext(); + } + + ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) 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 createContext(const Parameter::Common& common) override; + RetCode releaseContext() override; + + private: + std::shared_ptr mContext; + /* capabilities */ + const Visualizer::Capability kCapability; + /* Effect descriptor */ + const Descriptor kDescriptor = { + .common = {.id = {.type = VisualizerTypeUUID, + .uuid = VisualizerSwImplUUID, + .proxy = std::nullopt}, + .flags = {.type = Flags::Type::INSERT, + .insert = Flags::Insert::FIRST, + .volume = Flags::Volume::CTRL}, + .name = "VisualizerSw"}, + .capability = Capability::make(kCapability)}; + + /* parameters */ + Visualizer mSpecificParam; +}; +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/volume/Android.bp b/audio/aidl/default/volume/Android.bp new file mode 100644 index 0000000000..505ee67c34 --- /dev/null +++ b/audio/aidl/default/volume/Android.bp @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library_shared { + name: "libvolumesw", + defaults: [ + "aidlaudioeffectservice_defaults", + "latest_android_media_audio_common_types_ndk_shared", + "latest_android_hardware_audio_effect_ndk_shared", + ], + srcs: [ + "VolumeSw.cpp", + ":effectCommonFile", + ], + visibility: [ + "//hardware/interfaces/audio/aidl/default", + ], +} diff --git a/audio/aidl/default/volume/VolumeSw.cpp b/audio/aidl/default/volume/VolumeSw.cpp new file mode 100644 index 0000000000..e2f42d7413 --- /dev/null +++ b/audio/aidl/default/volume/VolumeSw.cpp @@ -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. + */ + +#include +#define LOG_TAG "AHAL_VolumeSw" +#include +#include +#include + +#include +#include + +#include "VolumeSw.h" + +using aidl::android::hardware::audio::effect::IEffect; +using aidl::android::hardware::audio::effect::State; +using aidl::android::hardware::audio::effect::VolumeSw; +using aidl::android::hardware::audio::effect::VolumeSwImplUUID; +using aidl::android::media::audio::common::AudioUuid; + +extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid, + std::shared_ptr* instanceSpp) { + if (!in_impl_uuid || *in_impl_uuid != VolumeSwImplUUID) { + LOG(ERROR) << __func__ << "uuid not supported"; + return EX_ILLEGAL_ARGUMENT; + } + if (instanceSpp) { + *instanceSpp = ndk::SharedRefBase::make(); + 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& instanceSp) { + if (!instanceSp) { + return EX_NONE; + } + 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 { + +ndk::ScopedAStatus VolumeSw::getDescriptor(Descriptor* _aidl_return) { + LOG(DEBUG) << __func__ << kDescriptor.toString(); + *_aidl_return = kDescriptor; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus VolumeSw::setParameterSpecific(const Parameter::Specific& specific) { + RETURN_IF(Parameter::Specific::volume != specific.getTag(), EX_ILLEGAL_ARGUMENT, + "EffectNotSupported"); + std::lock_guard lg(mMutex); + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); + + mSpecificParam = specific.get(); + LOG(DEBUG) << __func__ << " success with: " << specific.toString(); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus VolumeSw::getParameterSpecific(const Parameter::Id& id, + Parameter::Specific* specific) { + auto tag = id.getTag(); + RETURN_IF(Parameter::Id::volumeTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag"); + specific->set(mSpecificParam); + return ndk::ScopedAStatus::ok(); +} + +std::shared_ptr VolumeSw::createContext(const Parameter::Common& common) { + if (mContext) { + LOG(DEBUG) << __func__ << " context already exist"; + return mContext; + } + mContext = std::make_shared(1 /* statusFmqDepth */, common); + return mContext; +} + +RetCode VolumeSw::releaseContext() { + if (mContext) { + mContext.reset(); + } + return RetCode::SUCCESS; +} + +// Processing method running in EffectWorker thread. +IEffect::Status VolumeSw::effectProcessImpl(float* in, float* out, int process) { + // TODO: get data buffer and process. + LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process; + for (int i = 0; i < process; i++) { + *out++ = *in++; + } + return {STATUS_OK, process, process}; +} + +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/volume/VolumeSw.h b/audio/aidl/default/volume/VolumeSw.h new file mode 100644 index 0000000000..b0d2aa7306 --- /dev/null +++ b/audio/aidl/default/volume/VolumeSw.h @@ -0,0 +1,72 @@ +/* + * 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 +#include +#include +#include + +#include "effect-impl/EffectImpl.h" +#include "effect-impl/EffectUUID.h" + +namespace aidl::android::hardware::audio::effect { + +class VolumeSwContext : public EffectContext { + public: + VolumeSwContext(int statusDepth, const Parameter::Common& common) + : EffectContext(statusDepth, common) { + LOG(DEBUG) << __func__; + } + // TODO: add specific context here +}; + +class VolumeSw : public EffectImpl { + public: + VolumeSw() { LOG(DEBUG) << __func__; } + ~VolumeSw() { + LOG(DEBUG) << __func__; + releaseContext(); + } + + ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) 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 createContext(const Parameter::Common& common) override; + RetCode releaseContext() override; + + private: + std::shared_ptr mContext; + /* capabilities */ + const Volume::Capability kCapability; + /* Effect descriptor */ + const Descriptor kDescriptor = { + .common = {.id = {.type = VolumeTypeUUID, + .uuid = VolumeSwImplUUID, + .proxy = std::nullopt}, + .flags = {.type = Flags::Type::INSERT, + .insert = Flags::Insert::FIRST, + .volume = Flags::Volume::CTRL}, + .name = "VolumeSw"}, + .capability = Capability::make(kCapability)}; + + /* parameters */ + Volume mSpecificParam; +}; +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/vts/EffectFactoryHelper.h b/audio/aidl/vts/EffectFactoryHelper.h index 63efae0646..d58fcf259b 100644 --- a/audio/aidl/vts/EffectFactoryHelper.h +++ b/audio/aidl/vts/EffectFactoryHelper.h @@ -53,9 +53,10 @@ class EffectFactoryHelper { void QueryEffects(const std::optional& in_type, const std::optional& in_instance, + const std::optional& in_proxy, std::vector* _aidl_return) { ASSERT_NE(mEffectFactory, nullptr); - EXPECT_IS_OK(mEffectFactory->queryEffects(in_type, in_instance, _aidl_return)); + EXPECT_IS_OK(mEffectFactory->queryEffects(in_type, in_instance, in_proxy, _aidl_return)); mIds = *_aidl_return; } @@ -85,9 +86,10 @@ class EffectFactoryHelper { ASSERT_NE(mEffectFactory, nullptr); if (type == EffectNullUuid) { - EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, &ids)); + EXPECT_IS_OK( + mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids)); } else { - EXPECT_IS_OK(mEffectFactory->queryEffects(type, std::nullopt, &ids)); + EXPECT_IS_OK(mEffectFactory->queryEffects(type, std::nullopt, std::nullopt, &ids)); } for (const auto& id : ids) { ASSERT_EQ(id.type, type); @@ -121,7 +123,8 @@ class EffectFactoryHelper { void QueryAndCreateAllEffects() { ASSERT_NE(mEffectFactory, nullptr); - EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, &mCompleteIds)); + EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, + &mCompleteIds)); for (const auto& id : mCompleteIds) { std::shared_ptr effect; EXPECT_IS_OK(mEffectFactory->createEffect(id.uuid, &effect)); diff --git a/audio/aidl/vts/EffectHelper.h b/audio/aidl/vts/EffectHelper.h index e4edd10083..623ac3749d 100644 --- a/audio/aidl/vts/EffectHelper.h +++ b/audio/aidl/vts/EffectHelper.h @@ -49,7 +49,7 @@ using aidl::android::media::audio::common::AudioUuid; using aidl::android::media::audio::common::PcmType; const AudioFormatDescription DefaultFormat = { - .type = AudioFormatType::PCM, .pcm = PcmType::INT_16_BIT, .encoding = ""}; + .type = AudioFormatType::PCM, .pcm = PcmType::FLOAT_32_BIT, .encoding = ""}; class EffectHelper { public: @@ -59,6 +59,7 @@ class EffectHelper { void OpenEffects(const AudioUuid& type = EffectNullUuid) { auto open = [&](const std::shared_ptr& effect) { + ASSERT_NE(effect, nullptr); IEffect::OpenEffectReturn ret; EXPECT_IS_OK(effect->open(mCommon, mSpecific, &ret)); EffectParam params; @@ -72,6 +73,7 @@ class EffectHelper { void CloseEffects(const binder_status_t status = EX_NONE) { auto close = [&](const std::shared_ptr& effect) { + ASSERT_NE(effect, nullptr); EXPECT_STATUS(status, effect->close()); }; @@ -97,6 +99,7 @@ class EffectHelper { void GetEffectDescriptors() { auto get = [&](const std::shared_ptr& effect) { + ASSERT_NE(effect, nullptr); Descriptor desc; EXPECT_IS_OK(effect->getDescriptor(&desc)); mEffectDescriptors.push_back(std::move(desc)); @@ -106,6 +109,7 @@ class EffectHelper { void CommandEffects(CommandId command) { auto close = [&](const std::shared_ptr& effect) { + ASSERT_NE(effect, nullptr); EXPECT_IS_OK(effect->command(command)); }; EXPECT_NO_FATAL_FAILURE(ForEachEffect(close)); @@ -113,6 +117,7 @@ class EffectHelper { void CommandEffectsExpectStatus(CommandId command, const binder_status_t status) { auto func = [&](const std::shared_ptr& effect) { + ASSERT_NE(effect, nullptr); EXPECT_STATUS(status, effect->command(command)); }; EXPECT_NO_FATAL_FAILURE(ForEachEffect(func)); @@ -120,6 +125,7 @@ class EffectHelper { void ExpectState(State expected) { auto get = [&](const std::shared_ptr& effect) { + ASSERT_NE(effect, nullptr); State state = State::INIT; EXPECT_IS_OK(effect->getState(&state)); EXPECT_EQ(expected, state); @@ -129,6 +135,7 @@ class EffectHelper { void SetParameter() { auto func = [&](const std::shared_ptr& effect) { + ASSERT_NE(effect, nullptr); Parameter param; param.set(mCommon); EXPECT_IS_OK(effect->setParameter(param)); @@ -138,9 +145,10 @@ class EffectHelper { void VerifyParameters() { auto func = [&](const std::shared_ptr& effect) { + ASSERT_NE(effect, nullptr); Parameter paramCommonGet = Parameter(), paramCommonExpect = Parameter(); Parameter::Id id; - id.set(0); + id.set(Parameter::common); paramCommonExpect.set(mCommon); EXPECT_IS_OK(effect->getParameter(id, ¶mCommonGet)); EXPECT_EQ(paramCommonExpect, paramCommonGet) @@ -151,8 +159,9 @@ class EffectHelper { void QueryEffects(const std::optional& in_type, const std::optional& in_instance, + const std::optional& in_proxy, std::vector* _aidl_return) { - mFactoryHelper.QueryEffects(in_type, in_instance, _aidl_return); + mFactoryHelper.QueryEffects(in_type, in_instance, in_proxy, _aidl_return); } template @@ -173,7 +182,7 @@ class EffectHelper { } } - static const size_t mWriteMQSize = 0x400; + static const size_t mWriteMQBytes = 0x400; enum class IO : char { INPUT = 0, OUTPUT = 1, INOUT = 2 }; @@ -204,7 +213,7 @@ class EffectHelper { mCommon.output.frameCount = frameCount; } } - void initParamCommon(int session = -1, int ioHandle = -1, int iSampleRate = 48000, + void initParamCommon(int session = 0, int ioHandle = -1, int iSampleRate = 48000, int oSampleRate = 48000, long iFrameCount = 0x100, long oFrameCount = 0x100) { mCommon.session = session; @@ -215,10 +224,12 @@ class EffectHelper { input.base.sampleRate = iSampleRate; input.base.channelMask = mInputChannelLayout; input.frameCount = iFrameCount; + input.base.format = DefaultFormat; output.base.sampleRate = oSampleRate; output.base.channelMask = mOutputChannelLayout; output.base.format = DefaultFormat; output.frameCount = oFrameCount; + output.base.format = DefaultFormat; inputFrameSize = android::hardware::audio::common::getFrameSizeInBytes( input.base.format, input.base.channelMask); outputFrameSize = android::hardware::audio::common::getFrameSizeInBytes( @@ -228,45 +239,45 @@ class EffectHelper { void setSpecific(Parameter::Specific& specific) { mSpecific = specific; } // usually this function only call once. - void PrepareInputData(size_t s = mWriteMQSize) { - size_t maxInputSize = s; + void PrepareInputData(size_t bytes = mWriteMQBytes) { + size_t maxInputBytes = mWriteMQBytes; for (auto& it : mEffectParams) { auto& mq = it.inputMQ; EXPECT_NE(nullptr, mq); EXPECT_TRUE(mq->isValid()); - const size_t bytesToWrite = mq->availableToWrite(); + const size_t bytesToWrite = mq->availableToWrite() * sizeof(float); EXPECT_EQ(inputFrameSize * mCommon.input.frameCount, bytesToWrite); EXPECT_NE(0UL, bytesToWrite); - EXPECT_TRUE(s <= bytesToWrite); - maxInputSize = std::max(maxInputSize, bytesToWrite); + EXPECT_TRUE(bytes <= bytesToWrite); + maxInputBytes = std::max(maxInputBytes, bytesToWrite); } - mInputBuffer.resize(maxInputSize); + mInputBuffer.resize(maxInputBytes / sizeof(float)); std::fill(mInputBuffer.begin(), mInputBuffer.end(), 0x5a); } - void writeToFmq(size_t s = mWriteMQSize) { + void writeToFmq(size_t bytes = mWriteMQBytes) { for (auto& it : mEffectParams) { auto& mq = it.inputMQ; EXPECT_NE(nullptr, mq); - const size_t bytesToWrite = mq->availableToWrite(); + const size_t bytesToWrite = mq->availableToWrite() * sizeof(float); EXPECT_NE(0Ul, bytesToWrite); - EXPECT_TRUE(s <= bytesToWrite); - EXPECT_TRUE(mq->write(mInputBuffer.data(), s)); + EXPECT_TRUE(bytes <= bytesToWrite); + EXPECT_TRUE(mq->write(mInputBuffer.data(), bytes / sizeof(float))); } } - void readFromFmq(size_t expectSize = mWriteMQSize) { + void readFromFmq(size_t expectBytes = mWriteMQBytes) { for (auto& it : mEffectParams) { IEffect::Status status{}; auto& statusMq = it.statusMQ; EXPECT_NE(nullptr, statusMq); EXPECT_TRUE(statusMq->readBlocking(&status, 1)); EXPECT_EQ(STATUS_OK, status.status); - EXPECT_EQ(expectSize, (unsigned)status.fmqByteProduced); + EXPECT_EQ(expectBytes, (unsigned)status.fmqProduced * sizeof(float)); auto& outputMq = it.outputMQ; EXPECT_NE(nullptr, outputMq); - EXPECT_EQ(expectSize, outputMq->availableToRead()); + EXPECT_EQ(expectBytes, outputMq->availableToRead() * sizeof(float)); } } @@ -288,16 +299,16 @@ class EffectHelper { AudioChannelLayout::LAYOUT_STEREO); Parameter::Common mCommon; - Parameter::Specific mSpecific; + std::optional mSpecific = std::nullopt; size_t inputFrameSize, outputFrameSize; - std::vector mInputBuffer; // reuse same buffer for all effects testing + std::vector mInputBuffer; // reuse same buffer for all effects testing typedef ::android::AidlMessageQueue< IEffect::Status, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> StatusMQ; typedef ::android::AidlMessageQueue< - int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> + float, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> DataMQ; class EffectParam { diff --git a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp index da8ca37e0c..d30dff47aa 100644 --- a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp +++ b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp @@ -66,13 +66,13 @@ TEST_P(EffectFactoryTest, CanBeRestarted) { TEST_P(EffectFactoryTest, QueriedDescriptorList) { std::vector descriptors; - mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors); + mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors); EXPECT_NE(descriptors.size(), 0UL); } TEST_P(EffectFactoryTest, DescriptorUUIDNotNull) { std::vector descriptors; - mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors); + mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors); // TODO: Factory eventually need to return the full list of MUST supported AOSP effects. for (auto& desc : descriptors) { EXPECT_NE(desc.type, EffectNullUuid); @@ -82,19 +82,19 @@ TEST_P(EffectFactoryTest, DescriptorUUIDNotNull) { TEST_P(EffectFactoryTest, QueriedDescriptorNotExistType) { std::vector descriptors; - mFactory.QueryEffects(EffectNullUuid, std::nullopt, &descriptors); + mFactory.QueryEffects(EffectNullUuid, std::nullopt, std::nullopt, &descriptors); EXPECT_EQ(descriptors.size(), 0UL); } TEST_P(EffectFactoryTest, QueriedDescriptorNotExistInstance) { std::vector descriptors; - mFactory.QueryEffects(std::nullopt, EffectNullUuid, &descriptors); + mFactory.QueryEffects(std::nullopt, EffectNullUuid, std::nullopt, &descriptors); EXPECT_EQ(descriptors.size(), 0UL); } TEST_P(EffectFactoryTest, CreateAndDestroyOnce) { std::vector descriptors; - mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors); + mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors); auto numIds = mFactory.GetEffectIds().size(); EXPECT_NE(numIds, 0UL); @@ -108,7 +108,7 @@ TEST_P(EffectFactoryTest, CreateAndDestroyOnce) { TEST_P(EffectFactoryTest, CreateAndDestroyRepeat) { std::vector descriptors; - mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors); + mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors); auto numIds = mFactory.GetEffectIds().size(); EXPECT_NE(numIds, 0UL); @@ -128,7 +128,7 @@ TEST_P(EffectFactoryTest, CreateAndDestroyRepeat) { TEST_P(EffectFactoryTest, CreateMultipleInstanceOfSameEffect) { std::vector descriptors; - mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors); + mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors); auto numIds = mFactory.GetEffectIds().size(); EXPECT_NE(numIds, 0UL); @@ -167,7 +167,7 @@ TEST_P(EffectFactoryTest, DestroyWithInvalidInterface) { TEST_P(EffectFactoryTest, CreateAndRemoveReference) { std::vector descriptors; - mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors); + mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors); auto numIds = mFactory.GetEffectIds().size(); EXPECT_NE(numIds, 0UL); @@ -182,7 +182,7 @@ TEST_P(EffectFactoryTest, CreateAndRemoveReference) { TEST_P(EffectFactoryTest, CreateRemoveReferenceAndCreateDestroy) { std::vector descriptors; - mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors); + mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors); auto numIds = mFactory.GetEffectIds().size(); EXPECT_NE(numIds, 0UL); @@ -203,7 +203,7 @@ TEST_P(EffectFactoryTest, CreateRemoveReferenceAndCreateDestroy) { TEST_P(EffectFactoryTest, CreateRestartAndCreateDestroy) { std::vector descriptors; - mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors); + mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors); auto numIds = mFactory.GetEffectIds().size(); auto& effectMap = mFactory.GetEffectMap(); mFactory.CreateEffects(); diff --git a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp index 7ed1f01dfb..3ea67bc96b 100644 --- a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp +++ b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp @@ -59,7 +59,6 @@ class AudioEffectTest : public testing::TestWithParam, public Effec CreateEffects(); initParamCommonFormat(); initParamCommon(); - // initParamSpecific(); } void TearDown() override { @@ -105,8 +104,9 @@ TEST_P(AudioEffectTest, DescriptorIdExistAndUnique) { Descriptor desc; std::vector idList; EXPECT_IS_OK(effect->getDescriptor(&desc)); - QueryEffects(desc.common.id.type, desc.common.id.uuid, &idList); - EXPECT_EQ(idList.size(), 1UL); + QueryEffects(desc.common.id.type, desc.common.id.uuid, desc.common.id.proxy, &idList); + // Must have at least one instance. + EXPECT_NE(idList.size(), 0UL); }; ForEachEffect(checker); @@ -117,7 +117,7 @@ TEST_P(AudioEffectTest, DescriptorIdExistAndUnique) { auto vec = GetCompleteEffectIdList(); std::unordered_set idSet(0, stringHash); for (auto it : vec) { - EXPECT_EQ(idSet.count(it), 0UL); + EXPECT_EQ(idSet.count(it), 0UL) << it.toString(); idSet.insert(it); } } @@ -256,7 +256,8 @@ TEST_P(AudioEffectTest, DestroyOpenEffects) { // open effects, destroy without close, expect to get EX_ILLEGAL_STATE status. CreateEffects(); OpenEffects(); - DestroyEffects(EX_ILLEGAL_STATE, 1); + auto vec = GetCompleteEffectIdList(); + DestroyEffects(EX_ILLEGAL_STATE, vec.size()); CloseEffects(); } @@ -310,9 +311,11 @@ TEST_P(AudioEffectTest, ResetAndVerifyParameter) { CloseEffects(); } +// TODO: need a way to support setting different sessionId to different effect instances +#if 0 // Multiple instances of same implementation running. -TEST_P(AudioEffectTest, MultipleInstancesRunning) { - CreateEffects(3); +TEST_P(AudioEffectTest, MultipleInstancesRunningWithDiffSessionId) { + CreateEffects(); ExpectState(State::INIT); OpenEffects(); ExpectState(State::IDLE); @@ -327,15 +330,16 @@ TEST_P(AudioEffectTest, MultipleInstancesRunning) { VerifyParameters(); CloseEffects(); } +#endif // Send data to effects and expect it to consume by check statusMQ. TEST_P(AudioEffectTest, ExpectEffectsToConsumeDataInMQ) { OpenEffects(); - PrepareInputData(mWriteMQSize); + PrepareInputData(mWriteMQBytes); CommandEffects(CommandId::START); - writeToFmq(mWriteMQSize); - readFromFmq(mWriteMQSize); + writeToFmq(mWriteMQBytes); + readFromFmq(mWriteMQBytes); ExpectState(State::PROCESSING); CommandEffects(CommandId::STOP); diff --git a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp index 1ac71f1e85..4162551ba4 100644 --- a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp +++ b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp @@ -95,9 +95,9 @@ class EqualizerParamTest : public ::testing::TestWithParam& effect) { @@ -122,19 +122,54 @@ class EqualizerParamTest : public ::testing::TestWithParam(tag); + Parameter::Id id; + Equalizer::Id eqId; + eqId.set(tag); + id.set(eqId); // if set success, then get should match EXPECT_STATUS(expected, effect->getParameter(id, &getParam)); - EXPECT_EQ(expectParam, getParam) << "\n" - << expectParam.toString() << "\n" - << getParam.toString(); + EXPECT_TRUE(isEqParameterExpected(expectParam, getParam)); } } }; EXPECT_NO_FATAL_FAILURE(ForEachEffect(functor)); } + bool isEqParameterExpected(const Parameter& expect, const Parameter& target) { + // if parameter same, then for sure matched + if (expect == target) return true; + + // if not, see if target include the expect parameter, and others all default (0). + /* + This is verify the case of client setParameter to a single bandLevel ({3, -1} for + example), and return of getParameter must be [{0, 0}, {1, 0}, {2, 0}, {3, -1}, {4, 0}] + */ + EXPECT_EQ(expect.getTag(), Parameter::specific); + EXPECT_EQ(target.getTag(), Parameter::specific); + + Parameter::Specific expectSpec = expect.get(), + targetSpec = target.get(); + EXPECT_EQ(expectSpec.getTag(), Parameter::Specific::equalizer); + EXPECT_EQ(targetSpec.getTag(), Parameter::Specific::equalizer); + + Equalizer expectEq = expectSpec.get(), + targetEq = targetSpec.get(); + EXPECT_EQ(expectEq.getTag(), targetEq.getTag()); + + auto eqTag = targetEq.getTag(); + switch (eqTag) { + case Equalizer::bandLevels: { + auto expectBl = expectEq.get(); + auto targetBl = targetEq.get(); + return std::includes(targetBl.begin(), targetBl.end(), expectBl.begin(), + expectBl.end()); + } + default: + return false; + } + return false; + } + void addPresetParam(int preset) { Equalizer eq; eq.set(preset); @@ -189,7 +224,6 @@ class EqualizerParamTest : public ::testing::TestWithParam>> mTags; bool validCapabilityTag(Capability& cap) { return cap.getTag() == Capability::equalizer; } @@ -211,8 +245,8 @@ TEST_P(EqualizerParamTest, SetAndGetPreset) { } TEST_P(EqualizerParamTest, SetAndGetSingleBand) { - Equalizer::BandLevel bandLevel = {mParamBandIndex, mParamBandLevel}; std::vector bandLevels; + Equalizer::BandLevel bandLevel = {mParamBandIndex, mParamBandLevel}; bandLevels.push_back(bandLevel); EXPECT_NO_FATAL_FAILURE(addBandLevelsParam(bandLevels)); SetAndGetEqualizerParameters();