Merge changes from topic "processing_effects" am: a46044e8d3 am: 7633167164 am: 1abc850cf9
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2363493
Change-Id: Id64b34e3f338a8f44b694d662b6778344b49c2ae
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
index 7d474b2..42a4ac1 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -223,6 +223,8 @@
"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 @@
"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/TEST_MAPPING b/audio/aidl/TEST_MAPPING
index 3c58324..1de1b5b 100644
--- a/audio/aidl/TEST_MAPPING
+++ b/audio/aidl/TEST_MAPPING
@@ -23,6 +23,15 @@
},
{
"name": "VtsHalVisualizerTargetTest"
+ },
+ {
+ "name": "VtsHalAECTargetTest"
+ },
+ {
+ "name": "VtsHalAGCTargetTest"
+ },
+ {
+ "name": "VtsHalNSTargetTest"
}
]
}
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 0000000..1d51ade
--- /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 <name>-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 0000000..39068d5
--- /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 <name>-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 60c88d3..28f77b3 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 @@
@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 @@
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 0000000..223d95a
--- /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 <name>-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 0635c13..eaa4bb1 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 @@
@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 @@
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 @@
@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 @@
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 a779ae4..f6d6ee2 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 @@
@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 0000000..19d60b6
--- /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 0000000..e82a564
--- /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 4149783..30780e6 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.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 @@
/**
* Effect capabilities.
*/
+ AcousticEchoCanceler.Capability acousticEchoCanceler;
+ AutomaticGainControl.Capability automaticGainControl;
BassBoost.Capability bassBoost;
Downmix.Capability downmix;
DynamicsProcessing.Capability dynamicsProcessing;
@@ -56,6 +61,7 @@
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 0000000..946fa87
--- /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 d7a6a27..1c001d2 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.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 @@
* effectInstance.getParameter(id, ¶m);
*
*/
+ AcousticEchoCanceler.Id acousticEchoCancelerTag;
+ AutomaticGainControl.Id automaticGainControlTag;
BassBoost.Id bassBoostTag;
Downmix.Id downmixTag;
DynamicsProcessing.Id dynamicsProcessingTag;
@@ -78,6 +83,7 @@
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 @@
@VintfStability
union Specific {
VendorExtension vendorEffect;
+ AcousticEchoCanceler acousticEchoCanceler;
+ AutomaticGainControl automaticGainControl;
BassBoost bassBoost;
Downmix downmix;
DynamicsProcessing dynamicsProcessing;
@@ -156,6 +164,7 @@
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 ef32e8c..cb77350 100644
--- a/audio/aidl/android/hardware/audio/effect/Processing.aidl
+++ b/audio/aidl/android/hardware/audio/effect/Processing.aidl
@@ -38,7 +38,7 @@
*/
Type type;
/**
- * List of effect identities for this processing.
+ * List of effect descriptors for this processing.
*/
- Descriptor.Identity[] ids;
+ Descriptor[] ids;
}
diff --git a/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.cpp b/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.cpp
new file mode 100644
index 0000000..7f06013
--- /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 <algorithm>
+#include <cstddef>
+#include <memory>
+#define LOG_TAG "AHAL_AcousticEchoCancelerSw"
+#include <Utils.h>
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+
+#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<IEffect>* 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<AcousticEchoCancelerSw>();
+ 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<Capability::acousticEchoCanceler>(
+ 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<Parameter::Specific::acousticEchoCanceler>();
+ auto tag = param.getTag();
+
+ switch (tag) {
+ case AcousticEchoCanceler::echoDelayUs: {
+ RETURN_IF(mContext->setEchoDelay(param.get<AcousticEchoCanceler::echoDelayUs>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "echoDelayNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case AcousticEchoCanceler::mobileMode: {
+ RETURN_IF(true == param.get<AcousticEchoCanceler::mobileMode>(), 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<Parameter::Id::acousticEchoCancelerTag>();
+ auto specificIdTag = specificId.getTag();
+ switch (specificIdTag) {
+ case AcousticEchoCanceler::Id::commonTag:
+ return getParameterAcousticEchoCanceler(
+ specificId.get<AcousticEchoCanceler::Id::commonTag>(), 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<AcousticEchoCanceler::echoDelayUs>(mContext->getEchoDelay());
+ break;
+ }
+ case AcousticEchoCanceler::mobileMode: {
+ param.set<AcousticEchoCanceler::mobileMode>(false);
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "AcousticEchoCancelerTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::acousticEchoCanceler>(param);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> AcousticEchoCancelerSw::createContext(
+ const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ } else {
+ mContext = std::make_shared<AcousticEchoCancelerSwContext>(1 /* statusFmqDepth */, common);
+ }
+ return mContext;
+}
+
+std::shared_ptr<EffectContext> 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 0000000..809812a
--- /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 <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <fmq/AidlMessageQueue.h>
+#include <cstdlib>
+#include <memory>
+
+#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<EffectContext> createContext(const Parameter::Common& common) override;
+ std::shared_ptr<EffectContext> 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<AcousticEchoCancelerSwContext> 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 0000000..b2e2682
--- /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 9491bc3..28a7656 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.
-->
<libraries>
+ <library name="aecsw" path="libaecsw.so"/>
+ <library name="agcsw" path="libagcsw.so"/>
<library name="bassboostsw" path="libbassboostsw.so"/>
<library name="bundle" path="libbundleaidl.so"/>
<library name="downmix" path="libdownmixaidl.so"/>
@@ -35,6 +37,7 @@
<library name="equalizersw" path="libequalizersw.so"/>
<library name="haptic_generatorsw" path="libhapticgeneratorsw.so"/>
<library name="loudness_enhancer" path="libloudnessenhanceraidl.so"/>
+ <library name="nssw" path="libnssw.so"/>
<library name="env_reverbsw" path="libenvreverbsw.so"/>
<library name="preset_reverbsw" path="libpresetreverbsw.so"/>
<library name="virtualizersw" path="libvirtualizersw.so"/>
@@ -62,6 +65,8 @@
-->
<effects>
+ <effect name="acoustic_echo_canceler" library="aecsw" uuid="bb392ec0-8d4d-11e0-a896-0002a5d5c51b"/>
+ <effect name="automatic_gain_control" library="agcsw" uuid="89f38e65-d4d2-4d64-ad0e-2b3e799ea886"/>
<effectProxy name="bassboost" uuid="14804144-a5ee-4d24-aa88-0002a5d5c51b">
<libsw library="bassboostsw" uuid="fa8181f2-588b-11ed-9b6a-0242ac120002"/>
<libsw library="bundle" uuid="8631f300-72e2-11df-b57e-0002a5d5c51b"/>
@@ -71,6 +76,7 @@
<effect name="haptic_generator" library="haptic_generatorsw" uuid="fa819110-588b-11ed-9b6a-0242ac120002"/>
<effect name="loudness_enhancer" library="loudness_enhancer" uuid="fa415329-2034-4bea-b5dc-5b381c8d1e2c"/>
<effect name="env_reverb" library="env_reverbsw" uuid="fa819886-588b-11ed-9b6a-0242ac120002"/>
+ <effect name="noise_suppression" library="nssw" uuid="c06c8400-8e06-11e0-9cb6-0002a5d5c51b"/>
<effect name="preset_reverb" library="preset_reverbsw" uuid="fa8199c6-588b-11ed-9b6a-0242ac120002"/>
<effect name="virtualizer" library="virtualizersw" uuid="fa819d86-588b-11ed-9b6a-0242ac120002"/>
<effect name="visualizer" library="visualizersw" uuid="fa81a0f6-588b-11ed-9b6a-0242ac120002"/>
diff --git a/audio/aidl/default/automaticGainControl/Android.bp b/audio/aidl/default/automaticGainControl/Android.bp
new file mode 100644
index 0000000..4899b39
--- /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 0000000..8c706ef
--- /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 <algorithm>
+#include <cstddef>
+#include <memory>
+#define LOG_TAG "AHAL_AutomaticGainControlSw"
+#include <Utils.h>
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+
+#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<IEffect>* 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<AutomaticGainControlSw>();
+ 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<Capability::automaticGainControl>(
+ 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<Parameter::Specific::automaticGainControl>();
+ auto tag = param.getTag();
+
+ switch (tag) {
+ case AutomaticGainControl::fixedDigitalGainMb: {
+ RETURN_IF(mContext->setDigitalGain(
+ param.get<AutomaticGainControl::fixedDigitalGainMb>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "digitalGainNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case AutomaticGainControl::levelEstimator: {
+ RETURN_IF(
+ mContext->setLevelEstimator(
+ param.get<AutomaticGainControl::levelEstimator>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "levelEstimatorNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case AutomaticGainControl::saturationMarginMb: {
+ RETURN_IF(mContext->setSaturationMargin(
+ param.get<AutomaticGainControl::saturationMarginMb>()) !=
+ 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<Parameter::Id::automaticGainControlTag>();
+ auto specificIdTag = specificId.getTag();
+ switch (specificIdTag) {
+ case AutomaticGainControl::Id::commonTag:
+ return getParameterAutomaticGainControl(
+ specificId.get<AutomaticGainControl::Id::commonTag>(), 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<AutomaticGainControl::fixedDigitalGainMb>(mContext->getDigitalGain());
+ break;
+ }
+ case AutomaticGainControl::levelEstimator: {
+ param.set<AutomaticGainControl::levelEstimator>(mContext->getLevelEstimator());
+ break;
+ }
+ case AutomaticGainControl::saturationMarginMb: {
+ param.set<AutomaticGainControl::saturationMarginMb>(mContext->getSaturationMargin());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "AutomaticGainControlTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::automaticGainControl>(param);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> AutomaticGainControlSw::createContext(
+ const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ } else {
+ mContext = std::make_shared<AutomaticGainControlSwContext>(1 /* statusFmqDepth */, common);
+ }
+ return mContext;
+}
+
+std::shared_ptr<EffectContext> 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 0000000..e23fec0
--- /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 <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <fmq/AidlMessageQueue.h>
+#include <cstdlib>
+#include <memory>
+
+#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<EffectContext> createContext(const Parameter::Common& common) override;
+ std::shared_ptr<EffectContext> 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<AutomaticGainControlSwContext> 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 c9bb1f4..34472b3 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 kEffectZeroUuid = {
static_cast<int32_t>(0x0), 0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
+// 7b491460-8d4d-11e0-bd61-0002a5d5c51b.
+static const AudioUuid kAcousticEchoCancelerTypeUUID = {static_cast<int32_t>(0x7b491460),
+ 0x8d4d,
+ 0x11e0,
+ 0xbd61,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+// bb392ec0-8d4d-11e0-a896-0002a5d5c51b
+static const AudioUuid kAcousticEchoCancelerSwImplUUID = {static_cast<int32_t>(0xbb392ec0),
+ 0x8d4d,
+ 0x11e0,
+ 0xa896,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+// 0xae3c653b-be18-4ab8-8938-418f0a7f06ac
+static const AudioUuid kAutomaticGainControlTypeUUID = {static_cast<int32_t>(0xae3c653b),
+ 0xbe18,
+ 0x4ab8,
+ 0x8938,
+ {0x41, 0x8f, 0x0a, 0x7f, 0x06, 0xac}};
+// 89f38e65-d4d2-4d64-ad0e-2b3e799ea886
+static const AudioUuid kAutomaticGainControlSwImplUUID = {static_cast<int32_t>(0x89f38e65),
+ 0xd4d2,
+ 0x4d64,
+ 0xad0e,
+ {0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86}};
// 0634f220-ddd4-11db-a0fc-0002a5d5c51b
static const AudioUuid kBassBoostTypeUUID = {static_cast<int32_t>(0x0634f220),
0xddd4,
@@ -153,6 +177,18 @@
0x11ed,
0x9b6a,
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// 58b4b260-8e06-11e0-aa8e-0002a5d5c51b
+static const AudioUuid kNoiseSuppressionTypeUUID = {static_cast<int32_t>(0x58b4b260),
+ 0x8e06,
+ 0x11e0,
+ 0xaa8e,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+// c06c8400-8e06-11e0-9cb6-0002a5d5c51b
+static const AudioUuid kNoiseSuppressionSwImplUUID = {static_cast<int32_t>(0xc06c8400),
+ 0x8e06,
+ 0x11e0,
+ 0x9cb6,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
// 47382d60-ddd8-11db-bf3a-0002a5d5c51b
static const AudioUuid kPresetReverbTypeUUID = {static_cast<int32_t>(0x47382d60),
0xddd8,
@@ -208,6 +244,8 @@
* We need this map is because existing audio_effects.xml don't have a type UUID defined.
*/
static const std::map<const std::string /* effect type */, const AudioUuid&> kUuidNameTypeMap = {
+ {"acoustic_echo_canceler", kAcousticEchoCancelerTypeUUID},
+ {"automatic_gain_control", kAutomaticGainControlTypeUUID},
{"bassboost", kBassBoostTypeUUID},
{"downmix", kDownmixTypeUUID},
{"dynamics_processing", kDynamicsProcessingTypeUUID},
@@ -215,6 +253,7 @@
{"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 0000000..581d4bf
--- /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 0000000..a36cfe0
--- /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 <algorithm>
+#include <cstddef>
+#include <memory>
+#define LOG_TAG "AHAL_NoiseSuppressionSw"
+#include <Utils.h>
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+
+#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<IEffect>* 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<NoiseSuppressionSw>();
+ 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<Capability::noiseSuppression>(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<Parameter::Specific::noiseSuppression>();
+ auto tag = param.getTag();
+
+ switch (tag) {
+ case NoiseSuppression::level: {
+ RETURN_IF(mContext->setLevel(param.get<NoiseSuppression::level>()) != 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<Parameter::Id::noiseSuppressionTag>();
+ auto specificIdTag = specificId.getTag();
+ switch (specificIdTag) {
+ case NoiseSuppression::Id::commonTag:
+ return getParameterNoiseSuppression(specificId.get<NoiseSuppression::Id::commonTag>(),
+ 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<NoiseSuppression::level>(mContext->getLevel());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "NoiseSuppressionTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::noiseSuppression>(param);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> NoiseSuppressionSw::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ } else {
+ mContext = std::make_shared<NoiseSuppressionSwContext>(1 /* statusFmqDepth */, common);
+ }
+ return mContext;
+}
+
+std::shared_ptr<EffectContext> 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 0000000..0c03038
--- /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 <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <fmq/AidlMessageQueue.h>
+#include <cstdlib>
+#include <memory>
+
+#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<EffectContext> createContext(const Parameter::Common& common) override;
+ std::shared_ptr<EffectContext> 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<NoiseSuppressionSwContext> mContext;
+ ndk::ScopedAStatus getParameterNoiseSuppression(const NoiseSuppression::Tag& tag,
+ Parameter::Specific* specific);
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index dcdecab..3e70525 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -102,3 +102,21 @@
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 0d5c649..4add844 100644
--- a/audio/aidl/vts/EffectFactoryHelper.h
+++ b/audio/aidl/vts/EffectFactoryHelper.h
@@ -70,7 +70,6 @@
}
}
}
-
return result;
}
diff --git a/audio/aidl/vts/VtsHalAECTargetTest.cpp b/audio/aidl/vts/VtsHalAECTargetTest.cpp
new file mode 100644
index 0000000..a06ab42
--- /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 <aidl/Vintf.h>
+#include <algorithm>
+
+#define LOG_TAG "VtsHalAECParamTest"
+
+#include <Utils.h>
+#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<std::pair<std::shared_ptr<IFactory>, Descriptor>,
+ int /* echoDelayUs */, bool /* mobileMode */>;
+
+class AECParamTest : public ::testing::TestWithParam<AECParamTestParam>, public EffectHelper {
+ public:
+ AECParamTest()
+ : mEchoDelay(std::get<PARAM_ECHO_DELAY>(GetParam())),
+ mMobileMode(std::get<PARAM_MOBILE_MODE>(GetParam())) {
+ std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(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<AcousticEchoCanceler::echoDelayUs>(0);
+ Parameter::Specific specific =
+ Parameter::Specific::make<Parameter::Specific::acousticEchoCanceler>(aec);
+ return specific;
+ }
+
+ static const std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> kFactoryDescList;
+ static const std::vector<int> kEchoDelayValues;
+ static const std::vector<bool> kMobileModeValues;
+
+ static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+ std::shared_ptr<IFactory> mFactory;
+ std::shared_ptr<IEffect> 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<Parameter::Specific::acousticEchoCanceler>(aec);
+ expectParam.set<Parameter::specific>(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<AcousticEchoCanceler::Id::commonTag>(tag);
+ id.set<Parameter::Id::acousticEchoCancelerTag>(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<AcousticEchoCanceler::echoDelayUs>(delay);
+ mTags.push_back({AcousticEchoCanceler::echoDelayUs, aec});
+ }
+
+ void addMobileModeParam(bool mode) {
+ AcousticEchoCanceler aec;
+ aec.set<AcousticEchoCanceler::mobileMode>(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<Capability::acousticEchoCanceler>();
+ switch (tag) {
+ case AcousticEchoCanceler::echoDelayUs: {
+ return isEchoDelayInRange(aecCap, aec.get<AcousticEchoCanceler::echoDelayUs>());
+ }
+ case AcousticEchoCanceler::mobileMode: {
+ bool mode = aec.get<AcousticEchoCanceler::mobileMode>();
+ 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<int> getEchoDelayTestValues() {
+ const auto max = std::max_element(
+ kFactoryDescList.begin(), kFactoryDescList.end(),
+ [](const std::pair<std::shared_ptr<IFactory>, Descriptor>& a,
+ const std::pair<std::shared_ptr<IFactory>, Descriptor>& b) {
+ return a.second.capability.get<Capability::acousticEchoCanceler>()
+ .maxEchoDelayUs <
+ b.second.capability.get<Capability::acousticEchoCanceler>()
+ .maxEchoDelayUs;
+ });
+ if (max == kFactoryDescList.end()) {
+ return {0};
+ }
+ int maxDelay =
+ max->second.capability.get<Capability::acousticEchoCanceler>().maxEchoDelayUs;
+ return {-1, 0, maxDelay - 1, maxDelay, maxDelay + 1};
+ }
+
+ private:
+ std::vector<std::pair<AcousticEchoCanceler::Tag, AcousticEchoCanceler>> mTags;
+ void CleanUp() { mTags.clear(); }
+};
+
+const std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> AECParamTest::kFactoryDescList =
+ EffectFactoryHelper::getAllEffectDescriptors(IFactory::descriptor,
+ kAcousticEchoCancelerTypeUUID);
+const std::vector<int> AECParamTest::kEchoDelayValues = AECParamTest::getEchoDelayTestValues();
+const std::vector<bool> 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<AECParamTest::ParamType>& info) {
+ auto descriptor = std::get<PARAM_INSTANCE_NAME>(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 0000000..ea3654f
--- /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 <aidl/Vintf.h>
+
+#define LOG_TAG "VtsHalAGCParamTest"
+
+#include <Utils.h>
+#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<std::pair<std::shared_ptr<IFactory>, Descriptor>, int /* gain */,
+ int /* margin */, AutomaticGainControl::LevelEstimator>;
+
+class AGCParamTest : public ::testing::TestWithParam<AGCParamTestParam>, public EffectHelper {
+ public:
+ AGCParamTest()
+ : mGain(std::get<PARAM_DIGITAL_GAIN>(GetParam())),
+ mMargin(std::get<PARAM_SATURATION_MARGIN>(GetParam())),
+ mLevelEstimator(std::get<PARAM_LEVEL_ESTIMATOR>(GetParam())) {
+ std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(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<AutomaticGainControl::fixedDigitalGainMb>(0);
+ Parameter::Specific specific =
+ Parameter::Specific::make<Parameter::Specific::automaticGainControl>(AGC);
+ return specific;
+ }
+
+ static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+ static const std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> kFactoryDescList;
+ static const std::vector<int> kDigitalGainValues;
+ static const std::vector<int> kSaturationMarginValues;
+ static const std::vector<AutomaticGainControl::LevelEstimator> kLevelEstimatorValues;
+
+ std::shared_ptr<IFactory> mFactory;
+ std::shared_ptr<IEffect> 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<Parameter::Specific::automaticGainControl>(AGC);
+ expectParam.set<Parameter::specific>(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<AutomaticGainControl::Id::commonTag>(tag);
+ id.set<Parameter::Id::automaticGainControlTag>(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<AutomaticGainControl::fixedDigitalGainMb>(gain);
+ mTags.push_back({AutomaticGainControl::fixedDigitalGainMb, AGC});
+ }
+ void addSaturationMarginParam(int margin) {
+ AutomaticGainControl AGC;
+ AGC.set<AutomaticGainControl::saturationMarginMb>(margin);
+ mTags.push_back({AutomaticGainControl::saturationMarginMb, AGC});
+ }
+ void addLevelEstimatorParam(AutomaticGainControl::LevelEstimator levelEstimator) {
+ AutomaticGainControl AGC;
+ AGC.set<AutomaticGainControl::levelEstimator>(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<Capability::automaticGainControl>();
+ switch (tag) {
+ case AutomaticGainControl::fixedDigitalGainMb: {
+ auto gain = AGC.get<AutomaticGainControl::fixedDigitalGainMb>();
+ return gain >= 0 && gain <= AGCCap.maxFixedDigitalGainMb;
+ }
+ case AutomaticGainControl::levelEstimator: {
+ return true;
+ }
+ case AutomaticGainControl::saturationMarginMb: {
+ auto margin = AGC.get<AutomaticGainControl::saturationMarginMb>();
+ return margin >= 0 && margin <= AGCCap.maxSaturationMarginMb;
+ }
+ default:
+ return false;
+ }
+ }
+ static std::vector<int> getDigitalGainValues() {
+ const auto max = std::max_element(
+ kFactoryDescList.begin(), kFactoryDescList.end(),
+ [](const std::pair<std::shared_ptr<IFactory>, Descriptor>& a,
+ const std::pair<std::shared_ptr<IFactory>, Descriptor>& b) {
+ return a.second.capability.get<Capability::automaticGainControl>()
+ .maxFixedDigitalGainMb <
+ b.second.capability.get<Capability::automaticGainControl>()
+ .maxFixedDigitalGainMb;
+ });
+ if (max == kFactoryDescList.end()) {
+ return {0};
+ }
+ int maxGain = max->second.capability.get<Capability::automaticGainControl>()
+ .maxFixedDigitalGainMb;
+ return {-1, 0, maxGain - 1, maxGain, maxGain + 1};
+ }
+ static std::vector<int> getSaturationMarginValues() {
+ const auto max = std::max_element(
+ kFactoryDescList.begin(), kFactoryDescList.end(),
+ [](const std::pair<std::shared_ptr<IFactory>, Descriptor>& a,
+ const std::pair<std::shared_ptr<IFactory>, Descriptor>& b) {
+ return a.second.capability.get<Capability::automaticGainControl>()
+ .maxSaturationMarginMb <
+ b.second.capability.get<Capability::automaticGainControl>()
+ .maxSaturationMarginMb;
+ });
+ if (max == kFactoryDescList.end()) {
+ return {0};
+ }
+ int maxMargin = max->second.capability.get<Capability::automaticGainControl>()
+ .maxSaturationMarginMb;
+ return {-1, 0, maxMargin - 1, maxMargin, maxMargin + 1};
+ }
+
+ private:
+ std::vector<std::pair<AutomaticGainControl::Tag, AutomaticGainControl>> mTags;
+ void CleanUp() { mTags.clear(); }
+};
+
+const std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> AGCParamTest::kFactoryDescList =
+ EffectFactoryHelper::getAllEffectDescriptors(IFactory::descriptor,
+ kAutomaticGainControlTypeUUID);
+const std::vector<int> AGCParamTest::kDigitalGainValues = AGCParamTest::getDigitalGainValues();
+const std::vector<int> AGCParamTest::kSaturationMarginValues =
+ AGCParamTest::getSaturationMarginValues();
+const std::vector<AutomaticGainControl::LevelEstimator> 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<AGCParamTest::ParamType>& info) {
+ auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
+ std::string gain = std::to_string(std::get<PARAM_DIGITAL_GAIN>(info.param));
+ std::string estimator = aidl::android::hardware::audio::effect::toString(
+ std::get<PARAM_LEVEL_ESTIMATOR>(info.param));
+ std::string margin =
+ std::to_string(static_cast<int>(std::get<PARAM_SATURATION_MARGIN>(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 0000000..186cb68
--- /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 <aidl/Vintf.h>
+
+#define LOG_TAG "VtsHalNSParamTest"
+
+#include <Utils.h>
+#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<std::pair<std::shared_ptr<IFactory>, Descriptor>, NoiseSuppression::Level>;
+
+class NSParamTest : public ::testing::TestWithParam<NSParamTestParam>, public EffectHelper {
+ public:
+ NSParamTest() : mLevel(std::get<PARAM_LEVEL>(GetParam())) {
+ std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(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>(NoiseSuppression::Level::MEDIUM);
+ Parameter::Specific specific =
+ Parameter::Specific::make<Parameter::Specific::noiseSuppression>(ns);
+ return specific;
+ }
+
+ static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+ static const std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> kFactoryDescList;
+ static const std::vector<NoiseSuppression::Level> kLevelValues;
+
+ std::shared_ptr<IFactory> mFactory;
+ std::shared_ptr<IEffect> 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<Parameter::Specific::noiseSuppression>(ns);
+ expectParam.set<Parameter::specific>(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<NoiseSuppression::Id::commonTag>(tag);
+ id.set<Parameter::Id::noiseSuppressionTag>(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<NoiseSuppression::level>(level);
+ mTags.push_back({NoiseSuppression::level, ns});
+ }
+
+ private:
+ std::vector<std::pair<NoiseSuppression::Tag, NoiseSuppression>> mTags;
+ void CleanUp() { mTags.clear(); }
+};
+
+const std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> kFactoryDescList =
+ EffectFactoryHelper::getAllEffectDescriptors(IFactory::descriptor,
+ kNoiseSuppressionTypeUUID);
+const std::vector<NoiseSuppression::Level> 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<NSParamTest::ParamType>& info) {
+ auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
+ std::string level = aidl::android::hardware::audio::effect::toString(
+ std::get<PARAM_LEVEL>(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