From 0b58d826f6eaae43e77fc04f2f78e73ee00e057c Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Tue, 20 Dec 2022 15:45:38 +0000 Subject: [PATCH 1/3] Effect AIDL: Add AEC, AGC and NS AIDL interface definition Bug: 238913361 Test: atest VtsHalAECTargetTest Test: atest VtsHalAGCTargetTest Test: atest VtsHalNSTargetTest Change-Id: I31aad9571623cec48b8cf921e1c778d33b015530 --- audio/aidl/Android.bp | 3 + .../audio/effect/AcousticEchoCanceler.aidl | 51 +++++++++++ .../audio/effect/AutomaticGainControl.aidl | 57 ++++++++++++ .../hardware/audio/effect/Capability.aidl | 3 + .../audio/effect/NoiseSuppression.aidl | 54 +++++++++++ .../hardware/audio/effect/Parameter.aidl | 6 ++ .../hardware/audio/effect/Processing.aidl | 2 +- .../audio/effect/AcousticEchoCanceler.aidl | 77 ++++++++++++++++ .../audio/effect/AutomaticGainControl.aidl | 90 +++++++++++++++++++ .../hardware/audio/effect/Capability.aidl | 6 ++ .../audio/effect/NoiseSuppression.aidl | 71 +++++++++++++++ .../hardware/audio/effect/Parameter.aidl | 9 ++ .../hardware/audio/effect/Processing.aidl | 4 +- 13 files changed, 430 insertions(+), 3 deletions(-) create mode 100644 audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/AcousticEchoCanceler.aidl create mode 100644 audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/AutomaticGainControl.aidl create mode 100644 audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/NoiseSuppression.aidl create mode 100644 audio/aidl/android/hardware/audio/effect/AcousticEchoCanceler.aidl create mode 100644 audio/aidl/android/hardware/audio/effect/AutomaticGainControl.aidl create mode 100644 audio/aidl/android/hardware/audio/effect/NoiseSuppression.aidl diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp index 7d474b24c9..42a4ac17f6 100644 --- a/audio/aidl/Android.bp +++ b/audio/aidl/Android.bp @@ -223,6 +223,8 @@ aidl_interface { "android.hardware.audio_defaults", ], srcs: [ + "android/hardware/audio/effect/AcousticEchoCanceler.aidl", + "android/hardware/audio/effect/AutomaticGainControl.aidl", "android/hardware/audio/effect/BassBoost.aidl", "android/hardware/audio/effect/Capability.aidl", "android/hardware/audio/effect/CommandId.aidl", @@ -236,6 +238,7 @@ aidl_interface { "android/hardware/audio/effect/IEffect.aidl", "android/hardware/audio/effect/IFactory.aidl", "android/hardware/audio/effect/LoudnessEnhancer.aidl", + "android/hardware/audio/effect/NoiseSuppression.aidl", "android/hardware/audio/effect/Parameter.aidl", "android/hardware/audio/effect/PresetReverb.aidl", "android/hardware/audio/effect/Processing.aidl", diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/AcousticEchoCanceler.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/AcousticEchoCanceler.aidl new file mode 100644 index 0000000000..1d51ade554 --- /dev/null +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/AcousticEchoCanceler.aidl @@ -0,0 +1,51 @@ +/* + * 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 AcousticEchoCanceler { + android.hardware.audio.effect.VendorExtension vendor; + int echoDelayUs; + boolean mobileMode; + @VintfStability + union Id { + int vendorExtensionTag; + android.hardware.audio.effect.AcousticEchoCanceler.Tag commonTag; + } + @VintfStability + parcelable Capability { + ParcelableHolder extension; + int maxEchoDelayUs; + boolean supportMobileMode; + } +} diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/AutomaticGainControl.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/AutomaticGainControl.aidl new file mode 100644 index 0000000000..39068d5105 --- /dev/null +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/AutomaticGainControl.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 AutomaticGainControl { + android.hardware.audio.effect.VendorExtension vendor; + int fixedDigitalGainMb; + android.hardware.audio.effect.AutomaticGainControl.LevelEstimator levelEstimator; + int saturationMarginMb; + @VintfStability + union Id { + int vendorExtensionTag; + android.hardware.audio.effect.AutomaticGainControl.Tag commonTag; + } + @VintfStability + parcelable Capability { + ParcelableHolder extension; + int maxFixedDigitalGainMb; + int maxSaturationMarginMb; + } + @Backing(type="int") @VintfStability + enum LevelEstimator { + RMS = 0, + PEAK = 1, + } +} 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 60c88d36a4..28f77b377d 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 @@ -35,6 +35,8 @@ package android.hardware.audio.effect; @VintfStability union Capability { android.hardware.audio.effect.VendorExtension vendorExtension; + android.hardware.audio.effect.AcousticEchoCanceler.Capability acousticEchoCanceler; + android.hardware.audio.effect.AutomaticGainControl.Capability automaticGainControl; android.hardware.audio.effect.BassBoost.Capability bassBoost; android.hardware.audio.effect.Downmix.Capability downmix; android.hardware.audio.effect.DynamicsProcessing.Capability dynamicsProcessing; @@ -42,6 +44,7 @@ union Capability { android.hardware.audio.effect.Equalizer.Capability equalizer; android.hardware.audio.effect.HapticGenerator.Capability hapticGenerator; android.hardware.audio.effect.LoudnessEnhancer.Capability loudnessEnhancer; + android.hardware.audio.effect.NoiseSuppression.Capability noiseSuppression; android.hardware.audio.effect.PresetReverb.Capability presetReverb; android.hardware.audio.effect.Virtualizer.Capability virtualizer; android.hardware.audio.effect.Visualizer.Capability visualizer; diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/NoiseSuppression.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/NoiseSuppression.aidl new file mode 100644 index 0000000000..223d95a7b5 --- /dev/null +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/NoiseSuppression.aidl @@ -0,0 +1,54 @@ +/* + * 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 NoiseSuppression { + android.hardware.audio.effect.VendorExtension vendor; + android.hardware.audio.effect.NoiseSuppression.Level level; + @VintfStability + union Id { + int vendorExtensionTag; + android.hardware.audio.effect.NoiseSuppression.Tag commonTag; + } + @VintfStability + parcelable Capability { + ParcelableHolder extension; + } + @Backing(type="int") @VintfStability + enum Level { + LOW = 0, + MEDIUM = 1, + HIGH = 2, + } +} 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 0635c138c2..eaa4bb1795 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 @@ -43,6 +43,8 @@ union Parameter { @VintfStability union Id { int vendorEffectTag; + android.hardware.audio.effect.AcousticEchoCanceler.Id acousticEchoCancelerTag; + android.hardware.audio.effect.AutomaticGainControl.Id automaticGainControlTag; android.hardware.audio.effect.BassBoost.Id bassBoostTag; android.hardware.audio.effect.Downmix.Id downmixTag; android.hardware.audio.effect.DynamicsProcessing.Id dynamicsProcessingTag; @@ -50,6 +52,7 @@ union Parameter { 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.NoiseSuppression.Id noiseSuppressionTag; android.hardware.audio.effect.PresetReverb.Id presetReverbTag; android.hardware.audio.effect.Virtualizer.Id virtualizerTag; android.hardware.audio.effect.Visualizer.Id visualizerTag; @@ -71,6 +74,8 @@ union Parameter { @VintfStability union Specific { android.hardware.audio.effect.VendorExtension vendorEffect; + android.hardware.audio.effect.AcousticEchoCanceler acousticEchoCanceler; + android.hardware.audio.effect.AutomaticGainControl automaticGainControl; android.hardware.audio.effect.BassBoost bassBoost; android.hardware.audio.effect.Downmix downmix; android.hardware.audio.effect.DynamicsProcessing dynamicsProcessing; @@ -78,6 +83,7 @@ union Parameter { android.hardware.audio.effect.Equalizer equalizer; android.hardware.audio.effect.HapticGenerator hapticGenerator; android.hardware.audio.effect.LoudnessEnhancer loudnessEnhancer; + android.hardware.audio.effect.NoiseSuppression noiseSuppression; android.hardware.audio.effect.PresetReverb presetReverb; android.hardware.audio.effect.Virtualizer virtualizer; android.hardware.audio.effect.Visualizer visualizer; diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Processing.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Processing.aidl index a779ae4c84..f6d6ee25bf 100644 --- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Processing.aidl +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Processing.aidl @@ -35,7 +35,7 @@ package android.hardware.audio.effect; @VintfStability parcelable Processing { android.hardware.audio.effect.Processing.Type type; - android.hardware.audio.effect.Descriptor.Identity[] ids; + android.hardware.audio.effect.Descriptor[] ids; @VintfStability union Type { android.media.audio.common.AudioStreamType streamType = android.media.audio.common.AudioStreamType.INVALID; diff --git a/audio/aidl/android/hardware/audio/effect/AcousticEchoCanceler.aidl b/audio/aidl/android/hardware/audio/effect/AcousticEchoCanceler.aidl new file mode 100644 index 0000000000..19d60b664f --- /dev/null +++ b/audio/aidl/android/hardware/audio/effect/AcousticEchoCanceler.aidl @@ -0,0 +1,77 @@ +/* + * 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; + +/** + * Acoustic Echo Canceler (AEC) is an audio pre-processor which removes the contribution of the + * signal received from the remote party from the captured audio signal. + * + * All parameters defined in union AcousticEchoCanceler must be gettable and settable. The + * capabilities defined in AcousticEchoCanceler.Capability can only acquired with + * IEffect.getDescriptor() and not settable. + */ +@VintfStability +union AcousticEchoCanceler { + /** + * Effect parameter tag to identify the parameters for getParameter(). + */ + @VintfStability + union Id { + int vendorExtensionTag; + AcousticEchoCanceler.Tag commonTag; + } + + /** + * Vendor AEC implementation definition for additional parameters. + */ + VendorExtension vendor; + + /** + * Capability supported by AEC implementation. + */ + @VintfStability + parcelable Capability { + /** + * AEC capability extension, vendor can use this extension in case existing capability + * definition not enough. + */ + ParcelableHolder extension; + + /** + * Maximum AEC echo delay in microseconds supported. + */ + int maxEchoDelayUs; + /** + * If AEC mobile mode was supported by the AEC implementation. + */ + boolean supportMobileMode; + } + + /** + * The AEC echo delay in microseconds. + * Must never be negative, and not larger than maxEchoDelayUs in capability. + */ + int echoDelayUs; + /** + * If AEC mobile mode enabled. + * Can only be false if AEC implementation indicate not support mobile mode by set + * supportMobileMode to false in capability. + */ + boolean mobileMode; +} diff --git a/audio/aidl/android/hardware/audio/effect/AutomaticGainControl.aidl b/audio/aidl/android/hardware/audio/effect/AutomaticGainControl.aidl new file mode 100644 index 0000000000..e82a564582 --- /dev/null +++ b/audio/aidl/android/hardware/audio/effect/AutomaticGainControl.aidl @@ -0,0 +1,90 @@ +/* + * 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; + +/** + * Automatic Gain Control (AGC) is an audio pre-processor which automatically normalizes the output + * of the captured signal by boosting or lowering input from the microphone to match a preset level + * so that the output signal level is virtually constant. AGC can be used by applications where the + * input signal dynamic range is not important but where a constant strong capture level is desired. + * + * All parameters defined in union AutomaticGainControl must be gettable and settable. The + * capabilities defined in AutomaticGainControl.Capability can only acquired with + * IEffect.getDescriptor() and not settable. + */ +@VintfStability +union AutomaticGainControl { + /** + * Effect parameter tag to identify the parameters for getParameter(). + */ + @VintfStability + union Id { + int vendorExtensionTag; + AutomaticGainControl.Tag commonTag; + } + + /** + * Vendor AutomaticGainControl implementation definition for additional parameters. + */ + VendorExtension vendor; + + /** + * Capability supported by AutomaticGainControl implementation. + */ + @VintfStability + parcelable Capability { + /** + * AutomaticGainControl capability extension, vendor can use this extension in case existing + * capability definition not enough. + */ + ParcelableHolder extension; + /** + * Max fixed digital gain supported by AGC implementation in millibel. + */ + int maxFixedDigitalGainMb; + /** + * Max fixed saturation margin supported by AGC implementation in millibel. + */ + int maxSaturationMarginMb; + } + + @VintfStability + @Backing(type="int") + enum LevelEstimator { + /* Use Root Mean Square level estimator*/ + RMS = 0, + /* Use Peak level estimator*/ + PEAK = 1, + } + + /** + * The AGC fixed digital gain in millibel. + * Must never be negative, and not larger than maxFixedDigitalGainMb in capability. + */ + int fixedDigitalGainMb; + /* + * Adaptive digital level estimator. + */ + LevelEstimator levelEstimator; + /** + * The AGC saturation margin in millibel. + * Must never be negative, and not larger than maxSaturationMarginMb in capability. + */ + int saturationMarginMb; +} diff --git a/audio/aidl/android/hardware/audio/effect/Capability.aidl b/audio/aidl/android/hardware/audio/effect/Capability.aidl index 414978325f..30780e6edf 100644 --- a/audio/aidl/android/hardware/audio/effect/Capability.aidl +++ b/audio/aidl/android/hardware/audio/effect/Capability.aidl @@ -16,6 +16,8 @@ package android.hardware.audio.effect; +import android.hardware.audio.effect.AcousticEchoCanceler; +import android.hardware.audio.effect.AutomaticGainControl; import android.hardware.audio.effect.BassBoost; import android.hardware.audio.effect.Downmix; import android.hardware.audio.effect.DynamicsProcessing; @@ -23,6 +25,7 @@ import android.hardware.audio.effect.EnvironmentalReverb; import android.hardware.audio.effect.Equalizer; import android.hardware.audio.effect.HapticGenerator; import android.hardware.audio.effect.LoudnessEnhancer; +import android.hardware.audio.effect.NoiseSuppression; import android.hardware.audio.effect.PresetReverb; import android.hardware.audio.effect.VendorExtension; import android.hardware.audio.effect.Virtualizer; @@ -49,6 +52,8 @@ union Capability { /** * Effect capabilities. */ + AcousticEchoCanceler.Capability acousticEchoCanceler; + AutomaticGainControl.Capability automaticGainControl; BassBoost.Capability bassBoost; Downmix.Capability downmix; DynamicsProcessing.Capability dynamicsProcessing; @@ -56,6 +61,7 @@ union Capability { Equalizer.Capability equalizer; HapticGenerator.Capability hapticGenerator; LoudnessEnhancer.Capability loudnessEnhancer; + NoiseSuppression.Capability noiseSuppression; PresetReverb.Capability presetReverb; Virtualizer.Capability virtualizer; Visualizer.Capability visualizer; diff --git a/audio/aidl/android/hardware/audio/effect/NoiseSuppression.aidl b/audio/aidl/android/hardware/audio/effect/NoiseSuppression.aidl new file mode 100644 index 0000000000..946fa87bb0 --- /dev/null +++ b/audio/aidl/android/hardware/audio/effect/NoiseSuppression.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; + +/** + * Noise suppression (NS) is an audio pre-processor which removes background noise from the captured + * signal. The component of the signal considered as noise can be either stationary (car/airplane + * engine, AC system) or non-stationary (other peoples conversations, car horn) for more advanced + * implementations. + * + * All parameters defined in union NoiseSuppression must be gettable and settable. The capabilities + * defined in NoiseSuppression.Capability can only acquired with IEffect.getDescriptor() and not + * settable. + */ +@VintfStability +union NoiseSuppression { + /** + * Effect parameter tag to identify the parameters for getParameter(). + */ + @VintfStability + union Id { + int vendorExtensionTag; + NoiseSuppression.Tag commonTag; + } + + /** + * Vendor NoiseSuppression implementation definition for additional parameters. + */ + VendorExtension vendor; + + /** + * Capability supported by NoiseSuppression implementation. + */ + @VintfStability + parcelable Capability { + /** + * NoiseSuppression capability extension, vendor can use this extension in case existing + * capability definition not enough. + */ + ParcelableHolder extension; + } + + /** + * Different level of Noise Suppression to set. + * As an example, webrtc have NsConfig::SuppressionLevel::k6dB applied for LOW level noise + * suppression, NsConfig::SuppressionLevel::k12dB for MEDIUM, and + * NsConfig::SuppressionLevel::k18dB for HIGH. + */ + @VintfStability @Backing(type="int") enum Level { LOW, MEDIUM, HIGH } + + /** + * The NS level. + */ + Level level; +} diff --git a/audio/aidl/android/hardware/audio/effect/Parameter.aidl b/audio/aidl/android/hardware/audio/effect/Parameter.aidl index d7a6a27d85..1c001d21d9 100644 --- a/audio/aidl/android/hardware/audio/effect/Parameter.aidl +++ b/audio/aidl/android/hardware/audio/effect/Parameter.aidl @@ -16,6 +16,8 @@ package android.hardware.audio.effect; +import android.hardware.audio.effect.AcousticEchoCanceler; +import android.hardware.audio.effect.AutomaticGainControl; import android.hardware.audio.effect.BassBoost; import android.hardware.audio.effect.Downmix; import android.hardware.audio.effect.DynamicsProcessing; @@ -23,6 +25,7 @@ import android.hardware.audio.effect.EnvironmentalReverb; import android.hardware.audio.effect.Equalizer; import android.hardware.audio.effect.HapticGenerator; import android.hardware.audio.effect.LoudnessEnhancer; +import android.hardware.audio.effect.NoiseSuppression; import android.hardware.audio.effect.PresetReverb; import android.hardware.audio.effect.VendorExtension; import android.hardware.audio.effect.Virtualizer; @@ -71,6 +74,8 @@ union Parameter { * effectInstance.getParameter(id, ¶m); * */ + AcousticEchoCanceler.Id acousticEchoCancelerTag; + AutomaticGainControl.Id automaticGainControlTag; BassBoost.Id bassBoostTag; Downmix.Id downmixTag; DynamicsProcessing.Id dynamicsProcessingTag; @@ -78,6 +83,7 @@ union Parameter { Equalizer.Id equalizerTag; HapticGenerator.Id hapticGeneratorTag; LoudnessEnhancer.Id loudnessEnhancerTag; + NoiseSuppression.Id noiseSuppressionTag; PresetReverb.Id presetReverbTag; Virtualizer.Id virtualizerTag; Visualizer.Id visualizerTag; @@ -149,6 +155,8 @@ union Parameter { @VintfStability union Specific { VendorExtension vendorEffect; + AcousticEchoCanceler acousticEchoCanceler; + AutomaticGainControl automaticGainControl; BassBoost bassBoost; Downmix downmix; DynamicsProcessing dynamicsProcessing; @@ -156,6 +164,7 @@ union Parameter { Equalizer equalizer; HapticGenerator hapticGenerator; LoudnessEnhancer loudnessEnhancer; + NoiseSuppression noiseSuppression; PresetReverb presetReverb; Virtualizer virtualizer; Visualizer visualizer; diff --git a/audio/aidl/android/hardware/audio/effect/Processing.aidl b/audio/aidl/android/hardware/audio/effect/Processing.aidl index ef32e8c904..cb773501fe 100644 --- a/audio/aidl/android/hardware/audio/effect/Processing.aidl +++ b/audio/aidl/android/hardware/audio/effect/Processing.aidl @@ -38,7 +38,7 @@ parcelable Processing { */ Type type; /** - * List of effect identities for this processing. + * List of effect descriptors for this processing. */ - Descriptor.Identity[] ids; + Descriptor[] ids; } From bd862b828796552bd53141f9c1c755f225adbcf4 Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Tue, 20 Dec 2022 00:11:41 +0000 Subject: [PATCH 2/3] Effect AIDL: Add AEC, AGC and NS AIDL and placeholder implmentation Bug: 238913361 Test: atest VtsHalAECTargetTest Test: atest VtsHalAGCTargetTest Test: atest VtsHalNSTargetTest Change-Id: I13de3fb554a3161d993fbe69942019546c7a96a6 --- .../AcousticEchoCancelerSw.cpp | 194 +++++++++++++++ .../AcousticEchoCancelerSw.h | 72 ++++++ .../default/acousticEchoCanceler/Android.bp | 40 +++ audio/aidl/default/audio_effects_config.xml | 6 + .../default/automaticGainControl/Android.bp | 40 +++ .../AutomaticGainControlSw.cpp | 234 ++++++++++++++++++ .../AutomaticGainControlSw.h | 78 ++++++ .../default/include/effect-impl/EffectUUID.h | 39 +++ .../aidl/default/noiseSuppression/Android.bp | 40 +++ .../noiseSuppression/NoiseSuppressionSw.cpp | 180 ++++++++++++++ .../noiseSuppression/NoiseSuppressionSw.h | 72 ++++++ 11 files changed, 995 insertions(+) create mode 100644 audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.cpp create mode 100644 audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.h create mode 100644 audio/aidl/default/acousticEchoCanceler/Android.bp create mode 100644 audio/aidl/default/automaticGainControl/Android.bp create mode 100644 audio/aidl/default/automaticGainControl/AutomaticGainControlSw.cpp create mode 100644 audio/aidl/default/automaticGainControl/AutomaticGainControlSw.h create mode 100644 audio/aidl/default/noiseSuppression/Android.bp create mode 100644 audio/aidl/default/noiseSuppression/NoiseSuppressionSw.cpp create mode 100644 audio/aidl/default/noiseSuppression/NoiseSuppressionSw.h diff --git a/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.cpp b/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.cpp new file mode 100644 index 0000000000..7f06013ee6 --- /dev/null +++ b/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.cpp @@ -0,0 +1,194 @@ +/* + * 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 +#include +#include +#define LOG_TAG "AHAL_AcousticEchoCancelerSw" +#include +#include + +#include +#include + +#include "AcousticEchoCancelerSw.h" + +using aidl::android::hardware::audio::effect::AcousticEchoCancelerSw; +using aidl::android::hardware::audio::effect::Descriptor; +using aidl::android::hardware::audio::effect::IEffect; +using aidl::android::hardware::audio::effect::kAcousticEchoCancelerSwImplUUID; +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 != kAcousticEchoCancelerSwImplUUID) { + 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 queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) { + if (!in_impl_uuid || *in_impl_uuid != kAcousticEchoCancelerSwImplUUID) { + LOG(ERROR) << __func__ << "uuid not supported"; + return EX_ILLEGAL_ARGUMENT; + } + *_aidl_return = AcousticEchoCancelerSw::kDescriptor; + LOG(ERROR) << __func__ << "xxx " << _aidl_return->toString(); + return EX_NONE; +} + +namespace aidl::android::hardware::audio::effect { + +const std::string AcousticEchoCancelerSw::kEffectName = "AcousticEchoCancelerSw"; +const AcousticEchoCanceler::Capability AcousticEchoCancelerSw::kCapability = { + .maxEchoDelayUs = 500, .supportMobileMode = false}; +const Descriptor AcousticEchoCancelerSw::kDescriptor = { + .common = {.id = {.type = kAcousticEchoCancelerTypeUUID, + .uuid = kAcousticEchoCancelerSwImplUUID, + .proxy = std::nullopt}, + .flags = {.type = Flags::Type::INSERT, + .insert = Flags::Insert::FIRST, + .volume = Flags::Volume::CTRL}, + .name = AcousticEchoCancelerSw::kEffectName, + .implementor = "The Android Open Source Project"}, + .capability = Capability::make( + AcousticEchoCancelerSw::kCapability)}; + +ndk::ScopedAStatus AcousticEchoCancelerSw::getDescriptor(Descriptor* _aidl_return) { + LOG(DEBUG) << __func__ << kDescriptor.toString(); + *_aidl_return = kDescriptor; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus AcousticEchoCancelerSw::setParameterSpecific( + const Parameter::Specific& specific) { + RETURN_IF(Parameter::Specific::acousticEchoCanceler != specific.getTag(), EX_ILLEGAL_ARGUMENT, + "EffectNotSupported"); + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); + + auto& param = specific.get(); + auto tag = param.getTag(); + + switch (tag) { + case AcousticEchoCanceler::echoDelayUs: { + RETURN_IF(mContext->setEchoDelay(param.get()) != + RetCode::SUCCESS, + EX_ILLEGAL_ARGUMENT, "echoDelayNotSupported"); + return ndk::ScopedAStatus::ok(); + } + case AcousticEchoCanceler::mobileMode: { + RETURN_IF(true == param.get(), EX_ILLEGAL_ARGUMENT, + "SettingmobileModeSupported"); + return ndk::ScopedAStatus::ok(); + } + default: { + LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); + return ndk::ScopedAStatus::fromExceptionCodeWithMessage( + EX_ILLEGAL_ARGUMENT, "AcousticEchoCancelerTagNotSupported"); + } + } +} + +ndk::ScopedAStatus AcousticEchoCancelerSw::getParameterSpecific(const Parameter::Id& id, + Parameter::Specific* specific) { + auto tag = id.getTag(); + RETURN_IF(Parameter::Id::acousticEchoCancelerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag"); + auto specificId = id.get(); + auto specificIdTag = specificId.getTag(); + switch (specificIdTag) { + case AcousticEchoCanceler::Id::commonTag: + return getParameterAcousticEchoCanceler( + specificId.get(), specific); + default: + LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); + return ndk::ScopedAStatus::fromExceptionCodeWithMessage( + EX_ILLEGAL_ARGUMENT, "AcousticEchoCancelerTagNotSupported"); + } +} + +ndk::ScopedAStatus AcousticEchoCancelerSw::getParameterAcousticEchoCanceler( + const AcousticEchoCanceler::Tag& tag, Parameter::Specific* specific) { + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); + AcousticEchoCanceler param; + switch (tag) { + case AcousticEchoCanceler::echoDelayUs: { + param.set(mContext->getEchoDelay()); + break; + } + case AcousticEchoCanceler::mobileMode: { + param.set(false); + break; + } + default: { + LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); + return ndk::ScopedAStatus::fromExceptionCodeWithMessage( + EX_ILLEGAL_ARGUMENT, "AcousticEchoCancelerTagNotSupported"); + } + } + + specific->set(param); + return ndk::ScopedAStatus::ok(); +} + +std::shared_ptr AcousticEchoCancelerSw::createContext( + const Parameter::Common& common) { + if (mContext) { + LOG(DEBUG) << __func__ << " context already exist"; + } else { + mContext = std::make_shared(1 /* statusFmqDepth */, common); + } + return mContext; +} + +std::shared_ptr AcousticEchoCancelerSw::getContext() { + return mContext; +} + +RetCode AcousticEchoCancelerSw::releaseContext() { + if (mContext) { + mContext.reset(); + } + return RetCode::SUCCESS; +} + +// Processing method running in EffectWorker thread. +IEffect::Status AcousticEchoCancelerSw::effectProcessImpl(float* in, float* out, int samples) { + // TODO: get data buffer and process. + LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples; + for (int i = 0; i < samples; i++) { + *out++ = *in++; + } + return {STATUS_OK, samples, samples}; +} + +RetCode AcousticEchoCancelerSwContext::setEchoDelay(int echoDelayUs) { + if (echoDelayUs < 0 || echoDelayUs > AcousticEchoCancelerSw::kCapability.maxEchoDelayUs) { + LOG(DEBUG) << __func__ << " illegal delay " << echoDelayUs; + return RetCode::ERROR_ILLEGAL_PARAMETER; + } + mEchoDelayUs = echoDelayUs; + return RetCode::SUCCESS; +} + +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.h b/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.h new file mode 100644 index 0000000000..809812a9cc --- /dev/null +++ b/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.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 AcousticEchoCancelerSwContext final : public EffectContext { + public: + AcousticEchoCancelerSwContext(int statusDepth, const Parameter::Common& common) + : EffectContext(statusDepth, common) { + LOG(DEBUG) << __func__; + } + + RetCode setEchoDelay(int echoDelayUs); + int getEchoDelay() const { return mEchoDelayUs; } + + private: + int mEchoDelayUs; +}; + +class AcousticEchoCancelerSw final : public EffectImpl { + public: + static const std::string kEffectName; + static const bool kStrengthSupported; + static const AcousticEchoCanceler::Capability kCapability; + static const Descriptor kDescriptor; + AcousticEchoCancelerSw() { LOG(DEBUG) << __func__; } + ~AcousticEchoCancelerSw() { + cleanUp(); + LOG(DEBUG) << __func__; + } + + 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; + + std::shared_ptr createContext(const Parameter::Common& common) override; + std::shared_ptr getContext() override; + RetCode releaseContext() override; + + std::string getEffectName() override { return kEffectName; }; + IEffect::Status effectProcessImpl(float* in, float* out, int samples) override; + + private: + std::shared_ptr mContext; + ndk::ScopedAStatus getParameterAcousticEchoCanceler(const AcousticEchoCanceler::Tag& tag, + Parameter::Specific* specific); +}; +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/acousticEchoCanceler/Android.bp b/audio/aidl/default/acousticEchoCanceler/Android.bp new file mode 100644 index 0000000000..b2e268237e --- /dev/null +++ b/audio/aidl/default/acousticEchoCanceler/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: "libaecsw", + defaults: [ + "aidlaudioeffectservice_defaults", + "latest_android_media_audio_common_types_ndk_shared", + "latest_android_hardware_audio_effect_ndk_shared", + ], + srcs: [ + "AcousticEchoCancelerSw.cpp", + ":effectCommonFile", + ], + visibility: [ + "//hardware/interfaces/audio/aidl/default", + ], +} diff --git a/audio/aidl/default/audio_effects_config.xml b/audio/aidl/default/audio_effects_config.xml index 9491bc3898..28a765631b 100644 --- a/audio/aidl/default/audio_effects_config.xml +++ b/audio/aidl/default/audio_effects_config.xml @@ -28,6 +28,8 @@ name of a library .so file on the target device. --> + + @@ -35,6 +37,7 @@ + @@ -62,6 +65,8 @@ --> + + @@ -71,6 +76,7 @@ + diff --git a/audio/aidl/default/automaticGainControl/Android.bp b/audio/aidl/default/automaticGainControl/Android.bp new file mode 100644 index 0000000000..4899b39289 --- /dev/null +++ b/audio/aidl/default/automaticGainControl/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: "libagcsw", + defaults: [ + "aidlaudioeffectservice_defaults", + "latest_android_media_audio_common_types_ndk_shared", + "latest_android_hardware_audio_effect_ndk_shared", + ], + srcs: [ + "AutomaticGainControlSw.cpp", + ":effectCommonFile", + ], + visibility: [ + "//hardware/interfaces/audio/aidl/default", + ], +} diff --git a/audio/aidl/default/automaticGainControl/AutomaticGainControlSw.cpp b/audio/aidl/default/automaticGainControl/AutomaticGainControlSw.cpp new file mode 100644 index 0000000000..8c706ef125 --- /dev/null +++ b/audio/aidl/default/automaticGainControl/AutomaticGainControlSw.cpp @@ -0,0 +1,234 @@ +/* + * 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 +#include +#include +#define LOG_TAG "AHAL_AutomaticGainControlSw" +#include +#include + +#include +#include + +#include "AutomaticGainControlSw.h" + +using aidl::android::hardware::audio::effect::AutomaticGainControlSw; +using aidl::android::hardware::audio::effect::Descriptor; +using aidl::android::hardware::audio::effect::IEffect; +using aidl::android::hardware::audio::effect::kAutomaticGainControlSwImplUUID; +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 != kAutomaticGainControlSwImplUUID) { + 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 queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) { + if (!in_impl_uuid || *in_impl_uuid != kAutomaticGainControlSwImplUUID) { + LOG(ERROR) << __func__ << "uuid not supported"; + return EX_ILLEGAL_ARGUMENT; + } + *_aidl_return = AutomaticGainControlSw::kDescriptor; + return EX_NONE; +} + +namespace aidl::android::hardware::audio::effect { + +const std::string AutomaticGainControlSw::kEffectName = "AutomaticGainControlSw"; +const AutomaticGainControl::Capability AutomaticGainControlSw::kCapability = { + .maxFixedDigitalGainMb = 50000, .maxSaturationMarginMb = 10000}; +const Descriptor AutomaticGainControlSw::kDescriptor = { + .common = {.id = {.type = kAutomaticGainControlTypeUUID, + .uuid = kAutomaticGainControlSwImplUUID, + .proxy = std::nullopt}, + .flags = {.type = Flags::Type::INSERT, + .insert = Flags::Insert::FIRST, + .volume = Flags::Volume::CTRL}, + .name = AutomaticGainControlSw::kEffectName, + .implementor = "The Android Open Source Project"}, + .capability = Capability::make( + AutomaticGainControlSw::kCapability)}; + +ndk::ScopedAStatus AutomaticGainControlSw::getDescriptor(Descriptor* _aidl_return) { + LOG(DEBUG) << __func__ << kDescriptor.toString(); + *_aidl_return = kDescriptor; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus AutomaticGainControlSw::setParameterSpecific( + const Parameter::Specific& specific) { + RETURN_IF(Parameter::Specific::automaticGainControl != specific.getTag(), EX_ILLEGAL_ARGUMENT, + "EffectNotSupported"); + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); + + auto& param = specific.get(); + auto tag = param.getTag(); + + switch (tag) { + case AutomaticGainControl::fixedDigitalGainMb: { + RETURN_IF(mContext->setDigitalGain( + param.get()) != + RetCode::SUCCESS, + EX_ILLEGAL_ARGUMENT, "digitalGainNotSupported"); + return ndk::ScopedAStatus::ok(); + } + case AutomaticGainControl::levelEstimator: { + RETURN_IF( + mContext->setLevelEstimator( + param.get()) != RetCode::SUCCESS, + EX_ILLEGAL_ARGUMENT, "levelEstimatorNotSupported"); + return ndk::ScopedAStatus::ok(); + } + case AutomaticGainControl::saturationMarginMb: { + RETURN_IF(mContext->setSaturationMargin( + param.get()) != + RetCode::SUCCESS, + EX_ILLEGAL_ARGUMENT, "saturationMarginNotSupported"); + return ndk::ScopedAStatus::ok(); + } + default: { + LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); + return ndk::ScopedAStatus::fromExceptionCodeWithMessage( + EX_ILLEGAL_ARGUMENT, "AutomaticGainControlTagNotSupported"); + } + } +} + +ndk::ScopedAStatus AutomaticGainControlSw::getParameterSpecific(const Parameter::Id& id, + Parameter::Specific* specific) { + auto tag = id.getTag(); + RETURN_IF(Parameter::Id::automaticGainControlTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag"); + auto specificId = id.get(); + auto specificIdTag = specificId.getTag(); + switch (specificIdTag) { + case AutomaticGainControl::Id::commonTag: + return getParameterAutomaticGainControl( + specificId.get(), specific); + default: + LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); + return ndk::ScopedAStatus::fromExceptionCodeWithMessage( + EX_ILLEGAL_ARGUMENT, "AutomaticGainControlTagNotSupported"); + } +} + +ndk::ScopedAStatus AutomaticGainControlSw::getParameterAutomaticGainControl( + const AutomaticGainControl::Tag& tag, Parameter::Specific* specific) { + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); + AutomaticGainControl param; + switch (tag) { + case AutomaticGainControl::fixedDigitalGainMb: { + param.set(mContext->getDigitalGain()); + break; + } + case AutomaticGainControl::levelEstimator: { + param.set(mContext->getLevelEstimator()); + break; + } + case AutomaticGainControl::saturationMarginMb: { + param.set(mContext->getSaturationMargin()); + break; + } + default: { + LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); + return ndk::ScopedAStatus::fromExceptionCodeWithMessage( + EX_ILLEGAL_ARGUMENT, "AutomaticGainControlTagNotSupported"); + } + } + + specific->set(param); + return ndk::ScopedAStatus::ok(); +} + +std::shared_ptr AutomaticGainControlSw::createContext( + const Parameter::Common& common) { + if (mContext) { + LOG(DEBUG) << __func__ << " context already exist"; + } else { + mContext = std::make_shared(1 /* statusFmqDepth */, common); + } + return mContext; +} + +std::shared_ptr AutomaticGainControlSw::getContext() { + return mContext; +} + +RetCode AutomaticGainControlSw::releaseContext() { + if (mContext) { + mContext.reset(); + } + return RetCode::SUCCESS; +} + +// Processing method running in EffectWorker thread. +IEffect::Status AutomaticGainControlSw::effectProcessImpl(float* in, float* out, int samples) { + // TODO: get data buffer and process. + LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples; + for (int i = 0; i < samples; i++) { + *out++ = *in++; + } + return {STATUS_OK, samples, samples}; +} + +RetCode AutomaticGainControlSwContext::setDigitalGain(int gain) { + if (gain < 0 || gain > AutomaticGainControlSw::kCapability.maxFixedDigitalGainMb) { + LOG(DEBUG) << __func__ << " illegal digital gain " << gain; + return RetCode::ERROR_ILLEGAL_PARAMETER; + } + mDigitalGain = gain; + return RetCode::SUCCESS; +} + +int AutomaticGainControlSwContext::getDigitalGain() { + return mDigitalGain; +} + +RetCode AutomaticGainControlSwContext::setLevelEstimator( + AutomaticGainControl::LevelEstimator levelEstimator) { + mLevelEstimator = levelEstimator; + return RetCode::SUCCESS; +} + +AutomaticGainControl::LevelEstimator AutomaticGainControlSwContext::getLevelEstimator() { + return mLevelEstimator; +} + +RetCode AutomaticGainControlSwContext::setSaturationMargin(int margin) { + if (margin < 0 || margin > AutomaticGainControlSw::kCapability.maxSaturationMarginMb) { + LOG(DEBUG) << __func__ << " illegal saturationMargin " << margin; + return RetCode::ERROR_ILLEGAL_PARAMETER; + } + mSaturationMargin = margin; + return RetCode::SUCCESS; +} + +int AutomaticGainControlSwContext::getSaturationMargin() { + return mSaturationMargin; +} + +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/automaticGainControl/AutomaticGainControlSw.h b/audio/aidl/default/automaticGainControl/AutomaticGainControlSw.h new file mode 100644 index 0000000000..e23fec0cc7 --- /dev/null +++ b/audio/aidl/default/automaticGainControl/AutomaticGainControlSw.h @@ -0,0 +1,78 @@ +/* + * 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 AutomaticGainControlSwContext final : public EffectContext { + public: + AutomaticGainControlSwContext(int statusDepth, const Parameter::Common& common) + : EffectContext(statusDepth, common) { + LOG(DEBUG) << __func__; + } + + RetCode setDigitalGain(int gain); + int getDigitalGain(); + RetCode setLevelEstimator(AutomaticGainControl::LevelEstimator levelEstimator); + AutomaticGainControl::LevelEstimator getLevelEstimator(); + RetCode setSaturationMargin(int margin); + int getSaturationMargin(); + + private: + int mDigitalGain; + AutomaticGainControl::LevelEstimator mLevelEstimator; + int mSaturationMargin; +}; + +class AutomaticGainControlSw final : public EffectImpl { + public: + static const std::string kEffectName; + static const bool kStrengthSupported; + static const AutomaticGainControl::Capability kCapability; + static const Descriptor kDescriptor; + AutomaticGainControlSw() { LOG(DEBUG) << __func__; } + ~AutomaticGainControlSw() { + cleanUp(); + LOG(DEBUG) << __func__; + } + + 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; + + std::shared_ptr createContext(const Parameter::Common& common) override; + std::shared_ptr getContext() override; + RetCode releaseContext() override; + + std::string getEffectName() override { return kEffectName; }; + IEffect::Status effectProcessImpl(float* in, float* out, int samples) override; + + private: + std::shared_ptr mContext; + ndk::ScopedAStatus getParameterAutomaticGainControl(const AutomaticGainControl::Tag& tag, + Parameter::Specific* specific); +}; +} // 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 c9bb1f446c..34472b3043 100644 --- a/audio/aidl/default/include/effect-impl/EffectUUID.h +++ b/audio/aidl/default/include/effect-impl/EffectUUID.h @@ -33,6 +33,30 @@ static const AudioUuid kEffectNullUuid = {static_cast(0xec7178ec), static const AudioUuid kEffectZeroUuid = { static_cast(0x0), 0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; +// 7b491460-8d4d-11e0-bd61-0002a5d5c51b. +static const AudioUuid kAcousticEchoCancelerTypeUUID = {static_cast(0x7b491460), + 0x8d4d, + 0x11e0, + 0xbd61, + {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}; +// bb392ec0-8d4d-11e0-a896-0002a5d5c51b +static const AudioUuid kAcousticEchoCancelerSwImplUUID = {static_cast(0xbb392ec0), + 0x8d4d, + 0x11e0, + 0xa896, + {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}; +// 0xae3c653b-be18-4ab8-8938-418f0a7f06ac +static const AudioUuid kAutomaticGainControlTypeUUID = {static_cast(0xae3c653b), + 0xbe18, + 0x4ab8, + 0x8938, + {0x41, 0x8f, 0x0a, 0x7f, 0x06, 0xac}}; +// 89f38e65-d4d2-4d64-ad0e-2b3e799ea886 +static const AudioUuid kAutomaticGainControlSwImplUUID = {static_cast(0x89f38e65), + 0xd4d2, + 0x4d64, + 0xad0e, + {0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86}}; // 0634f220-ddd4-11db-a0fc-0002a5d5c51b static const AudioUuid kBassBoostTypeUUID = {static_cast(0x0634f220), 0xddd4, @@ -153,6 +177,18 @@ static const AudioUuid kEnvReverbSwImplUUID = {static_cast(0xfa819886), 0x11ed, 0x9b6a, {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}}; +// 58b4b260-8e06-11e0-aa8e-0002a5d5c51b +static const AudioUuid kNoiseSuppressionTypeUUID = {static_cast(0x58b4b260), + 0x8e06, + 0x11e0, + 0xaa8e, + {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}; +// c06c8400-8e06-11e0-9cb6-0002a5d5c51b +static const AudioUuid kNoiseSuppressionSwImplUUID = {static_cast(0xc06c8400), + 0x8e06, + 0x11e0, + 0x9cb6, + {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}; // 47382d60-ddd8-11db-bf3a-0002a5d5c51b static const AudioUuid kPresetReverbTypeUUID = {static_cast(0x47382d60), 0xddd8, @@ -208,6 +244,8 @@ static const AudioUuid kVolumeSwImplUUID = {static_cast(0xfa81a718), * We need this map is because existing audio_effects.xml don't have a type UUID defined. */ static const std::map kUuidNameTypeMap = { + {"acoustic_echo_canceler", kAcousticEchoCancelerTypeUUID}, + {"automatic_gain_control", kAutomaticGainControlTypeUUID}, {"bassboost", kBassBoostTypeUUID}, {"downmix", kDownmixTypeUUID}, {"dynamics_processing", kDynamicsProcessingTypeUUID}, @@ -215,6 +253,7 @@ static const std::map kUu {"haptic_generator", kHapticGeneratorTypeUUID}, {"loudness_enhancer", kLoudnessEnhancerTypeUUID}, {"env_reverb", kEnvReverbTypeUUID}, + {"noise_suppression", kNoiseSuppressionTypeUUID}, {"preset_reverb", kPresetReverbTypeUUID}, {"reverb_env_aux", kEnvReverbTypeUUID}, {"reverb_env_ins", kEnvReverbTypeUUID}, diff --git a/audio/aidl/default/noiseSuppression/Android.bp b/audio/aidl/default/noiseSuppression/Android.bp new file mode 100644 index 0000000000..581d4bfe01 --- /dev/null +++ b/audio/aidl/default/noiseSuppression/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: "libnssw", + defaults: [ + "aidlaudioeffectservice_defaults", + "latest_android_media_audio_common_types_ndk_shared", + "latest_android_hardware_audio_effect_ndk_shared", + ], + srcs: [ + "NoiseSuppressionSw.cpp", + ":effectCommonFile", + ], + visibility: [ + "//hardware/interfaces/audio/aidl/default", + ], +} diff --git a/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.cpp b/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.cpp new file mode 100644 index 0000000000..a36cfe00a8 --- /dev/null +++ b/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.cpp @@ -0,0 +1,180 @@ +/* + * 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 +#include +#include +#define LOG_TAG "AHAL_NoiseSuppressionSw" +#include +#include + +#include +#include + +#include "NoiseSuppressionSw.h" + +using aidl::android::hardware::audio::effect::Descriptor; +using aidl::android::hardware::audio::effect::IEffect; +using aidl::android::hardware::audio::effect::kNoiseSuppressionSwImplUUID; +using aidl::android::hardware::audio::effect::NoiseSuppressionSw; +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 != kNoiseSuppressionSwImplUUID) { + 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 queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) { + if (!in_impl_uuid || *in_impl_uuid != kNoiseSuppressionSwImplUUID) { + LOG(ERROR) << __func__ << "uuid not supported"; + return EX_ILLEGAL_ARGUMENT; + } + *_aidl_return = NoiseSuppressionSw::kDescriptor; + return EX_NONE; +} + +namespace aidl::android::hardware::audio::effect { + +const std::string NoiseSuppressionSw::kEffectName = "NoiseSuppressionSw"; +const NoiseSuppression::Capability NoiseSuppressionSw::kCapability; +const Descriptor NoiseSuppressionSw::kDescriptor = { + .common = {.id = {.type = kNoiseSuppressionTypeUUID, + .uuid = kNoiseSuppressionSwImplUUID, + .proxy = std::nullopt}, + .flags = {.type = Flags::Type::INSERT, + .insert = Flags::Insert::FIRST, + .volume = Flags::Volume::CTRL}, + .name = NoiseSuppressionSw::kEffectName, + .implementor = "The Android Open Source Project"}, + .capability = + Capability::make(NoiseSuppressionSw::kCapability)}; + +ndk::ScopedAStatus NoiseSuppressionSw::getDescriptor(Descriptor* _aidl_return) { + LOG(DEBUG) << __func__ << kDescriptor.toString(); + *_aidl_return = kDescriptor; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus NoiseSuppressionSw::setParameterSpecific(const Parameter::Specific& specific) { + RETURN_IF(Parameter::Specific::noiseSuppression != specific.getTag(), EX_ILLEGAL_ARGUMENT, + "EffectNotSupported"); + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); + + auto& param = specific.get(); + auto tag = param.getTag(); + + switch (tag) { + case NoiseSuppression::level: { + RETURN_IF(mContext->setLevel(param.get()) != RetCode::SUCCESS, + EX_ILLEGAL_ARGUMENT, "levelSupported"); + return ndk::ScopedAStatus::ok(); + } + default: { + LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); + return ndk::ScopedAStatus::fromExceptionCodeWithMessage( + EX_ILLEGAL_ARGUMENT, "NoiseSuppressionTagNotSupported"); + } + } +} + +ndk::ScopedAStatus NoiseSuppressionSw::getParameterSpecific(const Parameter::Id& id, + Parameter::Specific* specific) { + auto tag = id.getTag(); + RETURN_IF(Parameter::Id::noiseSuppressionTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag"); + auto specificId = id.get(); + auto specificIdTag = specificId.getTag(); + switch (specificIdTag) { + case NoiseSuppression::Id::commonTag: + return getParameterNoiseSuppression(specificId.get(), + specific); + default: + LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); + return ndk::ScopedAStatus::fromExceptionCodeWithMessage( + EX_ILLEGAL_ARGUMENT, "NoiseSuppressionTagNotSupported"); + } +} + +ndk::ScopedAStatus NoiseSuppressionSw::getParameterNoiseSuppression( + const NoiseSuppression::Tag& tag, Parameter::Specific* specific) { + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); + NoiseSuppression param; + switch (tag) { + case NoiseSuppression::level: { + param.set(mContext->getLevel()); + break; + } + default: { + LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); + return ndk::ScopedAStatus::fromExceptionCodeWithMessage( + EX_ILLEGAL_ARGUMENT, "NoiseSuppressionTagNotSupported"); + } + } + + specific->set(param); + return ndk::ScopedAStatus::ok(); +} + +std::shared_ptr NoiseSuppressionSw::createContext(const Parameter::Common& common) { + if (mContext) { + LOG(DEBUG) << __func__ << " context already exist"; + } else { + mContext = std::make_shared(1 /* statusFmqDepth */, common); + } + return mContext; +} + +std::shared_ptr NoiseSuppressionSw::getContext() { + return mContext; +} + +RetCode NoiseSuppressionSw::releaseContext() { + if (mContext) { + mContext.reset(); + } + return RetCode::SUCCESS; +} + +// Processing method running in EffectWorker thread. +IEffect::Status NoiseSuppressionSw::effectProcessImpl(float* in, float* out, int samples) { + // TODO: get data buffer and process. + LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples; + for (int i = 0; i < samples; i++) { + *out++ = *in++; + } + return {STATUS_OK, samples, samples}; +} + +RetCode NoiseSuppressionSwContext::setLevel(NoiseSuppression::Level level) { + mLevel = level; + return RetCode::SUCCESS; +} + +NoiseSuppression::Level NoiseSuppressionSwContext::getLevel() { + return mLevel; +} + +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.h b/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.h new file mode 100644 index 0000000000..0c03038226 --- /dev/null +++ b/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.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 NoiseSuppressionSwContext final : public EffectContext { + public: + NoiseSuppressionSwContext(int statusDepth, const Parameter::Common& common) + : EffectContext(statusDepth, common) { + LOG(DEBUG) << __func__; + } + + RetCode setLevel(NoiseSuppression::Level level); + NoiseSuppression::Level getLevel(); + + private: + NoiseSuppression::Level mLevel; +}; + +class NoiseSuppressionSw final : public EffectImpl { + public: + static const std::string kEffectName; + static const bool kStrengthSupported; + static const NoiseSuppression::Capability kCapability; + static const Descriptor kDescriptor; + NoiseSuppressionSw() { LOG(DEBUG) << __func__; } + ~NoiseSuppressionSw() { + cleanUp(); + LOG(DEBUG) << __func__; + } + + 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; + + std::shared_ptr createContext(const Parameter::Common& common) override; + std::shared_ptr getContext() override; + RetCode releaseContext() override; + + std::string getEffectName() override { return kEffectName; }; + IEffect::Status effectProcessImpl(float* in, float* out, int samples) override; + + private: + std::shared_ptr mContext; + ndk::ScopedAStatus getParameterNoiseSuppression(const NoiseSuppression::Tag& tag, + Parameter::Specific* specific); +}; +} // namespace aidl::android::hardware::audio::effect From 5bd4a30758b0b0dc6de5386e2904758616ca5193 Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Tue, 20 Dec 2022 15:46:24 +0000 Subject: [PATCH 3/3] Effect AIDL: Add AEC, AGC and NS AIDL vts Bug: 238913361 Test: atest VtsHalAECTargetTest Test: atest VtsHalAGCTargetTest Test: atest VtsHalNSTargetTest Change-Id: Ie28ceda35a7ed3fa7857b439bdd4180d9c202f92 --- audio/aidl/TEST_MAPPING | 9 + audio/aidl/vts/Android.bp | 18 ++ audio/aidl/vts/EffectFactoryHelper.h | 1 - audio/aidl/vts/VtsHalAECTargetTest.cpp | 219 +++++++++++++++++++++ audio/aidl/vts/VtsHalAGCTargetTest.cpp | 256 +++++++++++++++++++++++++ audio/aidl/vts/VtsHalNSTargetTest.cpp | 158 +++++++++++++++ 6 files changed, 660 insertions(+), 1 deletion(-) create mode 100644 audio/aidl/vts/VtsHalAECTargetTest.cpp create mode 100644 audio/aidl/vts/VtsHalAGCTargetTest.cpp create mode 100644 audio/aidl/vts/VtsHalNSTargetTest.cpp diff --git a/audio/aidl/TEST_MAPPING b/audio/aidl/TEST_MAPPING index dfd82c3d41..6395abc249 100644 --- a/audio/aidl/TEST_MAPPING +++ b/audio/aidl/TEST_MAPPING @@ -20,6 +20,15 @@ }, { "name": "VtsHalVisualizerTargetTest" + }, + { + "name": "VtsHalAECTargetTest" + }, + { + "name": "VtsHalAGCTargetTest" + }, + { + "name": "VtsHalNSTargetTest" } ] } diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp index aeff615a5e..f44109dc62 100644 --- a/audio/aidl/vts/Android.bp +++ b/audio/aidl/vts/Android.bp @@ -96,3 +96,21 @@ cc_test { defaults: ["VtsHalAudioTargetTestDefaults"], srcs: ["VtsHalVisualizerTargetTest.cpp"], } + +cc_test { + name: "VtsHalAECTargetTest", + defaults: ["VtsHalAudioTargetTestDefaults"], + srcs: ["VtsHalAECTargetTest.cpp"], +} + +cc_test { + name: "VtsHalAGCTargetTest", + defaults: ["VtsHalAudioTargetTestDefaults"], + srcs: ["VtsHalAGCTargetTest.cpp"], +} + +cc_test { + name: "VtsHalNSTargetTest", + defaults: ["VtsHalAudioTargetTestDefaults"], + srcs: ["VtsHalNSTargetTest.cpp"], +} diff --git a/audio/aidl/vts/EffectFactoryHelper.h b/audio/aidl/vts/EffectFactoryHelper.h index 0d5c6499ac..4add844533 100644 --- a/audio/aidl/vts/EffectFactoryHelper.h +++ b/audio/aidl/vts/EffectFactoryHelper.h @@ -70,7 +70,6 @@ class EffectFactoryHelper { } } } - return result; } diff --git a/audio/aidl/vts/VtsHalAECTargetTest.cpp b/audio/aidl/vts/VtsHalAECTargetTest.cpp new file mode 100644 index 0000000000..a06ab421f2 --- /dev/null +++ b/audio/aidl/vts/VtsHalAECTargetTest.cpp @@ -0,0 +1,219 @@ +/* + * 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 +#include + +#define LOG_TAG "VtsHalAECParamTest" + +#include +#include "EffectHelper.h" + +using namespace android; + +using aidl::android::hardware::audio::effect::AcousticEchoCanceler; +using aidl::android::hardware::audio::effect::Capability; +using aidl::android::hardware::audio::effect::Descriptor; +using aidl::android::hardware::audio::effect::IEffect; +using aidl::android::hardware::audio::effect::IFactory; +using aidl::android::hardware::audio::effect::kAcousticEchoCancelerTypeUUID; +using aidl::android::hardware::audio::effect::Parameter; + +enum ParamName { PARAM_INSTANCE_NAME, PARAM_ECHO_DELAY, PARAM_MOBILE_MODE }; +using AECParamTestParam = std::tuple, Descriptor>, + int /* echoDelayUs */, bool /* mobileMode */>; + +class AECParamTest : public ::testing::TestWithParam, public EffectHelper { + public: + AECParamTest() + : mEchoDelay(std::get(GetParam())), + mMobileMode(std::get(GetParam())) { + std::tie(mFactory, mDescriptor) = std::get(GetParam()); + } + + void SetUp() override { + ASSERT_NE(nullptr, mFactory); + ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor)); + + Parameter::Specific specific = getDefaultParamSpecific(); + Parameter::Common common = EffectHelper::createParamCommon( + 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */, + kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */); + IEffect::OpenEffectReturn ret; + ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE)); + ASSERT_NE(nullptr, mEffect); + } + + void TearDown() override { + ASSERT_NO_FATAL_FAILURE(close(mEffect)); + ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect)); + } + + Parameter::Specific getDefaultParamSpecific() { + AcousticEchoCanceler aec = AcousticEchoCanceler::make(0); + Parameter::Specific specific = + Parameter::Specific::make(aec); + return specific; + } + + static const std::vector, Descriptor>> kFactoryDescList; + static const std::vector kEchoDelayValues; + static const std::vector kMobileModeValues; + + static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100; + std::shared_ptr mFactory; + std::shared_ptr mEffect; + Descriptor mDescriptor; + + int mEchoDelay; + bool mMobileMode; + + void SetAndGetParameters() { + for (auto& it : mTags) { + auto& tag = it.first; + auto& aec = it.second; + + // validate parameter + Descriptor desc; + ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc)); + const bool valid = isTagInRange(tag, aec, desc); + const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT; + + // set parameter + Parameter expectParam; + Parameter::Specific specific; + specific.set(aec); + expectParam.set(specific); + EXPECT_STATUS(expected, mEffect->setParameter(expectParam)) << expectParam.toString(); + + // only get if parameter in range and set success + if (expected == EX_NONE) { + Parameter getParam; + Parameter::Id id; + AcousticEchoCanceler::Id specificId; + specificId.set(tag); + id.set(specificId); + EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam)); + + EXPECT_EQ(expectParam, getParam) << "\nexpect:" << expectParam.toString() + << "\ngetParam:" << getParam.toString(); + } + } + } + + void addEchoDelayParam(int delay) { + AcousticEchoCanceler aec; + aec.set(delay); + mTags.push_back({AcousticEchoCanceler::echoDelayUs, aec}); + } + + void addMobileModeParam(bool mode) { + AcousticEchoCanceler aec; + aec.set(mode); + mTags.push_back({AcousticEchoCanceler::mobileMode, aec}); + } + + bool isTagInRange(const AcousticEchoCanceler::Tag& tag, const AcousticEchoCanceler& aec, + const Descriptor& desc) const { + const AcousticEchoCanceler::Capability& aecCap = + desc.capability.get(); + switch (tag) { + case AcousticEchoCanceler::echoDelayUs: { + return isEchoDelayInRange(aecCap, aec.get()); + } + case AcousticEchoCanceler::mobileMode: { + bool mode = aec.get(); + return isMobileModeValid(aecCap, mode); + } + default: + return false; + } + } + + bool isEchoDelayInRange(const AcousticEchoCanceler::Capability& cap, int delay) const { + return (delay >= 0 && delay <= cap.maxEchoDelayUs); + } + + bool isMobileModeValid(const AcousticEchoCanceler::Capability& cap, bool mode) const { + if (cap.supportMobileMode) { + return true; + } else { + return mode == false; + } + } + + static std::vector getEchoDelayTestValues() { + const auto max = std::max_element( + kFactoryDescList.begin(), kFactoryDescList.end(), + [](const std::pair, Descriptor>& a, + const std::pair, Descriptor>& b) { + return a.second.capability.get() + .maxEchoDelayUs < + b.second.capability.get() + .maxEchoDelayUs; + }); + if (max == kFactoryDescList.end()) { + return {0}; + } + int maxDelay = + max->second.capability.get().maxEchoDelayUs; + return {-1, 0, maxDelay - 1, maxDelay, maxDelay + 1}; + } + + private: + std::vector> mTags; + void CleanUp() { mTags.clear(); } +}; + +const std::vector, Descriptor>> AECParamTest::kFactoryDescList = + EffectFactoryHelper::getAllEffectDescriptors(IFactory::descriptor, + kAcousticEchoCancelerTypeUUID); +const std::vector AECParamTest::kEchoDelayValues = AECParamTest::getEchoDelayTestValues(); +const std::vector AECParamTest::kMobileModeValues = {true, false}; + +TEST_P(AECParamTest, SetAndGetEchoDelay) { + EXPECT_NO_FATAL_FAILURE(addEchoDelayParam(mEchoDelay)); + SetAndGetParameters(); +} + +TEST_P(AECParamTest, SetAndGetMobileMode) { + EXPECT_NO_FATAL_FAILURE(addMobileModeParam(mMobileMode)); + SetAndGetParameters(); +} + +INSTANTIATE_TEST_SUITE_P(AECParamTest, AECParamTest, + ::testing::Combine(testing::ValuesIn(AECParamTest::kFactoryDescList), + testing::ValuesIn(AECParamTest::kEchoDelayValues), + testing::ValuesIn(AECParamTest::kMobileModeValues)), + [](const testing::TestParamInfo& info) { + auto descriptor = std::get(info.param).second; + std::string name = "Implementor_" + descriptor.common.implementor + + "_name_" + descriptor.common.name + "_UUID_" + + descriptor.common.id.uuid.toString(); + std::replace_if( + name.begin(), name.end(), + [](const char c) { return !std::isalnum(c); }, '_'); + return name; + }); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AECParamTest); + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ABinderProcess_setThreadPoolMaxThreadCount(1); + ABinderProcess_startThreadPool(); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/audio/aidl/vts/VtsHalAGCTargetTest.cpp b/audio/aidl/vts/VtsHalAGCTargetTest.cpp new file mode 100644 index 0000000000..ea3654f90a --- /dev/null +++ b/audio/aidl/vts/VtsHalAGCTargetTest.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. + */ + +#include + +#define LOG_TAG "VtsHalAGCParamTest" + +#include +#include "EffectHelper.h" + +using namespace android; + +using aidl::android::hardware::audio::effect::AutomaticGainControl; +using aidl::android::hardware::audio::effect::Capability; +using aidl::android::hardware::audio::effect::Descriptor; +using aidl::android::hardware::audio::effect::IEffect; +using aidl::android::hardware::audio::effect::IFactory; +using aidl::android::hardware::audio::effect::kAutomaticGainControlTypeUUID; +using aidl::android::hardware::audio::effect::Parameter; + +enum ParamName { + PARAM_INSTANCE_NAME, + PARAM_DIGITAL_GAIN, + PARAM_SATURATION_MARGIN, + PARAM_LEVEL_ESTIMATOR +}; +using AGCParamTestParam = + std::tuple, Descriptor>, int /* gain */, + int /* margin */, AutomaticGainControl::LevelEstimator>; + +class AGCParamTest : public ::testing::TestWithParam, public EffectHelper { + public: + AGCParamTest() + : mGain(std::get(GetParam())), + mMargin(std::get(GetParam())), + mLevelEstimator(std::get(GetParam())) { + std::tie(mFactory, mDescriptor) = std::get(GetParam()); + } + + void SetUp() override { + ASSERT_NE(nullptr, mFactory); + ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor)); + + Parameter::Specific specific = getDefaultParamSpecific(); + Parameter::Common common = EffectHelper::createParamCommon( + 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */, + kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */); + IEffect::OpenEffectReturn ret; + ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE)); + ASSERT_NE(nullptr, mEffect); + } + + void TearDown() override { + ASSERT_NO_FATAL_FAILURE(close(mEffect)); + ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect)); + } + + Parameter::Specific getDefaultParamSpecific() { + AutomaticGainControl AGC = + AutomaticGainControl::make(0); + Parameter::Specific specific = + Parameter::Specific::make(AGC); + return specific; + } + + static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100; + static const std::vector, Descriptor>> kFactoryDescList; + static const std::vector kDigitalGainValues; + static const std::vector kSaturationMarginValues; + static const std::vector kLevelEstimatorValues; + + std::shared_ptr mFactory; + std::shared_ptr mEffect; + Descriptor mDescriptor; + int mGain; + int mMargin; + AutomaticGainControl::LevelEstimator mLevelEstimator; + + void SetAndGetParameters() { + for (auto& it : mTags) { + auto& tag = it.first; + auto& AGC = it.second; + + // validate parameter + Descriptor desc; + ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc)); + const bool valid = isTagInRange(tag, AGC, desc); + const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT; + + // set parameter + Parameter expectParam; + Parameter::Specific specific; + specific.set(AGC); + expectParam.set(specific); + EXPECT_STATUS(expected, mEffect->setParameter(expectParam)) << expectParam.toString(); + + // only get if parameter in range and set success + if (expected == EX_NONE) { + Parameter getParam; + Parameter::Id id; + AutomaticGainControl::Id specificId; + specificId.set(tag); + id.set(specificId); + EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam)); + + EXPECT_EQ(expectParam, getParam) << "\nexpect:" << expectParam.toString() + << "\ngetParam:" << getParam.toString(); + } + } + } + + void addDigitalGainParam(int gain) { + AutomaticGainControl AGC; + AGC.set(gain); + mTags.push_back({AutomaticGainControl::fixedDigitalGainMb, AGC}); + } + void addSaturationMarginParam(int margin) { + AutomaticGainControl AGC; + AGC.set(margin); + mTags.push_back({AutomaticGainControl::saturationMarginMb, AGC}); + } + void addLevelEstimatorParam(AutomaticGainControl::LevelEstimator levelEstimator) { + AutomaticGainControl AGC; + AGC.set(levelEstimator); + mTags.push_back({AutomaticGainControl::levelEstimator, AGC}); + } + + bool isTagInRange(const AutomaticGainControl::Tag& tag, const AutomaticGainControl& AGC, + const Descriptor& desc) const { + const AutomaticGainControl::Capability& AGCCap = + desc.capability.get(); + switch (tag) { + case AutomaticGainControl::fixedDigitalGainMb: { + auto gain = AGC.get(); + return gain >= 0 && gain <= AGCCap.maxFixedDigitalGainMb; + } + case AutomaticGainControl::levelEstimator: { + return true; + } + case AutomaticGainControl::saturationMarginMb: { + auto margin = AGC.get(); + return margin >= 0 && margin <= AGCCap.maxSaturationMarginMb; + } + default: + return false; + } + } + static std::vector getDigitalGainValues() { + const auto max = std::max_element( + kFactoryDescList.begin(), kFactoryDescList.end(), + [](const std::pair, Descriptor>& a, + const std::pair, Descriptor>& b) { + return a.second.capability.get() + .maxFixedDigitalGainMb < + b.second.capability.get() + .maxFixedDigitalGainMb; + }); + if (max == kFactoryDescList.end()) { + return {0}; + } + int maxGain = max->second.capability.get() + .maxFixedDigitalGainMb; + return {-1, 0, maxGain - 1, maxGain, maxGain + 1}; + } + static std::vector getSaturationMarginValues() { + const auto max = std::max_element( + kFactoryDescList.begin(), kFactoryDescList.end(), + [](const std::pair, Descriptor>& a, + const std::pair, Descriptor>& b) { + return a.second.capability.get() + .maxSaturationMarginMb < + b.second.capability.get() + .maxSaturationMarginMb; + }); + if (max == kFactoryDescList.end()) { + return {0}; + } + int maxMargin = max->second.capability.get() + .maxSaturationMarginMb; + return {-1, 0, maxMargin - 1, maxMargin, maxMargin + 1}; + } + + private: + std::vector> mTags; + void CleanUp() { mTags.clear(); } +}; + +const std::vector, Descriptor>> AGCParamTest::kFactoryDescList = + EffectFactoryHelper::getAllEffectDescriptors(IFactory::descriptor, + kAutomaticGainControlTypeUUID); +const std::vector AGCParamTest::kDigitalGainValues = AGCParamTest::getDigitalGainValues(); +const std::vector AGCParamTest::kSaturationMarginValues = + AGCParamTest::getSaturationMarginValues(); +const std::vector AGCParamTest::kLevelEstimatorValues = { + AutomaticGainControl::LevelEstimator::RMS, AutomaticGainControl::LevelEstimator::PEAK}; + +TEST_P(AGCParamTest, SetAndGetDigitalGainParam) { + EXPECT_NO_FATAL_FAILURE(addDigitalGainParam(mGain)); + SetAndGetParameters(); +} + +TEST_P(AGCParamTest, SetAndGetSaturationMargin) { + EXPECT_NO_FATAL_FAILURE(addSaturationMarginParam(mMargin)); + SetAndGetParameters(); +} + +TEST_P(AGCParamTest, SetAndGetLevelEstimator) { + EXPECT_NO_FATAL_FAILURE(addLevelEstimatorParam(mLevelEstimator)); + SetAndGetParameters(); +} + +INSTANTIATE_TEST_SUITE_P( + AGCParamTest, AGCParamTest, + ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors( + IFactory::descriptor, kAutomaticGainControlTypeUUID)), + testing::ValuesIn(AGCParamTest::kDigitalGainValues), + testing::ValuesIn(AGCParamTest::kSaturationMarginValues), + testing::ValuesIn(AGCParamTest::kLevelEstimatorValues)), + [](const testing::TestParamInfo& info) { + auto descriptor = std::get(info.param).second; + std::string gain = std::to_string(std::get(info.param)); + std::string estimator = aidl::android::hardware::audio::effect::toString( + std::get(info.param)); + std::string margin = + std::to_string(static_cast(std::get(info.param))); + + std::string name = "Implementor_" + descriptor.common.implementor + "_name_" + + descriptor.common.name + "_UUID_" + + descriptor.common.id.uuid.toString() + "_digital_gain_" + gain + + "_level_estimator_" + estimator + "_margin_" + margin; + std::replace_if( + name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_'); + return name; + }); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AGCParamTest); + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ABinderProcess_setThreadPoolMaxThreadCount(1); + ABinderProcess_startThreadPool(); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/audio/aidl/vts/VtsHalNSTargetTest.cpp b/audio/aidl/vts/VtsHalNSTargetTest.cpp new file mode 100644 index 0000000000..186cb680ec --- /dev/null +++ b/audio/aidl/vts/VtsHalNSTargetTest.cpp @@ -0,0 +1,158 @@ +/* + * 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 "VtsHalNSParamTest" + +#include +#include "EffectHelper.h" + +using namespace android; + +using aidl::android::hardware::audio::effect::Capability; +using aidl::android::hardware::audio::effect::Descriptor; +using aidl::android::hardware::audio::effect::IEffect; +using aidl::android::hardware::audio::effect::IFactory; +using aidl::android::hardware::audio::effect::kNoiseSuppressionTypeUUID; +using aidl::android::hardware::audio::effect::NoiseSuppression; +using aidl::android::hardware::audio::effect::Parameter; + +enum ParamName { PARAM_INSTANCE_NAME, PARAM_LEVEL }; +using NSParamTestParam = + std::tuple, Descriptor>, NoiseSuppression::Level>; + +class NSParamTest : public ::testing::TestWithParam, public EffectHelper { + public: + NSParamTest() : mLevel(std::get(GetParam())) { + std::tie(mFactory, mDescriptor) = std::get(GetParam()); + } + + void SetUp() override { + ASSERT_NE(nullptr, mFactory); + ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor)); + + Parameter::Specific specific = getDefaultParamSpecific(); + Parameter::Common common = EffectHelper::createParamCommon( + 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */, + kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */); + IEffect::OpenEffectReturn ret; + ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE)); + ASSERT_NE(nullptr, mEffect); + } + + void TearDown() override { + ASSERT_NO_FATAL_FAILURE(close(mEffect)); + ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect)); + } + + Parameter::Specific getDefaultParamSpecific() { + NoiseSuppression ns = + NoiseSuppression::make(NoiseSuppression::Level::MEDIUM); + Parameter::Specific specific = + Parameter::Specific::make(ns); + return specific; + } + + static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100; + static const std::vector, Descriptor>> kFactoryDescList; + static const std::vector kLevelValues; + + std::shared_ptr mFactory; + std::shared_ptr mEffect; + Descriptor mDescriptor; + NoiseSuppression::Level mLevel; + + void SetAndGetParameters() { + for (auto& it : mTags) { + auto& tag = it.first; + auto& ns = it.second; + + // validate parameter + Descriptor desc; + ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc)); + const binder_exception_t expected = EX_NONE; + + // set parameter + Parameter expectParam; + Parameter::Specific specific; + specific.set(ns); + expectParam.set(specific); + EXPECT_STATUS(expected, mEffect->setParameter(expectParam)) << expectParam.toString(); + + // only get if parameter in range and set success + if (expected == EX_NONE) { + Parameter getParam; + Parameter::Id id; + NoiseSuppression::Id specificId; + specificId.set(tag); + id.set(specificId); + EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam)); + + EXPECT_EQ(expectParam, getParam) << "\nexpect:" << expectParam.toString() + << "\ngetParam:" << getParam.toString(); + } + } + } + + void addLevelParam(NoiseSuppression::Level level) { + NoiseSuppression ns; + ns.set(level); + mTags.push_back({NoiseSuppression::level, ns}); + } + + private: + std::vector> mTags; + void CleanUp() { mTags.clear(); } +}; + +const std::vector, Descriptor>> kFactoryDescList = + EffectFactoryHelper::getAllEffectDescriptors(IFactory::descriptor, + kNoiseSuppressionTypeUUID); +const std::vector NSParamTest::kLevelValues = { + NoiseSuppression::Level::LOW, NoiseSuppression::Level::MEDIUM, + NoiseSuppression::Level::HIGH}; + +TEST_P(NSParamTest, SetAndGetLevel) { + EXPECT_NO_FATAL_FAILURE(addLevelParam(mLevel)); + SetAndGetParameters(); +} + +INSTANTIATE_TEST_SUITE_P( + NSParamTest, NSParamTest, + ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors( + IFactory::descriptor, kNoiseSuppressionTypeUUID)), + testing::ValuesIn(NSParamTest::kLevelValues)), + [](const testing::TestParamInfo& info) { + auto descriptor = std::get(info.param).second; + std::string level = aidl::android::hardware::audio::effect::toString( + std::get(info.param)); + std::string name = "Implementor_" + descriptor.common.implementor + "_name_" + + descriptor.common.name + "_UUID_" + + descriptor.common.id.uuid.toString() + "_level_" + level; + std::replace_if( + name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_'); + return name; + }); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NSParamTest); + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ABinderProcess_setThreadPoolMaxThreadCount(1); + ABinderProcess_startThreadPool(); + return RUN_ALL_TESTS(); +} \ No newline at end of file