Merge "CAS: Add missing @hide annotations"
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
index 05c7649..42a4ac1 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -41,6 +41,7 @@
"android/hardware/audio/common/SinkMetadata.aidl",
"android/hardware/audio/common/SourceMetadata.aidl",
],
+ frozen: true,
imports: [
"android.media.audio.common.types-V2",
],
@@ -113,7 +114,9 @@
"android/hardware/audio/core/AudioRoute.aidl",
"android/hardware/audio/core/IConfig.aidl",
"android/hardware/audio/core/IModule.aidl",
+ "android/hardware/audio/core/ISoundDose.aidl",
"android/hardware/audio/core/IStreamCallback.aidl",
+ "android/hardware/audio/core/IStreamCommon.aidl",
"android/hardware/audio/core/IStreamIn.aidl",
"android/hardware/audio/core/IStreamOut.aidl",
"android/hardware/audio/core/ITelephony.aidl",
@@ -123,11 +126,13 @@
"android/hardware/audio/core/ModuleDebug.aidl",
"android/hardware/audio/core/StreamDescriptor.aidl",
"android/hardware/audio/core/SurroundSoundConfig.aidl",
+ "android/hardware/audio/core/VendorParameter.aidl",
],
imports: [
"android.hardware.common-V2",
"android.hardware.common.fmq-V1",
"android.hardware.audio.common-V1",
+ "android.hardware.audio.effect-V1",
"android.media.audio.common.types-V2",
],
backend: {
@@ -165,12 +170,61 @@
],
}
+// Used for the standalone sounddose HAL
+aidl_interface {
+ name: "android.hardware.audio.core.sounddose",
+ defaults: [
+ "android.hardware.audio_defaults",
+ ],
+ srcs: [
+ "android/hardware/audio/core/ISoundDose.aidl",
+ ],
+ imports: [
+ "android.media.audio.common.types-V2",
+ ],
+ backend: {
+ // The C++ backend is disabled transitively due to use of FMQ by the core HAL.
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ sdk_version: "module_current",
+ },
+ },
+ versions_with_info: [
+ // IMPORTANT: Update latest_android_hardware_audio_core_sounddose every time you
+ // add the latest frozen version to versions_with_info
+ ],
+}
+
+// Note: This should always be one version ahead of the last frozen version
+latest_android_hardware_audio_core_sounddose = "android.hardware.audio.core.sounddose-V1"
+
+// Modules that depend on android.hardware.audio.core.sounddose directly can include
+// the following cc_defaults to avoid explicitly managing dependency versions
+// across many scattered files.
+cc_defaults {
+ name: "latest_android_hardware_audio_core_sounddose_ndk_shared",
+ shared_libs: [
+ latest_android_hardware_audio_core_sounddose + "-ndk",
+ ],
+}
+
+cc_defaults {
+ name: "latest_android_hardware_audio_core_sounddose_ndk_static",
+ static_libs: [
+ latest_android_hardware_audio_core_sounddose + "-ndk",
+ ],
+}
+
aidl_interface {
name: "android.hardware.audio.effect",
defaults: [
"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",
@@ -184,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 484320f..a2c7966 100644
--- a/audio/aidl/TEST_MAPPING
+++ b/audio/aidl/TEST_MAPPING
@@ -10,10 +10,31 @@
"name": "VtsHalAudioEffectTargetTest"
},
{
+ "name": "VtsHalDownmixTargetTest"
+ },
+ {
+ "name": "VtsHalEnvironmentalReverbTargetTest"
+ },
+ {
"name": "VtsHalEqualizerTargetTest"
},
{
+ "name": "VtsHalHapticGeneratorTargetTest"
+ },
+ {
"name": "VtsHalLoudnessEnhancerTargetTest"
+ },
+ {
+ "name": "VtsHalVisualizerTargetTest"
+ },
+ {
+ "name": "VtsHalAECTargetTest"
+ },
+ {
+ "name": "VtsHalAGCTargetTest"
+ },
+ {
+ "name": "VtsHalNSTargetTest"
}
]
}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core.sounddose/current/android/hardware/audio/core/ISoundDose.aidl b/audio/aidl/aidl_api/android.hardware.audio.core.sounddose/current/android/hardware/audio/core/ISoundDose.aidl
new file mode 100644
index 0000000..bc010ca
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core.sounddose/current/android/hardware/audio/core/ISoundDose.aidl
@@ -0,0 +1,52 @@
+/*
+ * 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.core;
+@VintfStability
+interface ISoundDose {
+ void setOutputRs2(float rs2ValueDbA);
+ float getOutputRs2();
+ void registerSoundDoseCallback(in android.hardware.audio.core.ISoundDose.IHalSoundDoseCallback callback);
+ const int DEFAULT_MAX_RS2 = 100;
+ const int MIN_RS2 = 80;
+ @VintfStability
+ interface IHalSoundDoseCallback {
+ oneway void onMomentaryExposureWarning(float currentDbA, in android.media.audio.common.AudioDevice audioDevice);
+ oneway void onNewMelValues(in android.hardware.audio.core.ISoundDose.IHalSoundDoseCallback.MelRecord melRecord, in android.media.audio.common.AudioDevice audioDevice);
+ @VintfStability
+ parcelable MelRecord {
+ float[] melValues;
+ long timestamp;
+ }
+ }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl
index 0c7ca27..dd2279d 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl
@@ -60,6 +60,12 @@
void updateAudioMode(android.hardware.audio.core.AudioMode mode);
void updateScreenRotation(android.hardware.audio.core.IModule.ScreenRotation rotation);
void updateScreenState(boolean isTurnedOn);
+ @nullable android.hardware.audio.core.ISoundDose getSoundDose();
+ int generateHwAvSyncId();
+ android.hardware.audio.core.VendorParameter[] getVendorParameters(in @utf8InCpp String[] ids);
+ void setVendorParameters(in android.hardware.audio.core.VendorParameter[] parameters, boolean async);
+ void addDeviceEffect(int portConfigId, in android.hardware.audio.effect.IEffect effect);
+ void removeDeviceEffect(int portConfigId, in android.hardware.audio.effect.IEffect effect);
@VintfStability
parcelable OpenInputStreamArguments {
int portConfigId;
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/ISoundDose.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/ISoundDose.aidl
new file mode 100644
index 0000000..bc010ca
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/ISoundDose.aidl
@@ -0,0 +1,52 @@
+/*
+ * 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.core;
+@VintfStability
+interface ISoundDose {
+ void setOutputRs2(float rs2ValueDbA);
+ float getOutputRs2();
+ void registerSoundDoseCallback(in android.hardware.audio.core.ISoundDose.IHalSoundDoseCallback callback);
+ const int DEFAULT_MAX_RS2 = 100;
+ const int MIN_RS2 = 80;
+ @VintfStability
+ interface IHalSoundDoseCallback {
+ oneway void onMomentaryExposureWarning(float currentDbA, in android.media.audio.common.AudioDevice audioDevice);
+ oneway void onNewMelValues(in android.hardware.audio.core.ISoundDose.IHalSoundDoseCallback.MelRecord melRecord, in android.media.audio.common.AudioDevice audioDevice);
+ @VintfStability
+ parcelable MelRecord {
+ float[] melValues;
+ long timestamp;
+ }
+ }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamCommon.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamCommon.aidl
new file mode 100644
index 0000000..f0bf100
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamCommon.aidl
@@ -0,0 +1,43 @@
+/*
+ * 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.core;
+@VintfStability
+interface IStreamCommon {
+ void close();
+ void updateHwAvSyncId(int hwAvSyncId);
+ android.hardware.audio.core.VendorParameter[] getVendorParameters(in @utf8InCpp String[] ids);
+ void setVendorParameters(in android.hardware.audio.core.VendorParameter[] parameters, boolean async);
+ void addEffect(in android.hardware.audio.effect.IEffect effect);
+ void removeEffect(in android.hardware.audio.effect.IEffect effect);
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamIn.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamIn.aidl
index e9c727f..68f1ff3 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamIn.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamIn.aidl
@@ -34,16 +34,20 @@
package android.hardware.audio.core;
@VintfStability
interface IStreamIn {
- void close();
+ android.hardware.audio.core.IStreamCommon getStreamCommon();
android.hardware.audio.core.MicrophoneDynamicInfo[] getActiveMicrophones();
android.hardware.audio.core.IStreamIn.MicrophoneDirection getMicrophoneDirection();
void setMicrophoneDirection(android.hardware.audio.core.IStreamIn.MicrophoneDirection direction);
float getMicrophoneFieldDimension();
void setMicrophoneFieldDimension(float zoom);
void updateMetadata(in android.hardware.audio.common.SinkMetadata sinkMetadata);
+ float[] getHwGain();
+ void setHwGain(in float[] channelGains);
const int MIC_FIELD_DIMENSION_WIDE_ANGLE = -1;
const int MIC_FIELD_DIMENSION_NO_ZOOM = 0;
const int MIC_FIELD_DIMENSION_MAX_ZOOM = 1;
+ const int HW_GAIN_MIN = 0;
+ const int HW_GAIN_MAX = 1;
@Backing(type="int") @VintfStability
enum MicrophoneDirection {
UNSPECIFIED = 0,
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamOut.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamOut.aidl
index 3021d94..092b801 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamOut.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamOut.aidl
@@ -34,6 +34,10 @@
package android.hardware.audio.core;
@VintfStability
interface IStreamOut {
- void close();
+ android.hardware.audio.core.IStreamCommon getStreamCommon();
void updateMetadata(in android.hardware.audio.common.SourceMetadata sourceMetadata);
+ float[] getHwVolume();
+ void setHwVolume(in float[] channelVolumes);
+ const int HW_VOLUME_MIN = 0;
+ const int HW_VOLUME_MAX = 1;
}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/VendorParameter.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/VendorParameter.aidl
new file mode 100644
index 0000000..bfe33ee
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/VendorParameter.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.core;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable VendorParameter {
+ @utf8InCpp String id;
+ ParcelableHolder ext;
+}
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/EnvironmentalReverb.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/EnvironmentalReverb.aidl
index fcf08c3..0e61932 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/EnvironmentalReverb.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/EnvironmentalReverb.aidl
@@ -44,6 +44,22 @@
int diffusionPm;
int densityPm;
boolean bypass;
+ const int MIN_ROOM_LEVEL_MB = -6000;
+ const int MAX_ROOM_LEVEL_MB = 0;
+ const int MIN_ROOM_HF_LEVEL_MB = -4000;
+ const int MAX_ROOM_HF_LEVEL_MB = 0;
+ const int MIN_DECAY_TIME_MS = 100;
+ const int MAX_DECAY_TIME_MS = 20000;
+ const int MIN_DECAY_HF_RATIO_PM = 100;
+ const int MAX_DECAY_HF_RATIO_PM = 1000;
+ const int MIN_LEVEL_MB = -6000;
+ const int MAX_LEVEL_MB = 0;
+ const int MIN_DELAY_MS = 0;
+ const int MAX_DELAY_MS = 65;
+ const int MIN_DIFFUSION_PM = 0;
+ const int MAX_DIFFUSION_PM = 1000;
+ const int MIN_DENSITY_PM = 0;
+ const int MAX_DENSITY_PM = 1000;
@VintfStability
union Id {
int vendorExtensionTag;
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/core/IModule.aidl b/audio/aidl/android/hardware/audio/core/IModule.aidl
index 786d5ee..b278ac4 100644
--- a/audio/aidl/android/hardware/audio/core/IModule.aidl
+++ b/audio/aidl/android/hardware/audio/core/IModule.aidl
@@ -21,6 +21,7 @@
import android.hardware.audio.core.AudioMode;
import android.hardware.audio.core.AudioPatch;
import android.hardware.audio.core.AudioRoute;
+import android.hardware.audio.core.ISoundDose;
import android.hardware.audio.core.IStreamCallback;
import android.hardware.audio.core.IStreamIn;
import android.hardware.audio.core.IStreamOut;
@@ -28,6 +29,8 @@
import android.hardware.audio.core.MicrophoneInfo;
import android.hardware.audio.core.ModuleDebug;
import android.hardware.audio.core.StreamDescriptor;
+import android.hardware.audio.core.VendorParameter;
+import android.hardware.audio.effect.IEffect;
import android.media.audio.common.AudioOffloadInfo;
import android.media.audio.common.AudioPort;
import android.media.audio.common.AudioPortConfig;
@@ -513,7 +516,8 @@
* @throws EX_ILLEGAL_ARGUMENT If the port config can not be found by the ID.
* @throws EX_ILLEGAL_STATE In the following cases:
* - If the port config has a stream opened on it;
- * - If the port config is used by a patch.
+ * - If the port config is used by a patch;
+ * - If the port config has an audio effect on it.
*/
void resetAudioPortConfig(int portConfigId);
@@ -668,4 +672,92 @@
* @param isTurnedOn True if the screen is turned on.
*/
void updateScreenState(boolean isTurnedOn);
+
+ /**
+ * Retrieve the sound dose interface.
+ *
+ * If a device must comply to IEC62368-1 3rd edition audio safety requirements and is
+ * implementing audio offload decoding or other direct playback paths where volume control
+ * happens below the audio HAL, it must return an instance of the ISoundDose interface.
+ * The same instance must be returned during the lifetime of the HAL module.
+ * If the HAL module does not support sound dose, null must be returned, without throwing
+ * any errors.
+ *
+ * @return An instance of the ISoundDose interface implementation.
+ * @throws EX_ILLEGAL_STATE If there was an error creating an instance.
+ */
+ @nullable ISoundDose getSoundDose();
+
+ /**
+ * Generate a HW AV Sync identifier for a new audio session.
+ *
+ * Creates a new unique identifier which can be further used by the client
+ * for tagging input / output streams that belong to the same audio
+ * session and thus must use the same HW AV Sync timestamps sequence.
+ *
+ * HW AV Sync timestamps are used for "tunneled" I/O modes and thus
+ * are not mandatory.
+ *
+ * @throws EX_ILLEGAL_STATE If the identifier can not be provided at the moment.
+ * @throws EX_UNSUPPORTED_OPERATION If synchronization with HW AV Sync markers
+ * is not supported.
+ */
+ int generateHwAvSyncId();
+
+ /**
+ * Get current values of vendor parameters.
+ *
+ * Return current values for the parameters corresponding to the provided ids.
+ *
+ * @param ids Ids of the parameters to retrieve values of.
+ * @return Current values of parameters, one per each id.
+ * @throws EX_ILLEGAL_ARGUMENT If the module does not recognize provided ids.
+ * @throws EX_ILLEGAL_STATE If parameter values can not be retrieved at the moment.
+ * @throws EX_UNSUPPORTED_OPERATION If the module does not support vendor parameters.
+ */
+ VendorParameter[] getVendorParameters(in @utf8InCpp String[] ids);
+ /**
+ * Set vendor parameters.
+ *
+ * Update values for provided vendor parameters. If the 'async' parameter
+ * is set to 'true', the implementation must return the control back without
+ * waiting for the application of parameters to complete.
+ *
+ * @param parameters Ids and values of parameters to set.
+ * @param async Whether to return from the method as early as possible.
+ * @throws EX_ILLEGAL_ARGUMENT If the module does not recognize provided parameters.
+ * @throws EX_ILLEGAL_STATE If parameters can not be set at the moment.
+ * @throws EX_UNSUPPORTED_OPERATION If the module does not support vendor parameters.
+ */
+ void setVendorParameters(in VendorParameter[] parameters, boolean async);
+
+ /**
+ * Apply an audio effect to a device port.
+ *
+ * The audio effect applies to all audio input or output on the specific
+ * configuration of the device audio port. The effect is inserted according
+ * to its insertion preference specified by the 'flags.insert' field of the
+ * EffectDescriptor.
+ *
+ * @param portConfigId The ID of the audio port config.
+ * @param effect The effect instance.
+ * @throws EX_ILLEGAL_ARGUMENT If the device port config can not be found by the ID,
+ * or the effect reference is invalid.
+ * @throws EX_UNSUPPORTED_OPERATION If the module does not support device port effects.
+ */
+ void addDeviceEffect(int portConfigId, in IEffect effect);
+
+ /**
+ * Stop applying an audio effect to a device port.
+ *
+ * Undo the action of the 'addDeviceEffect' method.
+ *
+ * @param portConfigId The ID of the audio port config.
+ * @param effect The effect instance.
+ * @throws EX_ILLEGAL_ARGUMENT If the device port config can not be found by the ID,
+ * or the effect reference is invalid, or the effect is
+ * not currently applied to the port config.
+ * @throws EX_UNSUPPORTED_OPERATION If the module does not support device port effects.
+ */
+ void removeDeviceEffect(int portConfigId, in IEffect effect);
}
diff --git a/audio/aidl/android/hardware/audio/core/ISoundDose.aidl b/audio/aidl/android/hardware/audio/core/ISoundDose.aidl
new file mode 100644
index 0000000..89fd69b
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/ISoundDose.aidl
@@ -0,0 +1,104 @@
+/*
+ * 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.core;
+
+import android.media.audio.common.AudioDevice;
+
+/**
+ * This interface provides functions related to sound exposure control required for compliance to
+ * EN/IEC 62368-1 3rd edition. Implementing this interface is mandatory for devices for which
+ * compliance to this standard is mandated and implementing audio offload decoding or other direct
+ * playback paths where volume control happens below the audio HAL.
+ */
+@VintfStability
+interface ISoundDose {
+ /**
+ * Max value in dBA used for momentary exposure warnings as defined by IEC62368-1
+ * 3rd edition. This value represents the default RS2 value.
+ */
+ const int DEFAULT_MAX_RS2 = 100;
+ /** Min value of the RS2 threshold in dBA as defined by IEC62368-1 3rd edition. */
+ const int MIN_RS2 = 80;
+
+ /**
+ * Sets the RS2 value used for momentary exposure warnings. Default value is
+ * DEFAULT_MAX_RS2 as specified in IEC62368-1 3rd edition.
+ *
+ * @param rs2ValueDbA custom RS2 value to use. Must not be higher than DEFAULT_MAX_RS2
+ * @throws EX_ILLEGAL_ARGUMENT if rs2ValueDbA is greater than DEFAULT_MAX_RS2 or lower
+ * than 80dBA
+ */
+ void setOutputRs2(float rs2ValueDbA);
+
+ /**
+ * Gets the RS2 value used for momentary exposure warnings.
+ *
+ * @return the RS2 value in dBA
+ */
+ float getOutputRs2();
+
+ /**
+ * Registers the HAL callback for sound dose computation. If sound dose is supported
+ * the MEL values and exposure notifications will be received through this callback
+ * only. The internal framework MEL computation will be disabled.
+ * It is not possible to unregister the callback. The HAL is responsible to provide
+ * the MEL values throughout its lifecycle.
+ * This method should only be called once (no updates allowed) with a valid callback.
+ *
+ * @param callback to use when new updates are available for sound dose
+ * @throws EX_ILLEGAL_STATE if the method is called more than once
+ * @throws EX_ILLEGAL_ARGUMENT if the passed callback is null
+ */
+ void registerSoundDoseCallback(in IHalSoundDoseCallback callback);
+
+ @VintfStability
+ oneway interface IHalSoundDoseCallback {
+ /**
+ * Called whenever the current MEL value exceeds the set RS2 value.
+ *
+ * @param currentDbA the current MEL value which exceeds the RS2 value
+ * @param audioDevice the audio device where the MEL exposure warning was recorded
+ */
+ void onMomentaryExposureWarning(float currentDbA, in AudioDevice audioDevice);
+
+ @VintfStability
+ parcelable MelRecord {
+ /**
+ * Array of continuously recorded MEL values >= RS1 (1 per second).
+ * First value in the array was recorded at 'timestamp'.
+ */
+ float[] melValues;
+ /**
+ * Corresponds to the time in seconds when the first MEL entry in melValues
+ * was recorded. The timestamp values have to be consistent throughout all
+ * audio ports, equal timestamp values will be aggregated.
+ */
+ long timestamp;
+ }
+
+ /**
+ * Provides a MelRecord containing continuous MEL values sorted by timestamp.
+ * Note that all the MEL values originate from the audio device specified by audioDevice.
+ * In case values from multiple devices need to be reported, the caller should execute
+ * this callback once for every device.
+ *
+ * @param melRecord contains the MEL values used for CSD
+ * @param audioDevice the audio device where the MEL values were recorded
+ */
+ void onNewMelValues(in MelRecord melRecord, in AudioDevice audioDevice);
+ }
+}
diff --git a/audio/aidl/android/hardware/audio/core/IStreamCommon.aidl b/audio/aidl/android/hardware/audio/core/IStreamCommon.aidl
new file mode 100644
index 0000000..533ef67
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/IStreamCommon.aidl
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.core;
+
+import android.hardware.audio.core.VendorParameter;
+import android.hardware.audio.effect.IEffect;
+
+/**
+ * This interface contains operations that are common to input and output
+ * streams (IStreamIn and IStreamOut). The lifetime of the server-side
+ * implementation object is the same as of the "parent" IStreamIn/Out object.
+ * The client must release all references to this object together with
+ * references to the "parent" object.
+ */
+@VintfStability
+interface IStreamCommon {
+ /**
+ * Close the stream.
+ *
+ * Releases any resources allocated for this stream on the HAL module side.
+ * This includes the fast message queues and shared memories returned via
+ * the StreamDescriptor. Thus, the stream can not be operated anymore after
+ * it has been closed. The client needs to release the audio data I/O
+ * objects after the call to this method returns.
+ *
+ * Methods of IStream* interfaces throw EX_ILLEGAL_STATE for a closed stream.
+ *
+ * @throws EX_ILLEGAL_STATE If the stream has already been closed.
+ */
+ void close();
+
+ /**
+ * Update the HW AV Sync identifier for the stream.
+ *
+ * The argument to this method must be one of the identifiers previously
+ * returned by the 'IModule.generateHwAvSyncId' method. By tagging streams
+ * with the same identifier, the client indicates to the HAL that they all
+ * use the same HW AV Sync timestamps sequence.
+ *
+ * HW AV Sync timestamps are used for "tunneled" I/O modes and thus
+ * are not mandatory.
+ *
+ * @throws EX_ILLEGAL_ARGUMENT If the provided ID is unknown to the HAL module.
+ * @throws EX_ILLEGAL_STATE If the stream is closed.
+ * @throws EX_UNSUPPORTED_OPERATION If synchronization with HW AV Sync markers
+ * is not supported.
+ */
+ void updateHwAvSyncId(int hwAvSyncId);
+
+ /**
+ * Get current values of vendor parameters.
+ *
+ * Return current values for the parameters corresponding to the provided ids.
+ *
+ * @param ids Ids of the parameters to retrieve values of.
+ * @return Current values of parameters.
+ * @throws EX_ILLEGAL_ARGUMENT If the stream does not recognize provided ids.
+ * @throws EX_ILLEGAL_STATE If parameter values can not be retrieved at the moment.
+ * @throws EX_UNSUPPORTED_OPERATION If the stream does not support vendor parameters.
+ */
+ VendorParameter[] getVendorParameters(in @utf8InCpp String[] ids);
+ /**
+ * Set vendor parameters.
+ *
+ * Update values for provided vendor parameters. If the 'async' parameter
+ * is set to 'true', the implementation must return the control back without
+ * waiting for the application of parameters to complete.
+ *
+ * @param parameters Ids and values of parameters to set.
+ * @param async Whether to return from the method as early as possible.
+ * @throws EX_ILLEGAL_ARGUMENT If the stream does not recognize provided parameters.
+ * @throws EX_ILLEGAL_STATE If parameters can not be set at the moment.
+ * @throws EX_UNSUPPORTED_OPERATION If the stream does not support vendor parameters.
+ */
+ void setVendorParameters(in VendorParameter[] parameters, boolean async);
+
+ /**
+ * Apply an audio effect to the stream.
+ *
+ * This method is intended for the cases when the effect has an offload
+ * implementation, since software effects can be applied at the client side.
+ *
+ * @param effect The effect instance.
+ * @throws EX_ILLEGAL_ARGUMENT If the effect reference is invalid.
+ * @throws EX_ILLEGAL_STATE If the stream is closed.
+ * @throws EX_UNSUPPORTED_OPERATION If the module does not support audio effects.
+ */
+ void addEffect(in IEffect effect);
+
+ /**
+ * Stop applying an audio effect to the stream.
+ *
+ * Undo the action of the 'addEffect' method.
+ *
+ * @param effect The effect instance.
+ * @throws EX_ILLEGAL_ARGUMENT If the effect reference is invalid, or the effect is
+ * not currently applied to the stream.
+ * @throws EX_ILLEGAL_STATE If the stream is closed.
+ * @throws EX_UNSUPPORTED_OPERATION If the module does not support audio effects.
+ */
+ void removeEffect(in IEffect effect);
+}
diff --git a/audio/aidl/android/hardware/audio/core/IStreamIn.aidl b/audio/aidl/android/hardware/audio/core/IStreamIn.aidl
index 0b6e02c..c2b3633 100644
--- a/audio/aidl/android/hardware/audio/core/IStreamIn.aidl
+++ b/audio/aidl/android/hardware/audio/core/IStreamIn.aidl
@@ -17,6 +17,7 @@
package android.hardware.audio.core;
import android.hardware.audio.common.SinkMetadata;
+import android.hardware.audio.core.IStreamCommon;
import android.hardware.audio.core.MicrophoneDynamicInfo;
/**
@@ -25,19 +26,15 @@
@VintfStability
interface IStreamIn {
/**
- * Close the stream.
+ * Return the interface for common stream operations.
*
- * Releases any resources allocated for this stream on the HAL module side.
- * This includes the fast message queues and shared memories returned via
- * the StreamDescriptor. Thus, the stream can not be operated anymore after
- * it has been closed. The client needs to release the audio data I/O
- * objects after the call to this method returns.
+ * This method must always succeed. The implementation must
+ * return the same instance object for all subsequent calls to
+ * this method.
*
- * Methods of this interface throw EX_ILLEGAL_STATE for a closed stream.
- *
- * @throws EX_ILLEGAL_STATE If the stream has already been closed.
+ * @return The interface for common operations.
*/
- void close();
+ IStreamCommon getStreamCommon();
/**
* Provides information on the microphones that are active for this stream.
@@ -134,4 +131,38 @@
* @throws EX_ILLEGAL_STATE If the stream is closed.
*/
void updateMetadata(in SinkMetadata sinkMetadata);
+
+ const int HW_GAIN_MIN = 0;
+ const int HW_GAIN_MAX = 1;
+ /**
+ * Retrieve current gain applied in hardware.
+ *
+ * In case when the HAL module has a gain controller, this method returns
+ * the current value of its gain for each input channel.
+ *
+ * The valid range for gain is [0.0f, 1.0f], where 1.0f corresponds to unity
+ * gain, 0.0f corresponds to full mute (see HW_GAIN_* constants).
+ *
+ * @return Current gain values for each input channel.
+ * @throws EX_ILLEGAL_STATE If the stream is closed.
+ * @throws EX_UNSUPPORTED_OPERATION If hardware gain control is not supported.
+ */
+ float[] getHwGain();
+ /**
+ * Set gain applied in hardware.
+ *
+ * In case when the HAL module has a gain controller, this method sets the
+ * current value of its gain for each input channel.
+ *
+ * The valid range for gain is [0.0f, 1.0f], where 1.0f corresponds to unity
+ * gain, 0.0f corresponds to full mute (see HW_GAIN_* constants).
+ *
+ * @param gain Gain values for each input channel.
+ * @throws EX_ILLEGAL_ARGUMENT If the number of elements in the provided
+ * array does not match the channel count, or
+ * gain values are out of range.
+ * @throws EX_ILLEGAL_STATE If the stream is closed.
+ * @throws EX_UNSUPPORTED_OPERATION If hardware gain control is not supported.
+ */
+ void setHwGain(in float[] channelGains);
}
diff --git a/audio/aidl/android/hardware/audio/core/IStreamOut.aidl b/audio/aidl/android/hardware/audio/core/IStreamOut.aidl
index 9fdb37d..85da00d 100644
--- a/audio/aidl/android/hardware/audio/core/IStreamOut.aidl
+++ b/audio/aidl/android/hardware/audio/core/IStreamOut.aidl
@@ -17,6 +17,7 @@
package android.hardware.audio.core;
import android.hardware.audio.common.SourceMetadata;
+import android.hardware.audio.core.IStreamCommon;
/**
* This interface provides means for sending audio data to output devices.
@@ -24,19 +25,15 @@
@VintfStability
interface IStreamOut {
/**
- * Close the stream.
+ * Return the interface for common stream operations.
*
- * Releases any resources allocated for this stream on the HAL module side.
- * This includes the fast message queues and shared memories returned via
- * the StreamDescriptor. Thus, the stream can not be operated anymore after
- * it has been closed. The client needs to release the audio data I/O
- * objects after the call to this method returns.
+ * This method must always succeed. The implementation must
+ * return the same instance object for all subsequent calls to
+ * this method.
*
- * Methods of this interface throw EX_ILLEGAL_STATE for a closed stream.
- *
- * @throws EX_ILLEGAL_STATE If the stream has already been closed.
+ * @return The interface for common operations.
*/
- void close();
+ IStreamCommon getStreamCommon();
/**
* Update stream metadata.
@@ -47,4 +44,46 @@
* @throws EX_ILLEGAL_STATE If the stream is closed.
*/
void updateMetadata(in SourceMetadata sourceMetadata);
+
+ const int HW_VOLUME_MIN = 0;
+ const int HW_VOLUME_MAX = 1;
+ /**
+ * Retrieve current attenuation applied in hardware.
+ *
+ * Hardware attenuation can be used in cases when the client can not, or is
+ * not allowed to modify the audio stream, for example because the stream is
+ * encoded.
+ *
+ * The valid range for attenuation is [0.0f, 1.0f], where 1.0f corresponds
+ * to unity gain, 0.0f corresponds to full mute (see HW_VOLUME_*
+ * constants). The returned array specifies attenuation for each output
+ * channel of the stream.
+ *
+ * Support of hardware volume control is optional.
+ *
+ * @return Current attenuation values for each output channel.
+ * @throws EX_ILLEGAL_STATE If the stream is closed.
+ * @throws EX_UNSUPPORTED_OPERATION If hardware volume control is not supported.
+ */
+ float[] getHwVolume();
+ /**
+ * Set attenuation applied in hardware.
+ *
+ * Hardware attenuation can be used in cases when the client can not, or is
+ * not allowed to modify the audio stream, for example because the stream is
+ * encoded.
+ *
+ * The valid range for attenuation is [0.0f, 1.0f], where 1.0f corresponds
+ * to unity gain, 0.0f corresponds to full mute (see HW_VOLUME_* constants).
+ *
+ * Support of hardware volume control is optional.
+ *
+ * @param channelVolumes Attenuation values for each output channel.
+ * @throws EX_ILLEGAL_ARGUMENT If the number of elements in the provided
+ * array does not match the channel count, or
+ * attenuation values are out of range.
+ * @throws EX_ILLEGAL_STATE If the stream is closed.
+ * @throws EX_UNSUPPORTED_OPERATION If hardware volume control is not supported.
+ */
+ void setHwVolume(in float[] channelVolumes);
}
diff --git a/audio/aidl/android/hardware/audio/core/VendorParameter.aidl b/audio/aidl/android/hardware/audio/core/VendorParameter.aidl
new file mode 100644
index 0000000..206bd9d
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/VendorParameter.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.core;
+
+/**
+ * Vendor parameters are used as a lightweight way to pass vendor-specific
+ * configuration data back and forth between the HAL and vendor's extension
+ * to the Android framework, without the need to extend audio interfaces
+ * from AOSP.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable VendorParameter {
+ /**
+ * Vendor-generated unique ID of the parameter. In order to avoid
+ * collisions, vendors must use a vendor-specific prefix for parameter
+ * ids. The Android framework always passes ids as-is, without any attempt
+ * to parse their content.
+ */
+ @utf8InCpp String id;
+ /**
+ * The payload of the parameter.
+ */
+ ParcelableHolder ext;
+}
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/EnvironmentalReverb.aidl b/audio/aidl/android/hardware/audio/effect/EnvironmentalReverb.aidl
index 3df0d27..81c0dde 100644
--- a/audio/aidl/android/hardware/audio/effect/EnvironmentalReverb.aidl
+++ b/audio/aidl/android/hardware/audio/effect/EnvironmentalReverb.aidl
@@ -56,37 +56,109 @@
}
/**
+ * Minimal possible room level in millibels.
+ */
+ const int MIN_ROOM_LEVEL_MB = -6000;
+ /**
+ * Maximum possible room level in millibels.
+ */
+ const int MAX_ROOM_LEVEL_MB = 0;
+ /**
* Room level apply to the reverb effect in millibels.
*/
int roomLevelMb;
+
+ /**
+ * Minimal possible room hf level in millibels.
+ */
+ const int MIN_ROOM_HF_LEVEL_MB = -4000;
+ /**
+ * Maximum possible room hf level in millibels.
+ */
+ const int MAX_ROOM_HF_LEVEL_MB = 0;
/**
* Room HF level apply to the reverb effect in millibels.
*/
int roomHfLevelMb;
+
+ /**
+ * Minimal possible decay time in milliseconds.
+ */
+ const int MIN_DECAY_TIME_MS = 100;
+ /**
+ * Maximum possible decay time in milliseconds.
+ */
+ const int MAX_DECAY_TIME_MS = 20000;
/**
* Delay time apply to the reverb effect in milliseconds.
*/
int decayTimeMs;
+
+ /**
+ * Minimal possible per mille decay hf ratio.
+ */
+ const int MIN_DECAY_HF_RATIO_PM = 100;
+ /**
+ * Maximum possible per mille decay hf ratio.
+ */
+ const int MAX_DECAY_HF_RATIO_PM = 1000;
/**
* HF decay ratio in permilles.
*/
int decayHfRatioPm;
+
+ /**
+ * Minimal possible room level in millibels.
+ */
+ const int MIN_LEVEL_MB = -6000;
+ /**
+ * Maximum possible room level in millibels.
+ */
+ const int MAX_LEVEL_MB = 0;
/**
* Reverb level in millibels.
*/
int levelMb;
+
+ /**
+ * Minimal possible delay time in milliseconds.
+ */
+ const int MIN_DELAY_MS = 0;
+ /**
+ * Maximum possible delay time in milliseconds.
+ */
+ const int MAX_DELAY_MS = 65;
/**
* Reverb delay in milliseconds.
*/
int delayMs;
+
+ /**
+ * Minimal possible per mille diffusion.
+ */
+ const int MIN_DIFFUSION_PM = 0;
+ /**
+ * Maximum possible per mille diffusion.
+ */
+ const int MAX_DIFFUSION_PM = 1000;
/**
* Diffusion in permilles.
*/
int diffusionPm;
+
+ /**
+ * Minimal possible per mille density.
+ */
+ const int MIN_DENSITY_PM = 0;
+ /**
+ * Maximum possible per mille density.
+ */
+ const int MAX_DENSITY_PM = 1000;
/**
* Density in permilles.
*/
int densityPm;
+
/**
* Bypass reverb and copy input to output if set to true.
*/
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/Android.bp b/audio/aidl/default/Android.bp
index f2cebbf..a938551 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -29,6 +29,29 @@
],
}
+cc_library {
+ name: "libaudioservicesounddoseimpl",
+ vendor: true,
+ defaults: [
+ "latest_android_media_audio_common_types_ndk_shared",
+ "latest_android_hardware_audio_core_sounddose_ndk_shared",
+ "latest_android_hardware_audio_sounddose_ndk_shared",
+ ],
+ export_include_dirs: ["include"],
+ srcs: [
+ "SoundDose.cpp",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libcutils",
+ "libutils",
+ ],
+ visibility: [
+ "//hardware/interfaces/audio/aidl/sounddose/default",
+ ],
+}
+
cc_library_static {
name: "libaudioserviceexampleimpl",
defaults: [
@@ -43,6 +66,7 @@
"Configuration.cpp",
"EngineConfigXmlConverter.cpp",
"Module.cpp",
+ "SoundDose.cpp",
"Stream.cpp",
"Telephony.cpp",
],
@@ -127,11 +151,12 @@
shared_libs: [
"libbassboostsw",
"libbundleaidl",
+ "libdownmixaidl",
"libdynamicsprocessingsw",
"libenvreverbsw",
"libequalizersw",
"libhapticgeneratorsw",
- "libloudnessenhancersw",
+ "libloudnessenhanceraidl",
"libpresetreverbsw",
"libtinyxml2",
"libvirtualizersw",
diff --git a/audio/aidl/default/EffectFactory.cpp b/audio/aidl/default/EffectFactory.cpp
index 7ae9a66..3b40ae0 100644
--- a/audio/aidl/default/EffectFactory.cpp
+++ b/audio/aidl/default/EffectFactory.cpp
@@ -40,12 +40,13 @@
}
Factory::~Factory() {
- if (auto count = mEffectUuidMap.size()) {
+ if (auto count = mEffectMap.size()) {
LOG(ERROR) << __func__ << " remaining " << count
<< " effect instances not destroyed indicating resource leak!";
- for (const auto& it : mEffectUuidMap) {
+ for (const auto& it : mEffectMap) {
if (auto spEffect = it.first.lock()) {
- LOG(ERROR) << __func__ << " erase remaining instance UUID " << it.second.toString();
+ LOG(ERROR) << __func__ << " erase remaining instance UUID "
+ << it.second.first.toString();
destroyEffectImpl(spEffect);
}
}
@@ -109,9 +110,10 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
}
*_aidl_return = effectSp;
- AIBinder_setMinSchedulerPolicy(effectSp->asBinder().get(), SCHED_NORMAL,
- ANDROID_PRIORITY_AUDIO);
- mEffectUuidMap[std::weak_ptr<IEffect>(effectSp)] = in_impl_uuid;
+ ndk::SpAIBinder effectBinder = effectSp->asBinder();
+ AIBinder_setMinSchedulerPolicy(effectBinder.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
+ mEffectMap[std::weak_ptr<IEffect>(effectSp)] =
+ std::make_pair(in_impl_uuid, std::move(effectBinder));
LOG(DEBUG) << __func__ << ": instance " << effectSp.get() << " created successfully";
return ndk::ScopedAStatus::ok();
} else {
@@ -123,9 +125,9 @@
ndk::ScopedAStatus Factory::destroyEffectImpl(const std::shared_ptr<IEffect>& in_handle) {
std::weak_ptr<IEffect> wpHandle(in_handle);
- // find UUID with key (std::weak_ptr<IEffect>)
- if (auto uuidIt = mEffectUuidMap.find(wpHandle); uuidIt != mEffectUuidMap.end()) {
- auto& uuid = uuidIt->second;
+ // find the effect entry with key (std::weak_ptr<IEffect>)
+ if (auto effectIt = mEffectMap.find(wpHandle); effectIt != mEffectMap.end()) {
+ auto& uuid = effectIt->second.first;
// find implementation library with UUID
if (auto libIt = mEffectLibMap.find(uuid); libIt != mEffectLibMap.end()) {
auto& interface = std::get<kMapEntryInterfaceIndex>(libIt->second);
@@ -136,7 +138,7 @@
LOG(ERROR) << __func__ << ": UUID " << uuid.toString() << " does not exist in libMap!";
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
- mEffectUuidMap.erase(uuidIt);
+ mEffectMap.erase(effectIt);
return ndk::ScopedAStatus::ok();
} else {
LOG(ERROR) << __func__ << ": instance " << in_handle << " does not exist!";
@@ -146,9 +148,9 @@
// go over the map and cleanup all expired weak_ptrs.
void Factory::cleanupEffectMap() {
- for (auto it = mEffectUuidMap.begin(); it != mEffectUuidMap.end();) {
+ for (auto it = mEffectMap.begin(); it != mEffectMap.end();) {
if (nullptr == it->first.lock()) {
- it = mEffectUuidMap.erase(it);
+ it = mEffectMap.erase(it);
} else {
++it;
}
diff --git a/audio/aidl/default/EngineConfigXmlConverter.cpp b/audio/aidl/default/EngineConfigXmlConverter.cpp
index 71b4b0e..5f17d71 100644
--- a/audio/aidl/default/EngineConfigXmlConverter.cpp
+++ b/audio/aidl/default/EngineConfigXmlConverter.cpp
@@ -20,7 +20,9 @@
#include <functional>
#include <unordered_map>
+#include <aidl/android/media/audio/common/AudioFlag.h>
#include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
+#include <aidl/android/media/audio/common/AudioProductStrategyType.h>
#include "core-impl/EngineConfigXmlConverter.h"
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 47d6fa4..4a424bd 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -26,6 +26,7 @@
#include <aidl/android/media/audio/common/AudioOutputFlags.h>
#include "core-impl/Module.h"
+#include "core-impl/SoundDose.h"
#include "core-impl/Telephony.h"
#include "core-impl/utils.h"
@@ -315,7 +316,8 @@
ndk::ScopedAStatus Module::getTelephony(std::shared_ptr<ITelephony>* _aidl_return) {
if (mTelephony == nullptr) {
mTelephony = ndk::SharedRefBase::make<Telephony>();
- AIBinder_setMinSchedulerPolicy(mTelephony->asBinder().get(), SCHED_NORMAL,
+ mTelephonyBinder = mTelephony->asBinder();
+ AIBinder_setMinSchedulerPolicy(mTelephonyBinder.get(), SCHED_NORMAL,
ANDROID_PRIORITY_AUDIO);
}
*_aidl_return = mTelephony;
@@ -530,13 +532,15 @@
return status;
}
context.fillDescriptor(&_aidl_return->desc);
- auto stream = ndk::SharedRefBase::make<StreamIn>(in_args.sinkMetadata, std::move(context),
- mConfig->microphones);
- if (auto status = stream->init(); !status.isOk()) {
+ std::shared_ptr<StreamIn> stream;
+ if (auto status = StreamIn::createInstance(in_args.sinkMetadata, std::move(context),
+ mConfig->microphones, &stream);
+ !status.isOk()) {
return status;
}
- AIBinder_setMinSchedulerPolicy(stream->asBinder().get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
StreamWrapper streamWrapper(stream);
+ AIBinder_setMinSchedulerPolicy(streamWrapper.getBinder().get(), SCHED_NORMAL,
+ ANDROID_PRIORITY_AUDIO);
auto patchIt = mPatches.find(in_args.portConfigId);
if (patchIt != mPatches.end()) {
streamWrapper.setStreamIsConnected(findConnectedDevices(in_args.portConfigId));
@@ -581,13 +585,15 @@
return status;
}
context.fillDescriptor(&_aidl_return->desc);
- auto stream = ndk::SharedRefBase::make<StreamOut>(in_args.sourceMetadata, std::move(context),
- in_args.offloadInfo);
- if (auto status = stream->init(); !status.isOk()) {
+ std::shared_ptr<StreamOut> stream;
+ if (auto status = StreamOut::createInstance(in_args.sourceMetadata, std::move(context),
+ in_args.offloadInfo, &stream);
+ !status.isOk()) {
return status;
}
- AIBinder_setMinSchedulerPolicy(stream->asBinder().get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
StreamWrapper streamWrapper(stream);
+ AIBinder_setMinSchedulerPolicy(streamWrapper.getBinder().get(), SCHED_NORMAL,
+ ANDROID_PRIORITY_AUDIO);
auto patchIt = mPatches.find(in_args.portConfigId);
if (patchIt != mPatches.end()) {
streamWrapper.setStreamIsConnected(findConnectedDevices(in_args.portConfigId));
@@ -931,4 +937,60 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus Module::getSoundDose(std::shared_ptr<ISoundDose>* _aidl_return) {
+ if (mSoundDose == nullptr) {
+ mSoundDose = ndk::SharedRefBase::make<SoundDose>();
+ mSoundDoseBinder = mSoundDose->asBinder();
+ AIBinder_setMinSchedulerPolicy(mSoundDoseBinder.get(), SCHED_NORMAL,
+ ANDROID_PRIORITY_AUDIO);
+ }
+ *_aidl_return = mSoundDose;
+ LOG(DEBUG) << __func__ << ": returning instance of ISoundDose: " << _aidl_return->get();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::generateHwAvSyncId(int32_t* _aidl_return) {
+ LOG(DEBUG) << __func__;
+ (void)_aidl_return;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus Module::getVendorParameters(const std::vector<std::string>& in_ids,
+ std::vector<VendorParameter>* _aidl_return) {
+ LOG(DEBUG) << __func__ << ": id count: " << in_ids.size();
+ (void)_aidl_return;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus Module::setVendorParameters(const std::vector<VendorParameter>& in_parameters,
+ bool in_async) {
+ LOG(DEBUG) << __func__ << ": parameter count " << in_parameters.size()
+ << ", async: " << in_async;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus Module::addDeviceEffect(
+ int32_t in_portConfigId,
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect) {
+ if (in_effect == nullptr) {
+ LOG(DEBUG) << __func__ << ": port id " << in_portConfigId << ", null effect";
+ } else {
+ LOG(DEBUG) << __func__ << ": port id " << in_portConfigId << ", effect Binder "
+ << in_effect->asBinder().get();
+ }
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus Module::removeDeviceEffect(
+ int32_t in_portConfigId,
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect) {
+ if (in_effect == nullptr) {
+ LOG(DEBUG) << __func__ << ": port id " << in_portConfigId << ", null effect";
+ } else {
+ LOG(DEBUG) << __func__ << ": port id " << in_portConfigId << ", effect Binder "
+ << in_effect->asBinder().get();
+ }
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/SoundDose.cpp b/audio/aidl/default/SoundDose.cpp
new file mode 100644
index 0000000..3d222a8
--- /dev/null
+++ b/audio/aidl/default/SoundDose.cpp
@@ -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.
+ */
+
+#define LOG_TAG "AHAL_SoundDose"
+
+#include "core-impl/SoundDose.h"
+
+#include <android-base/logging.h>
+
+namespace aidl::android::hardware::audio::core {
+
+ndk::ScopedAStatus SoundDose::setOutputRs2(float in_rs2ValueDbA) {
+ if (in_rs2ValueDbA < MIN_RS2 || in_rs2ValueDbA > DEFAULT_MAX_RS2) {
+ LOG(ERROR) << __func__ << ": RS2 value is invalid: " << in_rs2ValueDbA;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ mRs2Value = in_rs2ValueDbA;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus SoundDose::getOutputRs2(float* _aidl_return) {
+ *_aidl_return = mRs2Value;
+ LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus SoundDose::registerSoundDoseCallback(
+ const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& in_callback) {
+ if (in_callback.get() == nullptr) {
+ LOG(ERROR) << __func__ << ": Callback is nullptr";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ if (mCallback != nullptr) {
+ LOG(ERROR) << __func__ << ": Sound dose callback was already registered";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+
+ mCallback = in_callback;
+ LOG(DEBUG) << __func__ << ": Registered sound dose callback ";
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index be5887c..bb123a2 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "AHAL_Stream"
#include <android-base/logging.h>
+#include <android/binder_ibinder_platform.h>
#include <utils/SystemClock.h>
#include <Utils.h>
@@ -486,7 +487,7 @@
}
template <class Metadata, class StreamWorker>
-StreamCommon<Metadata, StreamWorker>::~StreamCommon() {
+StreamCommonImpl<Metadata, StreamWorker>::~StreamCommonImpl() {
if (!isClosed()) {
LOG(ERROR) << __func__ << ": stream was not closed prior to destruction, resource leak";
stopWorker();
@@ -495,7 +496,74 @@
}
template <class Metadata, class StreamWorker>
-ndk::ScopedAStatus StreamCommon<Metadata, StreamWorker>::close() {
+void StreamCommonImpl<Metadata, StreamWorker>::createStreamCommon(
+ const std::shared_ptr<StreamCommonInterface>& delegate) {
+ if (mCommon != nullptr) {
+ LOG(FATAL) << __func__ << ": attempting to create the common interface twice";
+ }
+ mCommon = ndk::SharedRefBase::make<StreamCommon>(delegate);
+ mCommonBinder = mCommon->asBinder();
+ AIBinder_setMinSchedulerPolicy(mCommonBinder.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
+}
+
+template <class Metadata, class StreamWorker>
+ndk::ScopedAStatus StreamCommonImpl<Metadata, StreamWorker>::getStreamCommon(
+ std::shared_ptr<IStreamCommon>* _aidl_return) {
+ if (mCommon == nullptr) {
+ LOG(FATAL) << __func__ << ": the common interface was not created";
+ }
+ *_aidl_return = mCommon;
+ LOG(DEBUG) << __func__ << ": returning " << _aidl_return->get()->asBinder().get();
+ return ndk::ScopedAStatus::ok();
+}
+
+template <class Metadata, class StreamWorker>
+ndk::ScopedAStatus StreamCommonImpl<Metadata, StreamWorker>::updateHwAvSyncId(
+ int32_t in_hwAvSyncId) {
+ LOG(DEBUG) << __func__ << ": id " << in_hwAvSyncId;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+template <class Metadata, class StreamWorker>
+ndk::ScopedAStatus StreamCommonImpl<Metadata, StreamWorker>::getVendorParameters(
+ const std::vector<std::string>& in_ids, std::vector<VendorParameter>* _aidl_return) {
+ LOG(DEBUG) << __func__ << ": id count: " << in_ids.size();
+ (void)_aidl_return;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+template <class Metadata, class StreamWorker>
+ndk::ScopedAStatus StreamCommonImpl<Metadata, StreamWorker>::setVendorParameters(
+ const std::vector<VendorParameter>& in_parameters, bool in_async) {
+ LOG(DEBUG) << __func__ << ": parameters count " << in_parameters.size()
+ << ", async: " << in_async;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+template <class Metadata, class StreamWorker>
+ndk::ScopedAStatus StreamCommonImpl<Metadata, StreamWorker>::addEffect(
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect) {
+ if (in_effect == nullptr) {
+ LOG(DEBUG) << __func__ << ": null effect";
+ } else {
+ LOG(DEBUG) << __func__ << ": effect Binder" << in_effect->asBinder().get();
+ }
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+template <class Metadata, class StreamWorker>
+ndk::ScopedAStatus StreamCommonImpl<Metadata, StreamWorker>::removeEffect(
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect) {
+ if (in_effect == nullptr) {
+ LOG(DEBUG) << __func__ << ": null effect";
+ } else {
+ LOG(DEBUG) << __func__ << ": effect Binder" << in_effect->asBinder().get();
+ }
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+template <class Metadata, class StreamWorker>
+ndk::ScopedAStatus StreamCommonImpl<Metadata, StreamWorker>::close() {
LOG(DEBUG) << __func__;
if (!isClosed()) {
stopWorker();
@@ -512,7 +580,7 @@
}
template <class Metadata, class StreamWorker>
-void StreamCommon<Metadata, StreamWorker>::stopWorker() {
+void StreamCommonImpl<Metadata, StreamWorker>::stopWorker() {
if (auto commandMQ = mContext.getCommandMQ(); commandMQ != nullptr) {
LOG(DEBUG) << __func__ << ": asking the worker to exit...";
auto cmd = StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::halReservedExit>(
@@ -529,7 +597,8 @@
}
template <class Metadata, class StreamWorker>
-ndk::ScopedAStatus StreamCommon<Metadata, StreamWorker>::updateMetadata(const Metadata& metadata) {
+ndk::ScopedAStatus StreamCommonImpl<Metadata, StreamWorker>::updateMetadata(
+ const Metadata& metadata) {
LOG(DEBUG) << __func__;
if (!isClosed()) {
mMetadata = metadata;
@@ -539,6 +608,20 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
+// static
+ndk::ScopedAStatus StreamIn::createInstance(const common::SinkMetadata& sinkMetadata,
+ StreamContext context,
+ const std::vector<MicrophoneInfo>& microphones,
+ std::shared_ptr<StreamIn>* result) {
+ auto stream = ndk::SharedRefBase::make<StreamIn>(sinkMetadata, std::move(context), microphones);
+ if (auto status = stream->init(); !status.isOk()) {
+ return status;
+ }
+ stream->createStreamCommon(stream);
+ *result = std::move(stream);
+ return ndk::ScopedAStatus::ok();
+}
+
namespace {
static std::map<AudioDevice, std::string> transformMicrophones(
const std::vector<MicrophoneInfo>& microphones) {
@@ -549,9 +632,9 @@
}
} // namespace
-StreamIn::StreamIn(const SinkMetadata& sinkMetadata, StreamContext context,
+StreamIn::StreamIn(const SinkMetadata& sinkMetadata, StreamContext&& context,
const std::vector<MicrophoneInfo>& microphones)
- : StreamCommon<SinkMetadata, StreamInWorker>(sinkMetadata, std::move(context)),
+ : StreamCommonImpl<SinkMetadata, StreamInWorker>(sinkMetadata, std::move(context)),
mMicrophones(transformMicrophones(microphones)) {
LOG(DEBUG) << __func__;
}
@@ -597,11 +680,48 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
-StreamOut::StreamOut(const SourceMetadata& sourceMetadata, StreamContext context,
+ndk::ScopedAStatus StreamIn::getHwGain(std::vector<float>* _aidl_return) {
+ LOG(DEBUG) << __func__;
+ (void)_aidl_return;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus StreamIn::setHwGain(const std::vector<float>& in_channelGains) {
+ LOG(DEBUG) << __func__ << ": gains " << ::android::internal::ToString(in_channelGains);
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+// static
+ndk::ScopedAStatus StreamOut::createInstance(const SourceMetadata& sourceMetadata,
+ StreamContext context,
+ const std::optional<AudioOffloadInfo>& offloadInfo,
+ std::shared_ptr<StreamOut>* result) {
+ auto stream =
+ ndk::SharedRefBase::make<StreamOut>(sourceMetadata, std::move(context), offloadInfo);
+ if (auto status = stream->init(); !status.isOk()) {
+ return status;
+ }
+ stream->createStreamCommon(stream);
+ *result = std::move(stream);
+ return ndk::ScopedAStatus::ok();
+}
+
+StreamOut::StreamOut(const SourceMetadata& sourceMetadata, StreamContext&& context,
const std::optional<AudioOffloadInfo>& offloadInfo)
- : StreamCommon<SourceMetadata, StreamOutWorker>(sourceMetadata, std::move(context)),
+ : StreamCommonImpl<SourceMetadata, StreamOutWorker>(sourceMetadata, std::move(context)),
mOffloadInfo(offloadInfo) {
LOG(DEBUG) << __func__;
}
+ndk::ScopedAStatus StreamOut::getHwVolume(std::vector<float>* _aidl_return) {
+ LOG(DEBUG) << __func__;
+ (void)_aidl_return;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus StreamOut::setHwVolume(const std::vector<float>& in_channelVolumes) {
+ LOG(DEBUG) << __func__ << ": gains " << ::android::internal::ToString(in_channelVolumes);
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
} // namespace aidl::android::hardware::audio::core
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 f4ac8fe..28a7656 100644
--- a/audio/aidl/default/audio_effects_config.xml
+++ b/audio/aidl/default/audio_effects_config.xml
@@ -28,12 +28,16 @@
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"/>
<library name="dynamics_processingsw" path="libdynamicsprocessingsw.so"/>
<library name="equalizersw" path="libequalizersw.so"/>
<library name="haptic_generatorsw" path="libhapticgeneratorsw.so"/>
- <library name="loudness_enhancersw" path="libloudnessenhancersw.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"/>
@@ -61,11 +65,18 @@
-->
<effects>
- <effect name="bassboost" library="bassboostsw" uuid="fa8181f2-588b-11ed-9b6a-0242ac120002"/>
+ <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"/>
+ </effectProxy>
+ <effect name="downmix" library="downmix" uuid="93f04452-e4fe-41cc-91f9-e475b6d1d69f"/>
<effect name="dynamics_processing" library="dynamics_processingsw" uuid="fa818d78-588b-11ed-9b6a-0242ac120002"/>
<effect name="haptic_generator" library="haptic_generatorsw" uuid="fa819110-588b-11ed-9b6a-0242ac120002"/>
- <effect name="loudness_enhancer" library="loudness_enhancersw" uuid="fa819610-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/bassboost/BassBoostSw.cpp b/audio/aidl/default/bassboost/BassBoostSw.cpp
index 61976c8..8e4779d 100644
--- a/audio/aidl/default/bassboost/BassBoostSw.cpp
+++ b/audio/aidl/default/bassboost/BassBoostSw.cpp
@@ -66,7 +66,7 @@
const Descriptor BassBoostSw::kDescriptor = {
.common = {.id = {.type = kBassBoostTypeUUID,
.uuid = kBassBoostSwImplUUID,
- .proxy = std::nullopt},
+ .proxy = kBassBoostProxyUUID},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
diff --git a/audio/aidl/default/config/audioPolicy/api/current.txt b/audio/aidl/default/config/audioPolicy/api/current.txt
index c0ffe70..ad79a0c 100644
--- a/audio/aidl/default/config/audioPolicy/api/current.txt
+++ b/audio/aidl/default/config/audioPolicy/api/current.txt
@@ -167,6 +167,7 @@
method @NonNull public String getRawName();
enum_constant public static final android.audio.policy.configuration.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_IEC61937;
enum_constant public static final android.audio.policy.configuration.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_NONE;
+ enum_constant public static final android.audio.policy.configuration.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_PCM;
}
public enum AudioFormat {
@@ -280,6 +281,7 @@
enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_INPUT_FLAG_SYNC;
enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_INPUT_FLAG_ULTRASOUND;
enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_INPUT_FLAG_VOIP_TX;
+ enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_BIT_PERFECT;
enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_DIRECT;
diff --git a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
index 2c18a1e..301c969 100644
--- a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
+++ b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
@@ -181,6 +181,7 @@
<xs:enumeration value="AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_SPATIALIZER" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_ULTRASOUND" />
+ <xs:enumeration value="AUDIO_OUTPUT_FLAG_BIT_PERFECT" />
<xs:enumeration value="AUDIO_INPUT_FLAG_FAST" />
<xs:enumeration value="AUDIO_INPUT_FLAG_HW_HOTWORD" />
<xs:enumeration value="AUDIO_INPUT_FLAG_RAW" />
@@ -575,6 +576,7 @@
<xs:restriction base="xs:string">
<xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_NONE"/>
<xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_IEC61937"/>
+ <xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_PCM"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="profile">
diff --git a/audio/aidl/default/downmix/Android.bp b/audio/aidl/default/downmix/Android.bp
new file mode 100644
index 0000000..230b2d8
--- /dev/null
+++ b/audio/aidl/default/downmix/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: "libdownmixsw",
+ defaults: [
+ "aidlaudioeffectservice_defaults",
+ "latest_android_media_audio_common_types_ndk_shared",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ ],
+ srcs: [
+ "DownmixSw.cpp",
+ ":effectCommonFile",
+ ],
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
diff --git a/audio/aidl/default/downmix/DownmixSw.cpp b/audio/aidl/default/downmix/DownmixSw.cpp
new file mode 100644
index 0000000..7bb958d
--- /dev/null
+++ b/audio/aidl/default/downmix/DownmixSw.cpp
@@ -0,0 +1,170 @@
+/*
+ * 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 <cstddef>
+#define LOG_TAG "AHAL_DownmixSw"
+#include <Utils.h>
+#include <algorithm>
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include "DownmixSw.h"
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::DownmixSw;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kDownmixSwImplUUID;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!in_impl_uuid || *in_impl_uuid != kDownmixSwImplUUID) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<DownmixSw>();
+ 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 != kDownmixSwImplUUID) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ *_aidl_return = DownmixSw::kDescriptor;
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string DownmixSw::kEffectName = "DownmixSw";
+const Downmix::Capability DownmixSw::kCapability;
+const Descriptor DownmixSw::kDescriptor = {
+ .common = {.id = {.type = kDownmixTypeUUID,
+ .uuid = kDownmixSwImplUUID,
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL},
+ .name = kEffectName,
+ .implementor = "The Android Open Source Project"},
+ .capability = Capability::make<Capability::downmix>(kCapability)};
+
+ndk::ScopedAStatus DownmixSw::getDescriptor(Descriptor* _aidl_return) {
+ LOG(DEBUG) << __func__ << kDescriptor.toString();
+ *_aidl_return = kDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus DownmixSw::setParameterSpecific(const Parameter::Specific& specific) {
+ RETURN_IF(Parameter::Specific::downmix != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ auto& dmParam = specific.get<Parameter::Specific::downmix>();
+ auto tag = dmParam.getTag();
+
+ switch (tag) {
+ case Downmix::type: {
+ RETURN_IF(mContext->setDmType(dmParam.get<Downmix::type>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setTypeFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "DownmixTagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus DownmixSw::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::downmixTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ auto dmId = id.get<Parameter::Id::downmixTag>();
+ auto dmIdTag = dmId.getTag();
+ switch (dmIdTag) {
+ case Downmix::Id::commonTag:
+ return getParameterDownmix(dmId.get<Downmix::Id::commonTag>(), specific);
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "DownmixTagNotSupported");
+ }
+}
+
+ndk::ScopedAStatus DownmixSw::getParameterDownmix(const Downmix::Tag& tag,
+ Parameter::Specific* specific) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ Downmix dmParam;
+ switch (tag) {
+ case Downmix::type: {
+ dmParam.set<Downmix::type>(mContext->getDmType());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "DownmixTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::downmix>(dmParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> DownmixSw::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ } else {
+ mContext = std::make_shared<DownmixSwContext>(1 /* statusFmqDepth */, common);
+ }
+
+ return mContext;
+}
+
+std::shared_ptr<EffectContext> DownmixSw::getContext() {
+ return mContext;
+}
+
+RetCode DownmixSw::releaseContext() {
+ if (mContext) {
+ mContext.reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status DownmixSw::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};
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/downmix/DownmixSw.h b/audio/aidl/default/downmix/DownmixSw.h
new file mode 100644
index 0000000..51546c1
--- /dev/null
+++ b/audio/aidl/default/downmix/DownmixSw.h
@@ -0,0 +1,75 @@
+/*
+ * 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 DownmixSwContext final : public EffectContext {
+ public:
+ DownmixSwContext(int statusDepth, const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
+ LOG(DEBUG) << __func__;
+ }
+
+ RetCode setDmType(Downmix::Type type) {
+ // TODO : Add implementation to apply new type
+ mType = type;
+ return RetCode::SUCCESS;
+ }
+ Downmix::Type getDmType() const { return mType; }
+
+ private:
+ Downmix::Type mType = Downmix::Type::STRIP;
+};
+
+class DownmixSw final : public EffectImpl {
+ public:
+ static const std::string kEffectName;
+ static const Downmix::Capability kCapability;
+ static const Descriptor kDescriptor;
+ DownmixSw() { LOG(DEBUG) << __func__; }
+ ~DownmixSw() {
+ 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 sample) override;
+
+ private:
+ std::shared_ptr<DownmixSwContext> mContext;
+
+ ndk::ScopedAStatus getParameterDownmix(const Downmix::Tag& tag, Parameter::Specific* specific);
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/envReverb/EnvReverbSw.cpp b/audio/aidl/default/envReverb/EnvReverbSw.cpp
index a107064..9d7159a 100644
--- a/audio/aidl/default/envReverb/EnvReverbSw.cpp
+++ b/audio/aidl/default/envReverb/EnvReverbSw.cpp
@@ -60,7 +60,8 @@
namespace aidl::android::hardware::audio::effect {
const std::string EnvReverbSw::kEffectName = "EnvReverbSw";
-const EnvironmentalReverb::Capability EnvReverbSw::kCapability;
+const EnvironmentalReverb::Capability EnvReverbSw::kCapability = {
+ .maxDecayTimeMs = EnvironmentalReverb::MAX_DECAY_TIME_MS};
const Descriptor EnvReverbSw::kDescriptor = {
.common = {.id = {.type = kEnvReverbTypeUUID,
.uuid = kEnvReverbSwImplUUID,
@@ -82,16 +83,140 @@
RETURN_IF(Parameter::Specific::environmentalReverb != specific.getTag(), EX_ILLEGAL_ARGUMENT,
"EffectNotSupported");
- mSpecificParam = specific.get<Parameter::Specific::environmentalReverb>();
- LOG(DEBUG) << __func__ << " success with: " << specific.toString();
- return ndk::ScopedAStatus::ok();
+ auto& erParam = specific.get<Parameter::Specific::environmentalReverb>();
+ auto tag = erParam.getTag();
+
+ switch (tag) {
+ case EnvironmentalReverb::roomLevelMb: {
+ RETURN_IF(mContext->setErRoomLevel(erParam.get<EnvironmentalReverb::roomLevelMb>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setRoomLevelFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case EnvironmentalReverb::roomHfLevelMb: {
+ RETURN_IF(
+ mContext->setErRoomHfLevel(erParam.get<EnvironmentalReverb::roomHfLevelMb>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setRoomHfLevelFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case EnvironmentalReverb::decayTimeMs: {
+ RETURN_IF(mContext->setErDecayTime(erParam.get<EnvironmentalReverb::decayTimeMs>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setDecayTimeFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case EnvironmentalReverb::decayHfRatioPm: {
+ RETURN_IF(
+ mContext->setErDecayHfRatio(
+ erParam.get<EnvironmentalReverb::decayHfRatioPm>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setDecayHfRatioFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case EnvironmentalReverb::levelMb: {
+ RETURN_IF(mContext->setErLevel(erParam.get<EnvironmentalReverb::levelMb>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setLevelFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case EnvironmentalReverb::delayMs: {
+ RETURN_IF(mContext->setErDelay(erParam.get<EnvironmentalReverb::delayMs>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setDelayFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case EnvironmentalReverb::diffusionPm: {
+ RETURN_IF(mContext->setErDiffusion(erParam.get<EnvironmentalReverb::diffusionPm>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setDiffusionFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case EnvironmentalReverb::densityPm: {
+ RETURN_IF(mContext->setErDensity(erParam.get<EnvironmentalReverb::densityPm>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setDensityFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case EnvironmentalReverb::bypass: {
+ RETURN_IF(mContext->setErBypass(erParam.get<EnvironmentalReverb::bypass>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setBypassFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "EnvironmentalReverbTagNotSupported");
+ }
+ }
}
ndk::ScopedAStatus EnvReverbSw::getParameterSpecific(const Parameter::Id& id,
Parameter::Specific* specific) {
auto tag = id.getTag();
RETURN_IF(Parameter::Id::environmentalReverbTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
- specific->set<Parameter::Specific::environmentalReverb>(mSpecificParam);
+ auto erId = id.get<Parameter::Id::environmentalReverbTag>();
+ auto erIdTag = erId.getTag();
+ switch (erIdTag) {
+ case EnvironmentalReverb::Id::commonTag:
+ return getParameterEnvironmentalReverb(erId.get<EnvironmentalReverb::Id::commonTag>(),
+ specific);
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(erIdTag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "EnvironmentalReverbTagNotSupported");
+ }
+}
+
+ndk::ScopedAStatus EnvReverbSw::getParameterEnvironmentalReverb(const EnvironmentalReverb::Tag& tag,
+ Parameter::Specific* specific) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ EnvironmentalReverb erParam;
+ switch (tag) {
+ case EnvironmentalReverb::roomLevelMb: {
+ erParam.set<EnvironmentalReverb::roomLevelMb>(mContext->getErRoomLevel());
+ break;
+ }
+ case EnvironmentalReverb::roomHfLevelMb: {
+ erParam.set<EnvironmentalReverb::roomHfLevelMb>(mContext->getErRoomHfLevel());
+ break;
+ }
+ case EnvironmentalReverb::decayTimeMs: {
+ erParam.set<EnvironmentalReverb::decayTimeMs>(mContext->getErDecayTime());
+ break;
+ }
+ case EnvironmentalReverb::decayHfRatioPm: {
+ erParam.set<EnvironmentalReverb::decayHfRatioPm>(mContext->getErDecayHfRatio());
+ break;
+ }
+ case EnvironmentalReverb::levelMb: {
+ erParam.set<EnvironmentalReverb::levelMb>(mContext->getErLevel());
+ break;
+ }
+ case EnvironmentalReverb::delayMs: {
+ erParam.set<EnvironmentalReverb::delayMs>(mContext->getErDelay());
+ break;
+ }
+ case EnvironmentalReverb::diffusionPm: {
+ erParam.set<EnvironmentalReverb::diffusionPm>(mContext->getErDiffusion());
+ break;
+ }
+ case EnvironmentalReverb::densityPm: {
+ erParam.set<EnvironmentalReverb::densityPm>(mContext->getErDensity());
+ break;
+ }
+ case EnvironmentalReverb::bypass: {
+ erParam.set<EnvironmentalReverb::bypass>(mContext->getErBypass());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "EnvironmentalReverbTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::environmentalReverb>(erParam);
return ndk::ScopedAStatus::ok();
}
diff --git a/audio/aidl/default/envReverb/EnvReverbSw.h b/audio/aidl/default/envReverb/EnvReverbSw.h
index b8761a6..f521215 100644
--- a/audio/aidl/default/envReverb/EnvReverbSw.h
+++ b/audio/aidl/default/envReverb/EnvReverbSw.h
@@ -32,7 +32,120 @@
: EffectContext(statusDepth, common) {
LOG(DEBUG) << __func__;
}
- // TODO: add specific context here
+
+ RetCode setErRoomLevel(int roomLevel) {
+ if (roomLevel < EnvironmentalReverb::MIN_ROOM_LEVEL_MB ||
+ roomLevel > EnvironmentalReverb::MAX_ROOM_LEVEL_MB) {
+ LOG(ERROR) << __func__ << " invalid roomLevel: " << roomLevel;
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ // TODO : Add implementation to apply new room level
+ mRoomLevel = roomLevel;
+ return RetCode::SUCCESS;
+ }
+ int getErRoomLevel() const { return mRoomLevel; }
+
+ RetCode setErRoomHfLevel(int roomHfLevel) {
+ if (roomHfLevel < EnvironmentalReverb::MIN_ROOM_HF_LEVEL_MB ||
+ roomHfLevel > EnvironmentalReverb::MAX_ROOM_HF_LEVEL_MB) {
+ LOG(ERROR) << __func__ << " invalid roomHfLevel: " << roomHfLevel;
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ // TODO : Add implementation to apply new room HF level
+ mRoomHfLevel = roomHfLevel;
+ return RetCode::SUCCESS;
+ }
+ int getErRoomHfLevel() const { return mRoomHfLevel; }
+
+ RetCode setErDecayTime(int decayTime) {
+ if (decayTime < EnvironmentalReverb::MIN_DECAY_TIME_MS ||
+ decayTime > EnvironmentalReverb::MAX_DECAY_TIME_MS) {
+ LOG(ERROR) << __func__ << " invalid decayTime: " << decayTime;
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ // TODO : Add implementation to apply new decay time
+ mDecayTime = decayTime;
+ return RetCode::SUCCESS;
+ }
+ int getErDecayTime() const { return mDecayTime; }
+
+ RetCode setErDecayHfRatio(int decayHfRatio) {
+ if (decayHfRatio < EnvironmentalReverb::MIN_DECAY_HF_RATIO_PM ||
+ decayHfRatio > EnvironmentalReverb::MAX_DECAY_HF_RATIO_PM) {
+ LOG(ERROR) << __func__ << " invalid decayHfRatio: " << decayHfRatio;
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ // TODO : Add implementation to apply new decay HF ratio
+ mDecayHfRatio = decayHfRatio;
+ return RetCode::SUCCESS;
+ }
+ int getErDecayHfRatio() const { return mDecayHfRatio; }
+
+ RetCode setErLevel(int level) {
+ if (level < EnvironmentalReverb::MIN_LEVEL_MB ||
+ level > EnvironmentalReverb::MAX_LEVEL_MB) {
+ LOG(ERROR) << __func__ << " invalid level: " << level;
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ // TODO : Add implementation to apply new level
+ mLevel = level;
+ return RetCode::SUCCESS;
+ }
+ int getErLevel() const { return mLevel; }
+
+ RetCode setErDelay(int delay) {
+ if (delay < EnvironmentalReverb::MIN_DELAY_MS ||
+ delay > EnvironmentalReverb::MAX_DELAY_MS) {
+ LOG(ERROR) << __func__ << " invalid delay: " << delay;
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ // TODO : Add implementation to apply new delay
+ mDelay = delay;
+ return RetCode::SUCCESS;
+ }
+ int getErDelay() const { return mDelay; }
+
+ RetCode setErDiffusion(int diffusion) {
+ if (diffusion < EnvironmentalReverb::MIN_DIFFUSION_PM ||
+ diffusion > EnvironmentalReverb::MAX_DIFFUSION_PM) {
+ LOG(ERROR) << __func__ << " invalid diffusion: " << diffusion;
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ // TODO : Add implementation to apply new diffusion
+ mDiffusion = diffusion;
+ return RetCode::SUCCESS;
+ }
+ int getErDiffusion() const { return mDiffusion; }
+
+ RetCode setErDensity(int density) {
+ if (density < EnvironmentalReverb::MIN_DENSITY_PM ||
+ density > EnvironmentalReverb::MAX_DENSITY_PM) {
+ LOG(ERROR) << __func__ << " invalid density: " << density;
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ // TODO : Add implementation to apply new density
+ mDensity = density;
+ return RetCode::SUCCESS;
+ }
+ int getErDensity() const { return mDensity; }
+
+ RetCode setErBypass(bool bypass) {
+ // TODO : Add implementation to apply new bypass
+ mBypass = bypass;
+ return RetCode::SUCCESS;
+ }
+ bool getErBypass() const { return mBypass; }
+
+ private:
+ int mRoomLevel = EnvironmentalReverb::MIN_ROOM_LEVEL_MB; // Default room level
+ int mRoomHfLevel = EnvironmentalReverb::MAX_ROOM_HF_LEVEL_MB; // Default room hf level
+ int mDecayTime = 1000; // Default decay time
+ int mDecayHfRatio = 500; // Default decay hf ratio
+ int mLevel = EnvironmentalReverb::MIN_LEVEL_MB; // Default level
+ int mDelay = 40; // Default delay
+ int mDiffusion = EnvironmentalReverb::MAX_DIFFUSION_PM; // Default diffusion
+ int mDensity = EnvironmentalReverb::MAX_DENSITY_PM; // Default density
+ bool mBypass = false; // Default bypass
};
class EnvReverbSw final : public EffectImpl {
@@ -60,7 +173,7 @@
private:
std::shared_ptr<EnvReverbSwContext> mContext;
- /* parameters */
- EnvironmentalReverb mSpecificParam;
+ ndk::ScopedAStatus getParameterEnvironmentalReverb(const EnvironmentalReverb::Tag& tag,
+ Parameter::Specific* specific);
};
} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/equalizer/EqualizerSw.h b/audio/aidl/default/equalizer/EqualizerSw.h
index 81bcd7a..65a8002 100644
--- a/audio/aidl/default/equalizer/EqualizerSw.h
+++ b/audio/aidl/default/equalizer/EqualizerSw.h
@@ -53,8 +53,9 @@
LOG(ERROR) << __func__ << " index illegal, skip: " << it.index << " - "
<< it.levelMb;
ret = RetCode::ERROR_ILLEGAL_PARAMETER;
+ } else {
+ mBandLevels[it.index] = it.levelMb;
}
- mBandLevels[it.index] = it.levelMb;
}
return ret;
}
diff --git a/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp
index 8004631..f6211c4 100644
--- a/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp
+++ b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp
@@ -84,16 +84,71 @@
ndk::ScopedAStatus HapticGeneratorSw::setParameterSpecific(const Parameter::Specific& specific) {
RETURN_IF(Parameter::Specific::hapticGenerator != specific.getTag(), EX_ILLEGAL_ARGUMENT,
"EffectNotSupported");
- mSpecificParam = specific.get<Parameter::Specific::hapticGenerator>();
- LOG(DEBUG) << __func__ << " success with: " << specific.toString();
- return ndk::ScopedAStatus::ok();
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ auto& hgParam = specific.get<Parameter::Specific::hapticGenerator>();
+ auto tag = hgParam.getTag();
+
+ switch (tag) {
+ case HapticGenerator::hapticScale: {
+ RETURN_IF(mContext->setHgHapticScale(hgParam.get<HapticGenerator::hapticScale>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "HapticScaleNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case HapticGenerator::vibratorInfo: {
+ RETURN_IF(mContext->setHgVibratorInformation(
+ hgParam.get<HapticGenerator::vibratorInfo>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "VibratorInfoNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "HapticGeneratorTagNotSupported");
+ }
+ }
}
ndk::ScopedAStatus HapticGeneratorSw::getParameterSpecific(const Parameter::Id& id,
Parameter::Specific* specific) {
auto tag = id.getTag();
RETURN_IF(Parameter::Id::hapticGeneratorTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
- specific->set<Parameter::Specific::hapticGenerator>(mSpecificParam);
+ auto hgId = id.get<Parameter::Id::hapticGeneratorTag>();
+ auto hgIdTag = hgId.getTag();
+ switch (hgIdTag) {
+ case HapticGenerator::Id::commonTag:
+ return getParameterHapticGenerator(hgId.get<HapticGenerator::Id::commonTag>(),
+ specific);
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "HapticGeneratorTagNotSupported");
+ }
+}
+
+ndk::ScopedAStatus HapticGeneratorSw::getParameterHapticGenerator(const HapticGenerator::Tag& tag,
+ Parameter::Specific* specific) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ HapticGenerator hgParam;
+ switch (tag) {
+ case HapticGenerator::hapticScale: {
+ hgParam.set<HapticGenerator::hapticScale>(mContext->getHgHapticScale());
+ break;
+ }
+ case HapticGenerator::vibratorInfo: {
+ hgParam.set<HapticGenerator::vibratorInfo>(mContext->getHgVibratorInformation());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "HapticGeneratorTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::hapticGenerator>(hgParam);
return ndk::ScopedAStatus::ok();
}
diff --git a/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h
index bf01bfb..d9ec744 100644
--- a/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h
+++ b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h
@@ -32,7 +32,31 @@
: EffectContext(statusDepth, common) {
LOG(DEBUG) << __func__;
}
- // TODO: add specific context here
+
+ RetCode setHgHapticScale(const HapticGenerator::HapticScale& hapticScale) {
+ // All int values are valid for ID
+ mHapticScale = hapticScale;
+ return RetCode::SUCCESS;
+ }
+ HapticGenerator::HapticScale getHgHapticScale() const { return mHapticScale; }
+
+ RetCode setHgVibratorInformation(const HapticGenerator::VibratorInformation& vibratorInfo) {
+ // All float values are valid for resonantFrequencyHz, qFactor, maxAmplitude
+ mVibratorInformation = vibratorInfo;
+ return RetCode::SUCCESS;
+ }
+
+ HapticGenerator::VibratorInformation getHgVibratorInformation() const {
+ return mVibratorInformation;
+ }
+
+ private:
+ static constexpr float DEFAULT_RESONANT_FREQUENCY = 150.0f;
+ static constexpr float DEFAULT_Q_FACTOR = 1.0f;
+ static constexpr float DEFAULT_MAX_AMPLITUDE = 0.0f;
+ HapticGenerator::HapticScale mHapticScale = {0, HapticGenerator::VibratorScale::MUTE};
+ HapticGenerator::VibratorInformation mVibratorInformation = {
+ DEFAULT_RESONANT_FREQUENCY, DEFAULT_Q_FACTOR, DEFAULT_MAX_AMPLITUDE};
};
class HapticGeneratorSw final : public EffectImpl {
@@ -60,7 +84,8 @@
private:
std::shared_ptr<HapticGeneratorSwContext> mContext;
- /* parameters */
- HapticGenerator mSpecificParam;
+
+ ndk::ScopedAStatus getParameterHapticGenerator(const HapticGenerator::Tag& tag,
+ Parameter::Specific* specific);
};
} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index 52fb54c..aa05d2a 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -86,6 +86,20 @@
ndk::ScopedAStatus updateScreenRotation(
::aidl::android::hardware::audio::core::IModule::ScreenRotation in_rotation) override;
ndk::ScopedAStatus updateScreenState(bool in_isTurnedOn) override;
+ ndk::ScopedAStatus getSoundDose(std::shared_ptr<ISoundDose>* _aidl_return) override;
+ ndk::ScopedAStatus generateHwAvSyncId(int32_t* _aidl_return) override;
+ ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_ids,
+ std::vector<VendorParameter>* _aidl_return) override;
+ ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
+ bool in_async) override;
+ ndk::ScopedAStatus addDeviceEffect(
+ int32_t in_portConfigId,
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
+ override;
+ ndk::ScopedAStatus removeDeviceEffect(
+ int32_t in_portConfigId,
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
+ override;
void cleanUpPatch(int32_t patchId);
ndk::ScopedAStatus createStreamContext(
@@ -114,6 +128,7 @@
// Since it is required to return the same instance of the ITelephony, even
// if the client has released it on its side, we need to hold it via a strong pointer.
std::shared_ptr<ITelephony> mTelephony;
+ ndk::SpAIBinder mTelephonyBinder;
// ids of ports created at runtime via 'connectExternalDevice'.
std::set<int32_t> mConnectedDevicePorts;
Streams mStreams;
@@ -123,6 +138,8 @@
bool mMasterMute = false;
float mMasterVolume = 1.0f;
bool mMicMute = false;
+ std::shared_ptr<ISoundDose> mSoundDose;
+ ndk::SpAIBinder mSoundDoseBinder;
};
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/SoundDose.h b/audio/aidl/default/include/core-impl/SoundDose.h
new file mode 100644
index 0000000..54a6cbf
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/SoundDose.h
@@ -0,0 +1,42 @@
+/*
+ * 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 <mutex>
+
+#include <aidl/android/hardware/audio/core/BnSoundDose.h>
+#include <aidl/android/media/audio/common/AudioDevice.h>
+
+using aidl::android::media::audio::common::AudioDevice;
+
+namespace aidl::android::hardware::audio::core {
+
+class SoundDose : public BnSoundDose {
+ public:
+ SoundDose() : mRs2Value(DEFAULT_MAX_RS2){};
+
+ ndk::ScopedAStatus setOutputRs2(float in_rs2ValueDbA) override;
+ ndk::ScopedAStatus getOutputRs2(float* _aidl_return) override;
+ ndk::ScopedAStatus registerSoundDoseCallback(
+ const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& in_callback) override;
+
+ private:
+ std::shared_ptr<ISoundDose::IHalSoundDoseCallback> mCallback;
+ float mRs2Value;
+};
+
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index 7a07eeb..a5d240f 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -27,6 +27,7 @@
#include <StreamWorker.h>
#include <aidl/android/hardware/audio/common/SinkMetadata.h>
#include <aidl/android/hardware/audio/common/SourceMetadata.h>
+#include <aidl/android/hardware/audio/core/BnStreamCommon.h>
#include <aidl/android/hardware/audio/core/BnStreamIn.h>
#include <aidl/android/hardware/audio/core/BnStreamOut.h>
#include <aidl/android/hardware/audio/core/IStreamCallback.h>
@@ -197,10 +198,93 @@
};
using StreamOutWorker = ::android::hardware::audio::common::StreamWorker<StreamOutWorkerLogic>;
-template <class Metadata, class StreamWorker>
-class StreamCommon {
+// This provides a C++ interface with methods of the IStreamCommon Binder interface,
+// but intentionally does not inherit from it. This is needed to avoid inheriting
+// StreamIn and StreamOut from two Binder interface classes, as these parts of the class
+// will be reference counted separately.
+//
+// The implementation of these common methods is in the StreamCommonImpl template class.
+struct StreamCommonInterface {
+ virtual ~StreamCommonInterface() = default;
+ virtual ndk::ScopedAStatus close() = 0;
+ virtual ndk::ScopedAStatus updateHwAvSyncId(int32_t in_hwAvSyncId) = 0;
+ virtual ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_ids,
+ std::vector<VendorParameter>* _aidl_return) = 0;
+ virtual ndk::ScopedAStatus setVendorParameters(
+ const std::vector<VendorParameter>& in_parameters, bool in_async) = 0;
+ virtual ndk::ScopedAStatus addEffect(
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&
+ in_effect) = 0;
+ virtual ndk::ScopedAStatus removeEffect(
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&
+ in_effect) = 0;
+};
+
+class StreamCommon : public BnStreamCommon {
public:
- ndk::ScopedAStatus close();
+ explicit StreamCommon(const std::shared_ptr<StreamCommonInterface>& delegate)
+ : mDelegate(delegate) {}
+
+ private:
+ ndk::ScopedAStatus close() override {
+ auto delegate = mDelegate.lock();
+ return delegate != nullptr ? delegate->close()
+ : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ ndk::ScopedAStatus updateHwAvSyncId(int32_t in_hwAvSyncId) override {
+ auto delegate = mDelegate.lock();
+ return delegate != nullptr ? delegate->updateHwAvSyncId(in_hwAvSyncId)
+ : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_ids,
+ std::vector<VendorParameter>* _aidl_return) override {
+ auto delegate = mDelegate.lock();
+ return delegate != nullptr ? delegate->getVendorParameters(in_ids, _aidl_return)
+ : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
+ bool in_async) override {
+ auto delegate = mDelegate.lock();
+ return delegate != nullptr ? delegate->setVendorParameters(in_parameters, in_async)
+ : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ ndk::ScopedAStatus addEffect(
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
+ override {
+ auto delegate = mDelegate.lock();
+ return delegate != nullptr ? delegate->addEffect(in_effect)
+ : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ ndk::ScopedAStatus removeEffect(
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
+ override {
+ auto delegate = mDelegate.lock();
+ return delegate != nullptr ? delegate->removeEffect(in_effect)
+ : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ // It is possible that on the client side the proxy for IStreamCommon will outlive
+ // the IStream* instance, and the server side IStream* instance will get destroyed
+ // while this IStreamCommon instance is still alive.
+ std::weak_ptr<StreamCommonInterface> mDelegate;
+};
+
+template <class Metadata, class StreamWorker>
+class StreamCommonImpl : public StreamCommonInterface {
+ public:
+ ndk::ScopedAStatus close() override;
+ ndk::ScopedAStatus updateHwAvSyncId(int32_t in_hwAvSyncId) override;
+ ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_ids,
+ std::vector<VendorParameter>* _aidl_return) override;
+ ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
+ bool in_async) override;
+ ndk::ScopedAStatus addEffect(
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
+ override;
+ ndk::ScopedAStatus removeEffect(
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
+ override;
+
+ ndk::ScopedAStatus getStreamCommon(std::shared_ptr<IStreamCommon>* _aidl_return);
ndk::ScopedAStatus init() {
return mWorker.start(StreamWorker::kThreadName, ANDROID_PRIORITY_AUDIO)
? ndk::ScopedAStatus::ok()
@@ -215,23 +299,26 @@
ndk::ScopedAStatus updateMetadata(const Metadata& metadata);
protected:
- StreamCommon(const Metadata& metadata, StreamContext context)
+ StreamCommonImpl(const Metadata& metadata, StreamContext&& context)
: mMetadata(metadata), mContext(std::move(context)), mWorker(mContext) {}
- ~StreamCommon();
+ ~StreamCommonImpl();
void stopWorker();
+ void createStreamCommon(const std::shared_ptr<StreamCommonInterface>& delegate);
+ std::shared_ptr<StreamCommon> mCommon;
+ ndk::SpAIBinder mCommonBinder;
Metadata mMetadata;
StreamContext mContext;
StreamWorker mWorker;
std::vector<::aidl::android::media::audio::common::AudioDevice> mConnectedDevices;
};
-class StreamIn
- : public StreamCommon<::aidl::android::hardware::audio::common::SinkMetadata, StreamInWorker>,
- public BnStreamIn {
- ndk::ScopedAStatus close() override {
- return StreamCommon<::aidl::android::hardware::audio::common::SinkMetadata,
- StreamInWorker>::close();
+class StreamIn : public StreamCommonImpl<::aidl::android::hardware::audio::common::SinkMetadata,
+ StreamInWorker>,
+ public BnStreamIn {
+ ndk::ScopedAStatus getStreamCommon(std::shared_ptr<IStreamCommon>* _aidl_return) override {
+ return StreamCommonImpl<::aidl::android::hardware::audio::common::SinkMetadata,
+ StreamInWorker>::getStreamCommon(_aidl_return);
}
ndk::ScopedAStatus getActiveMicrophones(
std::vector<MicrophoneDynamicInfo>* _aidl_return) override;
@@ -241,46 +328,75 @@
ndk::ScopedAStatus setMicrophoneFieldDimension(float in_zoom) override;
ndk::ScopedAStatus updateMetadata(const ::aidl::android::hardware::audio::common::SinkMetadata&
in_sinkMetadata) override {
- return StreamCommon<::aidl::android::hardware::audio::common::SinkMetadata,
- StreamInWorker>::updateMetadata(in_sinkMetadata);
+ return StreamCommonImpl<::aidl::android::hardware::audio::common::SinkMetadata,
+ StreamInWorker>::updateMetadata(in_sinkMetadata);
}
+ ndk::ScopedAStatus getHwGain(std::vector<float>* _aidl_return) override;
+ ndk::ScopedAStatus setHwGain(const std::vector<float>& in_channelGains) override;
public:
- StreamIn(const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
- StreamContext context, const std::vector<MicrophoneInfo>& microphones);
+ static ndk::ScopedAStatus createInstance(
+ const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+ StreamContext context, const std::vector<MicrophoneInfo>& microphones,
+ std::shared_ptr<StreamIn>* result);
private:
+ friend class ndk::SharedRefBase;
+ StreamIn(const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+ StreamContext&& context, const std::vector<MicrophoneInfo>& microphones);
+ void createStreamCommon(const std::shared_ptr<StreamIn>& myPtr) {
+ StreamCommonImpl<::aidl::android::hardware::audio::common::SinkMetadata,
+ StreamInWorker>::createStreamCommon(myPtr);
+ }
+
const std::map<::aidl::android::media::audio::common::AudioDevice, std::string> mMicrophones;
};
-class StreamOut : public StreamCommon<::aidl::android::hardware::audio::common::SourceMetadata,
- StreamOutWorker>,
+class StreamOut : public StreamCommonImpl<::aidl::android::hardware::audio::common::SourceMetadata,
+ StreamOutWorker>,
public BnStreamOut {
- ndk::ScopedAStatus close() override {
- return StreamCommon<::aidl::android::hardware::audio::common::SourceMetadata,
- StreamOutWorker>::close();
+ ndk::ScopedAStatus getStreamCommon(std::shared_ptr<IStreamCommon>* _aidl_return) override {
+ return StreamCommonImpl<::aidl::android::hardware::audio::common::SourceMetadata,
+ StreamOutWorker>::getStreamCommon(_aidl_return);
}
ndk::ScopedAStatus updateMetadata(
const ::aidl::android::hardware::audio::common::SourceMetadata& in_sourceMetadata)
override {
- return StreamCommon<::aidl::android::hardware::audio::common::SourceMetadata,
- StreamOutWorker>::updateMetadata(in_sourceMetadata);
+ return StreamCommonImpl<::aidl::android::hardware::audio::common::SourceMetadata,
+ StreamOutWorker>::updateMetadata(in_sourceMetadata);
}
+ ndk::ScopedAStatus getHwVolume(std::vector<float>* _aidl_return) override;
+ ndk::ScopedAStatus setHwVolume(const std::vector<float>& in_channelVolumes) override;
public:
- StreamOut(const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
- StreamContext context,
- const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
- offloadInfo);
+ static ndk::ScopedAStatus createInstance(
+ const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+ StreamContext context,
+ const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+ offloadInfo,
+ std::shared_ptr<StreamOut>* result);
private:
+ friend class ndk::SharedRefBase;
+ StreamOut(const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+ StreamContext&& context,
+ const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+ offloadInfo);
+ void createStreamCommon(const std::shared_ptr<StreamOut>& myPtr) {
+ StreamCommonImpl<::aidl::android::hardware::audio::common::SourceMetadata,
+ StreamOutWorker>::createStreamCommon(myPtr);
+ }
+
std::optional<::aidl::android::media::audio::common::AudioOffloadInfo> mOffloadInfo;
};
class StreamWrapper {
public:
- explicit StreamWrapper(std::shared_ptr<StreamIn> streamIn) : mStream(streamIn) {}
- explicit StreamWrapper(std::shared_ptr<StreamOut> streamOut) : mStream(streamOut) {}
+ explicit StreamWrapper(const std::shared_ptr<StreamIn>& streamIn)
+ : mStream(streamIn), mStreamBinder(streamIn->asBinder()) {}
+ explicit StreamWrapper(const std::shared_ptr<StreamOut>& streamOut)
+ : mStream(streamOut), mStreamBinder(streamOut->asBinder()) {}
+ ndk::SpAIBinder getBinder() const { return mStreamBinder; }
bool isStreamOpen() const {
return std::visit(
[](auto&& ws) -> bool {
@@ -301,6 +417,7 @@
private:
std::variant<std::weak_ptr<StreamIn>, std::weak_ptr<StreamOut>> mStream;
+ ndk::SpAIBinder mStreamBinder;
};
class Streams {
diff --git a/audio/aidl/default/include/effect-impl/EffectContext.h b/audio/aidl/default/include/effect-impl/EffectContext.h
index 95645d5..1f39db0 100644
--- a/audio/aidl/default/include/effect-impl/EffectContext.h
+++ b/audio/aidl/default/include/effect-impl/EffectContext.h
@@ -72,13 +72,11 @@
float* getWorkBuffer() { return static_cast<float*>(mWorkBuffer.data()); }
- // reset buffer status by abandon all data and status in FMQ
+ // reset buffer status by abandon input data in FMQ
void resetBuffer() {
auto buffer = static_cast<float*>(mWorkBuffer.data());
std::vector<IEffect::Status> status(mStatusMQ->availableToRead());
mInputMQ->read(buffer, mInputMQ->availableToRead());
- mOutputMQ->read(buffer, mOutputMQ->availableToRead());
- mStatusMQ->read(status.data(), mStatusMQ->availableToRead());
}
void dupeFmq(IEffect::OpenEffectReturn* effectRet) {
diff --git a/audio/aidl/default/include/effect-impl/EffectUUID.h b/audio/aidl/default/include/effect-impl/EffectUUID.h
index 7709eab..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,
@@ -45,6 +69,18 @@
0x11ed,
0x9b6a,
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// 8631f300-72e2-11df-b57e-0002a5d5c51b
+static const AudioUuid kBassBoostBundleImplUUID = {static_cast<int32_t>(0x8631f300),
+ 0x72e2,
+ 0x11df,
+ 0xb57e,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+// 14804144-a5ee-4d24-aa88-0002a5d5c51b
+static const AudioUuid kBassBoostProxyUUID = {static_cast<int32_t>(0x14804144),
+ 0xa5ee,
+ 0x4d24,
+ 0xaa88,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
// fa81862a-588b-11ed-9b6a-0242ac120002
static const AudioUuid kDownmixTypeUUID = {static_cast<int32_t>(0xfa81862a),
0x588b,
@@ -57,6 +93,12 @@
0x11ed,
0x9b6a,
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// 93f04452-e4fe-41cc-91f9-e475b6d1d69f
+static const AudioUuid kDownmixImplUUID = {static_cast<int32_t>(0x93f04452),
+ 0xe4fe,
+ 0x41cc,
+ 0x91f9,
+ {0xe4, 0x75, 0xb6, 0xd1, 0xd6, 0x9f}};
// 0bed4300-ddd6-11db-8f34-0002a5d5c51b.
static const AudioUuid kEqualizerTypeUUID = {static_cast<int32_t>(0x0bed4300),
0xddd6,
@@ -117,6 +159,12 @@
0x11ed,
0x9b6a,
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa415329-2034-4bea-b5dc-5b381c8d1e2c
+static const AudioUuid kLoudnessEnhancerImplUUID = {static_cast<int32_t>(0xfa415329),
+ 0x2034,
+ 0x4bea,
+ 0xb5dc,
+ {0x5b, 0x38, 0x1c, 0x8d, 0x1e, 0x2c}};
// c2e5d5f0-94bd-4763-9cac-4e234d06839e
static const AudioUuid kEnvReverbTypeUUID = {static_cast<int32_t>(0xc2e5d5f0),
0x94bd,
@@ -129,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,
@@ -184,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},
@@ -191,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/include/effectFactory-impl/EffectFactory.h b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
index 5903276..04bd1bb 100644
--- a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
+++ b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
@@ -96,9 +96,8 @@
std::map<aidl::android::media::audio::common::AudioUuid /* implUUID */, DlEntry> mEffectLibMap;
- std::map<std::weak_ptr<IEffect>, aidl::android::media::audio::common::AudioUuid,
- std::owner_less<>>
- mEffectUuidMap;
+ typedef std::pair<aidl::android::media::audio::common::AudioUuid, ndk::SpAIBinder> EffectEntry;
+ std::map<std::weak_ptr<IEffect>, EffectEntry, std::owner_less<>> mEffectMap;
ndk::ScopedAStatus destroyEffectImpl(const std::shared_ptr<IEffect>& in_handle);
void cleanupEffectMap();
diff --git a/audio/aidl/default/main.cpp b/audio/aidl/default/main.cpp
index b11af4e..b66c134 100644
--- a/audio/aidl/default/main.cpp
+++ b/audio/aidl/default/main.cpp
@@ -16,6 +16,7 @@
#include <cstdlib>
#include <ctime>
+#include <utility>
#include <android-base/logging.h>
#include <android/binder_ibinder_platform.h>
@@ -44,19 +45,17 @@
CHECK_EQ(STATUS_OK, status);
// Make modules
- auto moduleDefault = ndk::SharedRefBase::make<Module>(Module::Type::DEFAULT);
- const std::string moduleDefaultName = std::string() + Module::descriptor + "/default";
- AIBinder_setMinSchedulerPolicy(moduleDefault->asBinder().get(), SCHED_NORMAL,
- ANDROID_PRIORITY_AUDIO);
- status = AServiceManager_addService(moduleDefault->asBinder().get(), moduleDefaultName.c_str());
- CHECK_EQ(STATUS_OK, status);
-
- auto moduleRSubmix = ndk::SharedRefBase::make<Module>(Module::Type::R_SUBMIX);
- const std::string moduleRSubmixName = std::string() + Module::descriptor + "/r_submix";
- AIBinder_setMinSchedulerPolicy(moduleRSubmix->asBinder().get(), SCHED_NORMAL,
- ANDROID_PRIORITY_AUDIO);
- status = AServiceManager_addService(moduleRSubmix->asBinder().get(), moduleRSubmixName.c_str());
- CHECK_EQ(STATUS_OK, status);
+ auto createModule = [](Module::Type type, const std::string& instance) {
+ auto module = ndk::SharedRefBase::make<Module>(type);
+ ndk::SpAIBinder moduleBinder = module->asBinder();
+ const std::string moduleName = std::string(Module::descriptor).append("/").append(instance);
+ AIBinder_setMinSchedulerPolicy(moduleBinder.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
+ binder_status_t status = AServiceManager_addService(moduleBinder.get(), moduleName.c_str());
+ CHECK_EQ(STATUS_OK, status);
+ return std::make_pair(module, moduleBinder);
+ };
+ auto modules = {createModule(Module::Type::DEFAULT, "default"),
+ createModule(Module::Type::R_SUBMIX, "r_submix")};
ABinderProcess_joinThreadPool();
return EXIT_FAILURE; // should not reach
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/default/visualizer/VisualizerSw.cpp b/audio/aidl/default/visualizer/VisualizerSw.cpp
index b898c00..37eb30b 100644
--- a/audio/aidl/default/visualizer/VisualizerSw.cpp
+++ b/audio/aidl/default/visualizer/VisualizerSw.cpp
@@ -14,14 +14,9 @@
* limitations under the License.
*/
-#include <cstddef>
#define LOG_TAG "AHAL_VisualizerSw"
-#include <Utils.h>
-#include <algorithm>
-#include <unordered_set>
#include <android-base/logging.h>
-#include <fmq/AidlMessageQueue.h>
#include "VisualizerSw.h"
@@ -60,7 +55,10 @@
namespace aidl::android::hardware::audio::effect {
const std::string VisualizerSw::kEffectName = "VisualizerSw";
-const Visualizer::Capability VisualizerSw::kCapability;
+/* capabilities */
+const Visualizer::CaptureSizeRange mCaptureSizeRange = {MIN_CAPTURE_SIZE, MAX_CAPTURE_SIZE};
+const Visualizer::Capability VisualizerSw::kCapability = {.maxLatencyMs = MAX_LATENCY,
+ .captureSizeRange = mCaptureSizeRange};
const Descriptor VisualizerSw::kDescriptor = {
.common = {.id = {.type = kVisualizerTypeUUID,
.uuid = kVisualizerSwImplUUID,
@@ -82,8 +80,53 @@
RETURN_IF(Parameter::Specific::visualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
"EffectNotSupported");
- mSpecificParam = specific.get<Parameter::Specific::visualizer>();
- LOG(DEBUG) << __func__ << " success with: " << specific.toString();
+ auto& vsParam = specific.get<Parameter::Specific::visualizer>();
+ auto tag = vsParam.getTag();
+
+ switch (tag) {
+ case Visualizer::captureSizeBytes: {
+ RETURN_IF(mContext->setVsCaptureSize(vsParam.get<Visualizer::captureSizeBytes>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "captureSizeNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case Visualizer::scalingMode: {
+ RETURN_IF(mContext->setVsScalingMode(vsParam.get<Visualizer::scalingMode>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "scalingModeNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case Visualizer::measurementMode: {
+ RETURN_IF(mContext->setVsMeasurementMode(vsParam.get<Visualizer::measurementMode>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "measurementModeNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case Visualizer::setOnlyParameters: {
+ return setSetOnlyParameterVisualizer(vsParam.get<Visualizer::setOnlyParameters>());
+ }
+ case Visualizer::getOnlyParameters: {
+ LOG(ERROR) << __func__ << " unsupported settable getOnlyParam";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "SetofGetOnlyParamsNotSupported");
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "VisualizerTagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus VisualizerSw::setSetOnlyParameterVisualizer(
+ Visualizer::SetOnlyParameters setOnlyParam) {
+ auto tag = setOnlyParam.getTag();
+ RETURN_IF(Visualizer::SetOnlyParameters::latencyMs != tag, EX_ILLEGAL_ARGUMENT,
+ "SetOnlyParametersTagNotSupported");
+ RETURN_IF(
+ mContext->setVsLatency(setOnlyParam.get<Visualizer::SetOnlyParameters::latencyMs>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "latencyNotSupported");
return ndk::ScopedAStatus::ok();
}
@@ -91,7 +134,76 @@
Parameter::Specific* specific) {
auto tag = id.getTag();
RETURN_IF(Parameter::Id::visualizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
- specific->set<Parameter::Specific::visualizer>(mSpecificParam);
+ auto vsId = id.get<Parameter::Id::visualizerTag>();
+ auto vsIdTag = vsId.getTag();
+ switch (vsIdTag) {
+ case Visualizer::Id::commonTag:
+ return getParameterVisualizer(vsId.get<Visualizer::Id::commonTag>(), specific);
+ case Visualizer::Id::getOnlyParamTag:
+ return getGetOnlyParameterVisualizer(vsId.get<Visualizer::Id::getOnlyParamTag>(),
+ specific);
+ case Visualizer::Id::setOnlyParamTag: {
+ LOG(ERROR) << __func__ << " unsupported gettable setOnlyParam";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "GetofSetOnlyParamsNotSupported");
+ }
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "VisualizerTagNotSupported");
+ }
+}
+ndk::ScopedAStatus VisualizerSw::getParameterVisualizer(const Visualizer::Tag& tag,
+ Parameter::Specific* specific) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ Visualizer vsParam;
+ switch (tag) {
+ case Visualizer::captureSizeBytes: {
+ vsParam.set<Visualizer::captureSizeBytes>(mContext->getVsCaptureSize());
+ break;
+ }
+ case Visualizer::scalingMode: {
+ vsParam.set<Visualizer::scalingMode>(mContext->getVsScalingMode());
+ break;
+ }
+ case Visualizer::measurementMode: {
+ vsParam.set<Visualizer::measurementMode>(mContext->getVsMeasurementMode());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "VisualizerTagNotSupported");
+ }
+ }
+ specific->set<Parameter::Specific::visualizer>(vsParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VisualizerSw::getGetOnlyParameterVisualizer(
+ const Visualizer::GetOnlyParameters::Tag& tag, Parameter::Specific* specific) {
+ Visualizer::GetOnlyParameters getOnlyParam;
+ switch (tag) {
+ case Visualizer::GetOnlyParameters::measurement: {
+ getOnlyParam.set<Visualizer::GetOnlyParameters::measurement>(
+ mContext->getVsMeasurement());
+ break;
+ }
+ case Visualizer::GetOnlyParameters::captureBytes: {
+ getOnlyParam.set<Visualizer::GetOnlyParameters::captureBytes>(
+ mContext->getVsCaptureBytes());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "GetOnlyParameterTagNotSupported");
+ }
+ }
+ Visualizer vsParam;
+ vsParam.set<Visualizer::getOnlyParameters>(getOnlyParam);
+ specific->set<Parameter::Specific::visualizer>(vsParam);
return ndk::ScopedAStatus::ok();
}
diff --git a/audio/aidl/default/visualizer/VisualizerSw.h b/audio/aidl/default/visualizer/VisualizerSw.h
index 24b92dd..a95537c 100644
--- a/audio/aidl/default/visualizer/VisualizerSw.h
+++ b/audio/aidl/default/visualizer/VisualizerSw.h
@@ -17,13 +17,16 @@
#pragma once
#include <aidl/android/hardware/audio/effect/BnEffect.h>
-#include <fmq/AidlMessageQueue.h>
-#include <cstdlib>
-#include <memory>
+#include <vector>
#include "effect-impl/EffectImpl.h"
#include "effect-impl/EffectUUID.h"
+#define MIN_CAPTURE_SIZE 128
+#define MAX_CAPTURE_SIZE 1024
+#define MAX_LATENCY 3000
+#define CAPTURE_BUF_SIZE 65536
+
namespace aidl::android::hardware::audio::effect {
class VisualizerSwContext final : public EffectContext {
@@ -31,8 +34,55 @@
VisualizerSwContext(int statusDepth, const Parameter::Common& common)
: EffectContext(statusDepth, common) {
LOG(DEBUG) << __func__;
+ mCaptureBytes.resize(CAPTURE_BUF_SIZE);
+ fill(mCaptureBytes.begin(), mCaptureBytes.end(), 0x80);
}
- // TODO: add specific context here
+
+ RetCode setVsCaptureSize(int captureSize) {
+ if (captureSize < MIN_CAPTURE_SIZE || captureSize > MAX_CAPTURE_SIZE) {
+ LOG(ERROR) << __func__ << " invalid captureSize " << captureSize;
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ // TODO : Add implementation to apply new captureSize
+ mCaptureSize = captureSize;
+ return RetCode::SUCCESS;
+ }
+ int getVsCaptureSize() const { return mCaptureSize; }
+
+ RetCode setVsScalingMode(Visualizer::ScalingMode scalingMode) {
+ // TODO : Add implementation to apply new scalingMode
+ mScalingMode = scalingMode;
+ return RetCode::SUCCESS;
+ }
+ Visualizer::ScalingMode getVsScalingMode() const { return mScalingMode; }
+
+ RetCode setVsMeasurementMode(Visualizer::MeasurementMode measurementMode) {
+ // TODO : Add implementation to apply new measurementMode
+ mMeasurementMode = measurementMode;
+ return RetCode::SUCCESS;
+ }
+ Visualizer::MeasurementMode getVsMeasurementMode() const { return mMeasurementMode; }
+
+ RetCode setVsLatency(int latency) {
+ if (latency < 0 || latency > MAX_LATENCY) {
+ LOG(ERROR) << __func__ << " invalid latency " << latency;
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ // TODO : Add implementation to modify latency
+ mLatency = latency;
+ return RetCode::SUCCESS;
+ }
+
+ Visualizer::GetOnlyParameters::Measurement getVsMeasurement() const { return mMeasurement; }
+ std::vector<uint8_t> getVsCaptureBytes() const { return mCaptureBytes; }
+
+ private:
+ int mCaptureSize = MAX_CAPTURE_SIZE;
+ Visualizer::ScalingMode mScalingMode = Visualizer::ScalingMode::NORMALIZED;
+ Visualizer::MeasurementMode mMeasurementMode = Visualizer::MeasurementMode::NONE;
+ int mLatency;
+ const Visualizer::GetOnlyParameters::Measurement mMeasurement = {0, 0};
+ std::vector<uint8_t> mCaptureBytes;
};
class VisualizerSw final : public EffectImpl {
@@ -60,7 +110,11 @@
private:
std::shared_ptr<VisualizerSwContext> mContext;
- /* parameters */
- Visualizer mSpecificParam;
+
+ ndk::ScopedAStatus setSetOnlyParameterVisualizer(Visualizer::SetOnlyParameters setOnlyParam);
+ ndk::ScopedAStatus getParameterVisualizer(const Visualizer::Tag& tag,
+ Parameter::Specific* specific);
+ ndk::ScopedAStatus getGetOnlyParameterVisualizer(const Visualizer::GetOnlyParameters::Tag& tag,
+ Parameter::Specific* specific);
};
} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/sounddose/Android.bp b/audio/aidl/sounddose/Android.bp
new file mode 100644
index 0000000..85d6e21
--- /dev/null
+++ b/audio/aidl/sounddose/Android.bp
@@ -0,0 +1,70 @@
+/*
+ * 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"],
+}
+
+aidl_interface {
+ name: "android.hardware.audio.sounddose",
+ host_supported: true,
+ vendor_available: true,
+ stability: "vintf",
+ srcs: [
+ "android/hardware/audio/sounddose/ISoundDoseFactory.aidl",
+ ],
+ imports: [
+ latest_android_hardware_audio_core_sounddose,
+ ],
+ backend: {
+ // The C++ backend is disabled transitively due to use by core audio HAL.
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ sdk_version: "module_current",
+ },
+ },
+ versions_with_info: [
+ // IMPORTANT: Update latest_android_hardware_audio_sounddose every time you
+ // add the latest frozen version to versions_with_info
+ ],
+}
+
+// Note: This should always be one version ahead of the last frozen version
+latest_android_hardware_audio_sounddose = "android.hardware.audio.sounddose-V1"
+
+// Modules that depend on android.hardware.audio.sounddose directly can include
+// the following cc_defaults to avoid explicitly managing dependency versions
+// across many scattered files.
+cc_defaults {
+ name: "latest_android_hardware_audio_sounddose_ndk_shared",
+ shared_libs: [
+ latest_android_hardware_audio_sounddose + "-ndk",
+ ],
+}
+
+cc_defaults {
+ name: "latest_android_hardware_audio_sounddose_ndk_static",
+ static_libs: [
+ latest_android_hardware_audio_sounddose + "-ndk",
+ ],
+}
diff --git a/audio/aidl/sounddose/aidl_api/android.hardware.audio.core.sounddose/current/android/hardware/audio/core/ISoundDose.aidl b/audio/aidl/sounddose/aidl_api/android.hardware.audio.core.sounddose/current/android/hardware/audio/core/ISoundDose.aidl
new file mode 100644
index 0000000..dff17e2
--- /dev/null
+++ b/audio/aidl/sounddose/aidl_api/android.hardware.audio.core.sounddose/current/android/hardware/audio/core/ISoundDose.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.core;
+@VintfStability
+interface ISoundDose {
+ void setOutputRs2(float rs2ValueDbA);
+ float getOutputRs2();
+ void registerSoundDoseCallback(in android.hardware.audio.core.ISoundDose.IHalSoundDoseCallback callback);
+ const int DEFAULT_MAX_RS2 = 100;
+ @VintfStability
+ interface IHalSoundDoseCallback {
+ oneway void onMomentaryExposureWarning(float currentDbA, in android.media.audio.common.AudioDevice audioDevice);
+ oneway void onNewMelValues(in android.hardware.audio.core.ISoundDose.IHalSoundDoseCallback.MelRecord melRecord, in android.media.audio.common.AudioDevice audioDevice);
+ @VintfStability
+ parcelable MelRecord {
+ float[] melValues;
+ long timestamp;
+ }
+ }
+}
diff --git a/audio/aidl/sounddose/aidl_api/android.hardware.audio.sounddose/current/android/hardware/audio/sounddose/ISoundDoseFactory.aidl b/audio/aidl/sounddose/aidl_api/android.hardware.audio.sounddose/current/android/hardware/audio/sounddose/ISoundDoseFactory.aidl
new file mode 100644
index 0000000..7dda011
--- /dev/null
+++ b/audio/aidl/sounddose/aidl_api/android.hardware.audio.sounddose/current/android/hardware/audio/sounddose/ISoundDoseFactory.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <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.sounddose;
+@VintfStability
+interface ISoundDoseFactory {
+ @nullable android.hardware.audio.core.ISoundDose getSoundDose(in @utf8InCpp String module);
+}
diff --git a/audio/aidl/sounddose/android/hardware/audio/sounddose/ISoundDoseFactory.aidl b/audio/aidl/sounddose/android/hardware/audio/sounddose/ISoundDoseFactory.aidl
new file mode 100644
index 0000000..3487237
--- /dev/null
+++ b/audio/aidl/sounddose/android/hardware/audio/sounddose/ISoundDoseFactory.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.sounddose;
+
+import android.hardware.audio.core.ISoundDose;
+
+/**
+ * This interface is used to provide an easy way to implement the ISoundDose interface
+ * without switching the audio HAL to AIDL. The implementation is intended as a workaround
+ * for the certification with IEC62368-1 3rd edition and EN50332-3.
+ * Note that this interface will be deprecated in favor of the audio AIDL HAL.
+ */
+@VintfStability
+interface ISoundDoseFactory {
+ /**
+ * Retrieve the sound dose interface for a given audio HAL module name.
+ *
+ * If a device must comply to IEC62368-1 3rd edition audio safety requirements and is
+ * implementing audio offload decoding or other direct playback paths where volume control
+ * happens below the audio HAL, it must return an instance of the ISoundDose interface.
+ * The same instance must be returned during the lifetime of the HAL module.
+ * If the HAL module does not support sound dose, null must be returned, without throwing
+ * any errors.
+ *
+ * @param module for which we trigger sound dose updates.
+ * @return An instance of the ISoundDose interface implementation.
+ * @throws EX_ILLEGAL_STATE If there was an error creating an instance.
+ */
+ @nullable ISoundDose getSoundDose(in @utf8InCpp String module);
+}
diff --git a/audio/aidl/sounddose/default/Android.bp b/audio/aidl/sounddose/default/Android.bp
new file mode 100644
index 0000000..bd770fa
--- /dev/null
+++ b/audio/aidl/sounddose/default/Android.bp
@@ -0,0 +1,46 @@
+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_defaults {
+ name: "aidlsounddoseservice_defaults",
+ vendor: true,
+ header_libs: [
+ "libsounddoseaidl_headers",
+ ],
+}
+
+cc_library {
+ name: "libsounddoseserviceexampleimpl",
+ defaults: [
+ "aidlsounddoseservice_defaults",
+ "latest_android_media_audio_common_types_ndk_shared",
+ "latest_android_hardware_audio_core_sounddose_ndk_shared",
+ "latest_android_hardware_audio_sounddose_ndk_shared",
+ ],
+ export_include_dirs: ["include"],
+ srcs: [
+ "SoundDoseFactory.cpp",
+ ],
+ shared_libs: [
+ "libaudioservicesounddoseimpl",
+ "libbase",
+ "libbinder_ndk",
+ ],
+
+ visibility: [
+ "//hardware/interfaces/audio/common/all-versions/default/service",
+ ],
+}
+
+cc_library_headers {
+ name: "libsounddoseaidl_headers",
+ export_include_dirs: ["include"],
+ vendor_available: true,
+ host_supported: true,
+}
diff --git a/audio/aidl/sounddose/default/SoundDoseFactory.cpp b/audio/aidl/sounddose/default/SoundDoseFactory.cpp
new file mode 100644
index 0000000..50796d0
--- /dev/null
+++ b/audio/aidl/sounddose/default/SoundDoseFactory.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_SoundDoseFactory"
+
+#include "SoundDoseFactory.h"
+
+#include <android-base/logging.h>
+#include <core-impl/SoundDose.h>
+
+namespace aidl::android::hardware::audio::sounddose {
+
+using ::aidl::android::hardware::audio::core::SoundDose;
+
+ndk::ScopedAStatus SoundDoseFactory::getSoundDose(const std::string& in_module,
+ std::shared_ptr<ISoundDose>* _aidl_return) {
+ auto soundDoseIt = mSoundDoseBinderMap.find(in_module);
+ if (soundDoseIt != mSoundDoseBinderMap.end()) {
+ *_aidl_return = ISoundDose::fromBinder(soundDoseIt->second);
+
+ LOG(DEBUG) << __func__
+ << ": returning cached instance of ISoundDose: " << _aidl_return->get()
+ << " for module " << in_module;
+ return ndk::ScopedAStatus::ok();
+ }
+
+ auto soundDose = ndk::SharedRefBase::make<SoundDose>();
+ mSoundDoseBinderMap[in_module] = soundDose->asBinder();
+ *_aidl_return = soundDose;
+
+ LOG(DEBUG) << __func__ << ": returning new instance of ISoundDose: " << _aidl_return->get()
+ << " for module " << in_module;
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::audio::sounddose
diff --git a/audio/aidl/sounddose/default/include/SoundDoseFactory.h b/audio/aidl/sounddose/default/include/SoundDoseFactory.h
new file mode 100644
index 0000000..4cf3277
--- /dev/null
+++ b/audio/aidl/sounddose/default/include/SoundDoseFactory.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/core/ISoundDose.h>
+#include <aidl/android/hardware/audio/sounddose/BnSoundDoseFactory.h>
+#include <android/binder_interface_utils.h>
+
+#include <unordered_map>
+
+namespace aidl::android::hardware::audio::sounddose {
+
+using ::aidl::android::hardware::audio::core::ISoundDose;
+
+class SoundDoseFactory : public BnSoundDoseFactory {
+ public:
+ ndk::ScopedAStatus getSoundDose(const std::string& module,
+ std::shared_ptr<ISoundDose>* _aidl_return) override;
+
+ private:
+ std::unordered_map<std::string, ndk::SpAIBinder> mSoundDoseBinderMap;
+};
+
+} // namespace aidl::android::hardware::audio::sounddose
diff --git a/audio/aidl/sounddose/vts/Android.bp b/audio/aidl/sounddose/vts/Android.bp
new file mode 100644
index 0000000..88be968
--- /dev/null
+++ b/audio/aidl/sounddose/vts/Android.bp
@@ -0,0 +1,36 @@
+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_test {
+ name: "VtsHalSoundDoseFactoryTargetTest",
+ defaults: [
+ "latest_android_hardware_audio_core_sounddose_ndk_static",
+ "latest_android_hardware_audio_sounddose_ndk_static",
+ "latest_android_media_audio_common_types_ndk_static",
+ "use_libaidlvintf_gtest_helper_static",
+ "VtsHalTargetTestDefaults",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ "libcutils",
+ ],
+ srcs: [
+ "VtsHalSoundDoseFactoryTargetTest.cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-Wthread-safety",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
diff --git a/audio/aidl/sounddose/vts/TEST_MAPPING b/audio/aidl/sounddose/vts/TEST_MAPPING
new file mode 100644
index 0000000..bebeed9
--- /dev/null
+++ b/audio/aidl/sounddose/vts/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "VtsHalSoundDoseFactoryTargetTest"
+ }
+ ]
+}
diff --git a/audio/aidl/sounddose/vts/VtsHalSoundDoseFactoryTargetTest.cpp b/audio/aidl/sounddose/vts/VtsHalSoundDoseFactoryTargetTest.cpp
new file mode 100644
index 0000000..7448c1f
--- /dev/null
+++ b/audio/aidl/sounddose/vts/VtsHalSoundDoseFactoryTargetTest.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VtsHalSoundDose.Factory"
+#include <android-base/logging.h>
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/audio/sounddose/ISoundDoseFactory.h>
+#include <android/binder_manager.h>
+
+#include <memory>
+
+namespace android::hardware::audio::common::testing {
+
+namespace detail {
+
+inline ::testing::AssertionResult assertIsOk(const char* expr, const ::ndk::ScopedAStatus& status) {
+ if (status.isOk()) {
+ return ::testing::AssertionSuccess();
+ }
+ return ::testing::AssertionFailure()
+ << "Expected the transaction \'" << expr << "\' to succeed\n"
+ << " but it has failed with: " << status;
+}
+
+} // namespace detail
+
+} // namespace android::hardware::audio::common::testing
+
+// Test that the transaction status 'isOk'
+#define EXPECT_IS_OK(ret) \
+ EXPECT_PRED_FORMAT1(::android::hardware::audio::common::testing::detail::assertIsOk, ret)
+
+using namespace android;
+
+using aidl::android::hardware::audio::core::ISoundDose;
+using aidl::android::hardware::audio::sounddose::ISoundDoseFactory;
+
+class SoundDoseFactory : public testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override { ASSERT_NO_FATAL_FAILURE(ConnectToService(GetParam())); }
+
+ void TearDown() override {}
+
+ void ConnectToService(const std::string& interfaceName) {
+ ndk::SpAIBinder binder =
+ ndk::SpAIBinder(AServiceManager_waitForService(interfaceName.c_str()));
+ if (binder == nullptr) {
+ LOG(ERROR) << "Failed to get service " << interfaceName;
+ } else {
+ LOG(DEBUG) << "Succeeded to get service " << interfaceName;
+ }
+ soundDoseFactory = ISoundDoseFactory::fromBinder(binder);
+ ASSERT_NE(soundDoseFactory, nullptr);
+ }
+
+ std::shared_ptr<ISoundDoseFactory> soundDoseFactory;
+};
+
+TEST_P(SoundDoseFactory, GetSoundDoseForSameModule) {
+ const std::string module = "primary";
+
+ std::shared_ptr<ISoundDose> soundDose1;
+ EXPECT_IS_OK(soundDoseFactory->getSoundDose(module, &soundDose1));
+
+ if (soundDose1 == nullptr) {
+ LOG(WARNING) << "Primary module does not support sound dose";
+ return;
+ }
+
+ std::shared_ptr<ISoundDose> soundDose2;
+ EXPECT_IS_OK(soundDoseFactory->getSoundDose(module, &soundDose2));
+ EXPECT_NE(nullptr, soundDose2);
+ EXPECT_EQ(soundDose1->asBinder(), soundDose2->asBinder())
+ << "getSoundDose must return the same interface for the same module";
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ SoundDoseFactoryTest, SoundDoseFactory,
+ testing::ValuesIn(android::getAidlHalInstanceNames(ISoundDoseFactory::descriptor)),
+ android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SoundDoseFactory);
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index 068742d..4ca3d9e 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -24,6 +24,7 @@
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
"libaudioaidlcommon",
+ "libaidlcommonsupport",
],
header_libs: ["libaudioaidl_headers"],
cflags: [
@@ -73,13 +74,55 @@
}
cc_test {
+ name: "VtsHalDownmixTargetTest",
+ defaults: ["VtsHalAudioTargetTestDefaults"],
+ srcs: ["VtsHalDownmixTargetTest.cpp"],
+}
+
+cc_test {
+ name: "VtsHalEnvironmentalReverbTargetTest",
+ defaults: ["VtsHalAudioTargetTestDefaults"],
+ srcs: ["VtsHalEnvironmentalReverbTargetTest.cpp"],
+}
+
+cc_test {
name: "VtsHalEqualizerTargetTest",
defaults: ["VtsHalAudioTargetTestDefaults"],
srcs: ["VtsHalEqualizerTargetTest.cpp"],
}
cc_test {
+ name: "VtsHalHapticGeneratorTargetTest",
+ defaults: ["VtsHalAudioTargetTestDefaults"],
+ srcs: ["VtsHalHapticGeneratorTargetTest.cpp"],
+}
+
+cc_test {
name: "VtsHalLoudnessEnhancerTargetTest",
defaults: ["VtsHalAudioTargetTestDefaults"],
srcs: ["VtsHalLoudnessEnhancerTargetTest.cpp"],
}
+
+cc_test {
+ name: "VtsHalVisualizerTargetTest",
+ 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 b649d9e..4add844 100644
--- a/audio/aidl/vts/EffectFactoryHelper.h
+++ b/audio/aidl/vts/EffectFactoryHelper.h
@@ -49,11 +49,11 @@
std::shared_ptr<IFactory> GetFactory() const { return mEffectFactory; }
- static std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>>
- getAllEffectDescriptors(std::string serviceName, std::optional<AudioUuid> type = std::nullopt) {
+ static std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> getAllEffectDescriptors(
+ std::string serviceName, std::optional<AudioUuid> type = std::nullopt) {
AudioHalBinderServiceUtil util;
auto names = android::getAidlHalInstanceNames(serviceName);
- std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>> result;
+ std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> result;
for (const auto& name : names) {
auto factory = IFactory::fromBinder(util.connectToService(name));
@@ -62,16 +62,14 @@
factory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &descs)
.isOk()) {
for (const auto& desc : descs) {
- const auto& id = desc.common.id;
- if (type.has_value() && id.type != type.value()) {
+ if (type.has_value() && desc.common.id.type != type.value()) {
continue;
}
- result.emplace_back(factory, id);
+ result.emplace_back(factory, desc);
}
}
}
}
-
return result;
}
diff --git a/audio/aidl/vts/EffectHelper.h b/audio/aidl/vts/EffectHelper.h
index 73a1f49..7222d4f 100644
--- a/audio/aidl/vts/EffectHelper.h
+++ b/audio/aidl/vts/EffectHelper.h
@@ -58,26 +58,34 @@
class EffectHelper {
public:
static void create(std::shared_ptr<IFactory> factory, std::shared_ptr<IEffect>& effect,
- Descriptor::Identity id, binder_status_t status = EX_NONE) {
+ Descriptor& desc, binder_status_t status = EX_NONE) {
ASSERT_NE(factory, nullptr);
- EXPECT_STATUS(status, factory->createEffect(id.uuid, &effect));
+ auto& id = desc.common.id;
+ ASSERT_STATUS(status, factory->createEffect(id.uuid, &effect));
if (status == EX_NONE) {
ASSERT_NE(effect, nullptr) << id.uuid.toString();
}
}
+ static void destroyIgnoreRet(std::shared_ptr<IFactory> factory,
+ std::shared_ptr<IEffect> effect) {
+ if (factory && effect) {
+ factory->destroyEffect(effect);
+ }
+ }
+
static void destroy(std::shared_ptr<IFactory> factory, std::shared_ptr<IEffect> effect,
binder_status_t status = EX_NONE) {
ASSERT_NE(factory, nullptr);
ASSERT_NE(effect, nullptr);
- EXPECT_STATUS(status, factory->destroyEffect(effect));
+ ASSERT_STATUS(status, factory->destroyEffect(effect));
}
static void open(std::shared_ptr<IEffect> effect, const Parameter::Common& common,
const std::optional<Parameter::Specific>& specific,
IEffect::OpenEffectReturn* ret, binder_status_t status = EX_NONE) {
ASSERT_NE(effect, nullptr);
- EXPECT_STATUS(status, effect->open(common, specific, ret));
+ ASSERT_STATUS(status, effect->open(common, specific, ret));
}
static void open(std::shared_ptr<IEffect> effect, int session = 0,
@@ -85,30 +93,40 @@
ASSERT_NE(effect, nullptr);
Parameter::Common common = EffectHelper::createParamCommon(session);
IEffect::OpenEffectReturn ret;
- open(effect, common, std::nullopt /* specific */, &ret, status);
+ ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, status));
}
+ static void closeIgnoreRet(std::shared_ptr<IEffect> effect) {
+ if (effect) {
+ effect->close();
+ }
+ }
static void close(std::shared_ptr<IEffect> effect, binder_status_t status = EX_NONE) {
if (effect) {
- EXPECT_STATUS(status, effect->close());
+ ASSERT_STATUS(status, effect->close());
}
}
static void getDescriptor(std::shared_ptr<IEffect> effect, Descriptor& desc,
binder_status_t status = EX_NONE) {
ASSERT_NE(effect, nullptr);
- EXPECT_STATUS(status, effect->getDescriptor(&desc));
+ ASSERT_STATUS(status, effect->getDescriptor(&desc));
}
static void expectState(std::shared_ptr<IEffect> effect, State expectState,
binder_status_t status = EX_NONE) {
ASSERT_NE(effect, nullptr);
State state;
- EXPECT_STATUS(status, effect->getState(&state));
- EXPECT_EQ(expectState, state);
+ ASSERT_STATUS(status, effect->getState(&state));
+ ASSERT_EQ(expectState, state);
+ }
+ static void commandIgnoreRet(std::shared_ptr<IEffect> effect, CommandId command) {
+ if (effect) {
+ effect->command(command);
+ }
}
static void command(std::shared_ptr<IEffect> effect, CommandId command,
binder_status_t status = EX_NONE) {
ASSERT_NE(effect, nullptr);
- EXPECT_STATUS(status, effect->command(command));
+ ASSERT_STATUS(status, effect->command(command));
}
static void allocateInputData(const Parameter::Common common, std::unique_ptr<DataMQ>& mq,
std::vector<float>& buffer) {
@@ -116,29 +134,29 @@
auto frameSize = android::hardware::audio::common::getFrameSizeInBytes(
common.input.base.format, common.input.base.channelMask);
const size_t floatsToWrite = mq->availableToWrite();
- EXPECT_NE(0UL, floatsToWrite);
- EXPECT_EQ(frameSize * common.input.frameCount, floatsToWrite * sizeof(float));
+ ASSERT_NE(0UL, floatsToWrite);
+ ASSERT_EQ(frameSize * common.input.frameCount, floatsToWrite * sizeof(float));
buffer.resize(floatsToWrite);
std::fill(buffer.begin(), buffer.end(), 0x5a);
}
static void writeToFmq(std::unique_ptr<DataMQ>& mq, const std::vector<float>& buffer) {
const size_t available = mq->availableToWrite();
- EXPECT_NE(0Ul, available);
+ ASSERT_NE(0Ul, available);
auto bufferFloats = buffer.size();
auto floatsToWrite = std::min(available, bufferFloats);
- EXPECT_TRUE(mq->write(buffer.data(), floatsToWrite));
+ ASSERT_TRUE(mq->write(buffer.data(), floatsToWrite));
}
static void readFromFmq(std::unique_ptr<StatusMQ>& statusMq, size_t statusNum,
std::unique_ptr<DataMQ>& dataMq, size_t expectFloats,
std::vector<float>& buffer) {
IEffect::Status status{};
- EXPECT_TRUE(statusMq->readBlocking(&status, statusNum));
- EXPECT_EQ(STATUS_OK, status.status);
+ ASSERT_TRUE(statusMq->readBlocking(&status, statusNum));
+ ASSERT_EQ(STATUS_OK, status.status);
if (statusNum != 0) {
- EXPECT_EQ(expectFloats, (unsigned)status.fmqProduced);
- EXPECT_EQ(expectFloats, dataMq->availableToRead());
+ ASSERT_EQ(expectFloats, (unsigned)status.fmqProduced);
+ ASSERT_EQ(expectFloats, dataMq->availableToRead());
if (expectFloats != 0) {
- EXPECT_TRUE(dataMq->read(buffer.data(), expectFloats));
+ ASSERT_TRUE(dataMq->read(buffer.data(), expectFloats));
}
}
}
diff --git a/audio/aidl/vts/TestUtils.h b/audio/aidl/vts/TestUtils.h
index 5e4d56a..4c1d42c 100644
--- a/audio/aidl/vts/TestUtils.h
+++ b/audio/aidl/vts/TestUtils.h
@@ -16,6 +16,8 @@
#pragma once
+#include <algorithm>
+#include <initializer_list>
#include <iostream>
#include <android/binder_auto_utils.h>
@@ -45,6 +47,19 @@
<< "\n but is has completed with: " << status;
}
+template <typename T>
+inline ::testing::AssertionResult assertResult(const char* exp_expr, const char* act_expr,
+ const std::initializer_list<T>& expected,
+ const ::ndk::ScopedAStatus& status) {
+ if (std::find(expected.begin(), expected.end(), status.getExceptionCode()) != expected.end()) {
+ return ::testing::AssertionSuccess();
+ }
+ return ::testing::AssertionFailure() << "Expected the transaction \'" << act_expr
+ << "\' to complete with one of: " << exp_expr
+ << "\n which is: " << ::testing::PrintToString(expected)
+ << "\n but is has completed with: " << status;
+}
+
} // namespace detail
} // namespace android::hardware::audio::common::testing
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/VtsHalAudioCoreConfigTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
index bf73648..e7f5817 100644
--- a/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
@@ -10,6 +10,8 @@
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
#include <aidl/android/hardware/audio/core/IConfig.h>
+#include <aidl/android/media/audio/common/AudioFlag.h>
+#include <aidl/android/media/audio/common/AudioProductStrategyType.h>
#include "AudioHalBinderServiceUtil.h"
#include "TestUtils.h"
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index 99771e6..2508afd 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -36,6 +36,7 @@
#include <aidl/Vintf.h>
#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
#include <aidl/android/hardware/audio/core/IModule.h>
+#include <aidl/android/hardware/audio/core/ISoundDose.h>
#include <aidl/android/hardware/audio/core/ITelephony.h>
#include <aidl/android/media/audio/common/AudioIoFlags.h>
#include <aidl/android/media/audio/common/AudioOutputFlags.h>
@@ -56,6 +57,8 @@
using aidl::android::hardware::audio::core::AudioPatch;
using aidl::android::hardware::audio::core::AudioRoute;
using aidl::android::hardware::audio::core::IModule;
+using aidl::android::hardware::audio::core::ISoundDose;
+using aidl::android::hardware::audio::core::IStreamCommon;
using aidl::android::hardware::audio::core::IStreamIn;
using aidl::android::hardware::audio::core::IStreamOut;
using aidl::android::hardware::audio::core::ITelephony;
@@ -63,6 +66,7 @@
using aidl::android::hardware::audio::core::MicrophoneInfo;
using aidl::android::hardware::audio::core::ModuleDebug;
using aidl::android::hardware::audio::core::StreamDescriptor;
+using aidl::android::hardware::audio::core::VendorParameter;
using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
using aidl::android::media::audio::common::AudioContentType;
using aidl::android::media::audio::common::AudioDevice;
@@ -78,6 +82,7 @@
using aidl::android::media::audio::common::AudioSource;
using aidl::android::media::audio::common::AudioUsage;
using aidl::android::media::audio::common::Void;
+using android::hardware::audio::common::getChannelCount;
using android::hardware::audio::common::isBitPositionFlagSet;
using android::hardware::audio::common::isTelephonyDeviceType;
using android::hardware::audio::common::StreamLogic;
@@ -185,6 +190,29 @@
AudioPortConfig mConfig;
};
+template <typename T>
+void GenerateTestArrays(size_t validElementCount, T validMin, T validMax,
+ std::vector<std::vector<T>>* validValues,
+ std::vector<std::vector<T>>* invalidValues) {
+ validValues->emplace_back(validElementCount, validMin);
+ validValues->emplace_back(validElementCount, validMax);
+ validValues->emplace_back(validElementCount, (validMin + validMax) / 2.f);
+ if (validElementCount > 0) {
+ invalidValues->emplace_back(validElementCount - 1, validMin);
+ }
+ invalidValues->emplace_back(validElementCount + 1, validMin);
+ for (auto m : {-2, -1, 2}) {
+ const auto invalidMin = m * validMin;
+ if (invalidMin < validMin || invalidMin > validMax) {
+ invalidValues->emplace_back(validElementCount, invalidMin);
+ }
+ const auto invalidMax = m * validMax;
+ if (invalidMax < validMin || invalidMax > validMax) {
+ invalidValues->emplace_back(validElementCount, invalidMax);
+ }
+ }
+}
+
template <typename PropType, class Instance, typename Getter, typename Setter>
void TestAccessors(Instance* inst, Getter getter, Setter setter,
const std::vector<PropType>& validValues,
@@ -198,17 +226,68 @@
ASSERT_TRUE(status.isOk()) << "Unexpected status from a getter: " << status;
*isSupported = true;
for (const auto v : validValues) {
- EXPECT_IS_OK((inst->*setter)(v)) << "for valid value: " << v;
+ EXPECT_IS_OK((inst->*setter)(v)) << "for a valid value: " << ::testing::PrintToString(v);
PropType currentValue{};
EXPECT_IS_OK((inst->*getter)(¤tValue));
EXPECT_EQ(v, currentValue);
}
for (const auto v : invalidValues) {
- EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, (inst->*setter)(v)) << "for invalid value: " << v;
+ EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, (inst->*setter)(v))
+ << "for an invalid value: " << ::testing::PrintToString(v);
}
EXPECT_IS_OK((inst->*setter)(initialValue)) << "Failed to restore the initial value";
}
+template <class Instance>
+void TestGetVendorParameters(Instance* inst, bool* isSupported) {
+ static const std::vector<std::vector<std::string>> kIdsLists = {{}, {"zero"}, {"one", "two"}};
+ static const auto kStatuses = {EX_ILLEGAL_ARGUMENT, EX_ILLEGAL_STATE, EX_UNSUPPORTED_OPERATION};
+ for (const auto& ids : kIdsLists) {
+ std::vector<VendorParameter> params;
+ if (ndk::ScopedAStatus status = inst->getVendorParameters(ids, ¶ms); status.isOk()) {
+ EXPECT_EQ(ids.size(), params.size()) << "Size of the returned parameters list must "
+ << "match the size of the provided ids list";
+ for (const auto& param : params) {
+ EXPECT_NE(ids.end(), std::find(ids.begin(), ids.end(), param.id))
+ << "Returned parameter id \"" << param.id << "\" is unexpected";
+ }
+ for (const auto& id : ids) {
+ EXPECT_NE(params.end(),
+ std::find_if(params.begin(), params.end(),
+ [&](const auto& param) { return param.id == id; }))
+ << "Requested parameter with id \"" << id << "\" was not returned";
+ }
+ } else {
+ EXPECT_STATUS(kStatuses, status);
+ if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+ *isSupported = false;
+ return;
+ }
+ }
+ }
+ *isSupported = true;
+}
+
+template <class Instance>
+void TestSetVendorParameters(Instance* inst, bool* isSupported) {
+ static const auto kStatuses = {EX_NONE, EX_ILLEGAL_ARGUMENT, EX_ILLEGAL_STATE,
+ EX_UNSUPPORTED_OPERATION};
+ static const std::vector<std::vector<VendorParameter>> kParamsLists = {
+ {}, {VendorParameter{"zero"}}, {VendorParameter{"one"}, VendorParameter{"two"}}};
+ for (const auto& params : kParamsLists) {
+ ndk::ScopedAStatus status = inst->setVendorParameters(params, false);
+ if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+ *isSupported = false;
+ return;
+ }
+ EXPECT_STATUS(kStatuses, status)
+ << ::android::internal::ToString(params) << ", async: false";
+ EXPECT_STATUS(kStatuses, inst->setVendorParameters(params, true))
+ << ::android::internal::ToString(params) << ", async: true";
+ }
+ *isSupported = true;
+}
+
// Can be used as a base for any test here, does not depend on the fixture GTest parameters.
class AudioCoreModuleBase {
public:
@@ -835,6 +914,13 @@
template <typename Stream>
class WithStream {
public:
+ static ndk::ScopedAStatus callClose(std::shared_ptr<Stream> stream) {
+ std::shared_ptr<IStreamCommon> common;
+ ndk::ScopedAStatus status = stream->getStreamCommon(&common);
+ if (!status.isOk()) return status;
+ return common->close();
+ }
+
WithStream() {}
explicit WithStream(const AudioPortConfig& portConfig) : mPortConfig(portConfig) {}
WithStream(const WithStream&) = delete;
@@ -842,7 +928,7 @@
~WithStream() {
if (mStream != nullptr) {
mContext.reset();
- EXPECT_IS_OK(mStream->close()) << "port config id " << getPortId();
+ EXPECT_IS_OK(callClose(mStream)) << "port config id " << getPortId();
}
}
void SetUpPortConfig(IModule* module) { ASSERT_NO_FATAL_FAILURE(mPortConfig.SetUp(module)); }
@@ -1626,6 +1712,67 @@
EXPECT_IS_OK(module->updateScreenState(true));
}
+TEST_P(AudioCoreModule, GenerateHwAvSyncId) {
+ const auto kStatuses = {EX_NONE, EX_ILLEGAL_STATE};
+ int32_t id1;
+ ndk::ScopedAStatus status = module->generateHwAvSyncId(&id1);
+ if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+ GTEST_SKIP() << "HW AV Sync is not supported";
+ }
+ EXPECT_STATUS(kStatuses, status);
+ if (status.isOk()) {
+ int32_t id2;
+ ASSERT_IS_OK(module->generateHwAvSyncId(&id2));
+ EXPECT_NE(id1, id2) << "HW AV Sync IDs must be unique";
+ }
+}
+
+TEST_P(AudioCoreModule, GetVendorParameters) {
+ bool isGetterSupported = false;
+ EXPECT_NO_FATAL_FAILURE(TestGetVendorParameters(module.get(), &isGetterSupported));
+ ndk::ScopedAStatus status = module->setVendorParameters({}, false);
+ EXPECT_EQ(isGetterSupported, status.getExceptionCode() != EX_UNSUPPORTED_OPERATION)
+ << "Support for getting and setting of vendor parameters must be consistent";
+ if (!isGetterSupported) {
+ GTEST_SKIP() << "Vendor parameters are not supported";
+ }
+}
+
+TEST_P(AudioCoreModule, SetVendorParameters) {
+ bool isSupported = false;
+ EXPECT_NO_FATAL_FAILURE(TestSetVendorParameters(module.get(), &isSupported));
+ if (!isSupported) {
+ GTEST_SKIP() << "Vendor parameters are not supported";
+ }
+}
+
+// See b/262930731. In the absence of offloaded effect implementations,
+// currently we can only pass a nullptr, and the HAL module must either reject
+// it as an invalid argument, or say that offloaded effects are not supported.
+TEST_P(AudioCoreModule, AddRemoveEffectInvalidArguments) {
+ ndk::ScopedAStatus addEffectStatus = module->addDeviceEffect(-1, nullptr);
+ ndk::ScopedAStatus removeEffectStatus = module->removeDeviceEffect(-1, nullptr);
+ const bool isSupported = addEffectStatus.getExceptionCode() != EX_UNSUPPORTED_OPERATION;
+ if (isSupported) {
+ EXPECT_EQ(EX_ILLEGAL_ARGUMENT, addEffectStatus.getExceptionCode());
+ EXPECT_EQ(EX_ILLEGAL_ARGUMENT, removeEffectStatus.getExceptionCode());
+ } else if (EX_UNSUPPORTED_OPERATION != removeEffectStatus.getExceptionCode()) {
+ GTEST_FAIL() << "addEffect and removeEffect must be either supported or not supported "
+ << "together";
+ } else {
+ GTEST_SKIP() << "Offloaded effects not supported";
+ }
+ // Test rejection of a nullptr effect with a valid device port Id.
+ ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
+ const auto configs = moduleConfig->getPortConfigsForAttachedDevicePorts();
+ for (const auto& config : configs) {
+ WithAudioPortConfig portConfig(config);
+ ASSERT_NO_FATAL_FAILURE(portConfig.SetUp(module.get()));
+ EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->addDeviceEffect(portConfig.getId(), nullptr));
+ EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->removeDeviceEffect(portConfig.getId(), nullptr));
+ }
+}
+
class AudioCoreTelephony : public AudioCoreModuleBase, public testing::TestWithParam<std::string> {
public:
void SetUp() override {
@@ -1731,6 +1878,23 @@
ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
}
+ void GetStreamCommon() {
+ const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
+ if (!portConfig.has_value()) {
+ GTEST_SKIP() << "No mix port for attached devices";
+ }
+ WithStream<Stream> stream(portConfig.value());
+ ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+ std::shared_ptr<IStreamCommon> streamCommon1;
+ EXPECT_IS_OK(stream.get()->getStreamCommon(&streamCommon1));
+ std::shared_ptr<IStreamCommon> streamCommon2;
+ EXPECT_IS_OK(stream.get()->getStreamCommon(&streamCommon2));
+ ASSERT_NE(nullptr, streamCommon1);
+ ASSERT_NE(nullptr, streamCommon2);
+ EXPECT_EQ(streamCommon1->asBinder(), streamCommon2->asBinder())
+ << "getStreamCommon must return the same interface instance across invocations";
+ }
+
void CloseTwice() {
const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
if (!portConfig.has_value()) {
@@ -1742,7 +1906,8 @@
ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
heldStream = stream.getSharedPointer();
}
- EXPECT_STATUS(EX_ILLEGAL_STATE, heldStream->close()) << "when closing the stream twice";
+ EXPECT_STATUS(EX_ILLEGAL_STATE, WithStream<Stream>::callClose(heldStream))
+ << "when closing the stream twice";
}
void OpenAllConfigs() {
@@ -1761,9 +1926,7 @@
}
WithStream<Stream> stream(portConfig.value());
ASSERT_NO_FATAL_FAILURE(stream.SetUpPortConfig(module.get()));
- // The buffer size of 1 frame should be impractically small, and thus
- // less than any minimum buffer size suggested by any HAL.
- for (long bufferSize : std::array<long, 4>{-1, 0, 1, std::numeric_limits<long>::max()}) {
+ for (long bufferSize : std::array<long, 3>{-1, 0, std::numeric_limits<long>::max()}) {
EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, stream.SetUpNoChecks(module.get(), bufferSize))
<< "for the buffer size " << bufferSize;
EXPECT_EQ(nullptr, stream.get());
@@ -1847,6 +2010,138 @@
EXPECT_NO_FATAL_FAILURE(SendInvalidCommandImpl(portConfig.value()));
}
+ void UpdateHwAvSyncId() {
+ const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
+ if (!portConfig.has_value()) {
+ GTEST_SKIP() << "No mix port for attached devices";
+ }
+ WithStream<Stream> stream(portConfig.value());
+ ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+ std::shared_ptr<IStreamCommon> streamCommon;
+ ASSERT_IS_OK(stream.get()->getStreamCommon(&streamCommon));
+ ASSERT_NE(nullptr, streamCommon);
+ const auto kStatuses = {EX_NONE, EX_ILLEGAL_ARGUMENT, EX_ILLEGAL_STATE};
+ for (const auto id : {-100, -1, 0, 1, 100}) {
+ ndk::ScopedAStatus status = streamCommon->updateHwAvSyncId(id);
+ if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+ GTEST_SKIP() << "HW AV Sync is not supported";
+ }
+ EXPECT_STATUS(kStatuses, status) << "id: " << id;
+ }
+ }
+
+ void GetVendorParameters() {
+ const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
+ if (!portConfig.has_value()) {
+ GTEST_SKIP() << "No mix port for attached devices";
+ }
+ WithStream<Stream> stream(portConfig.value());
+ ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+ std::shared_ptr<IStreamCommon> streamCommon;
+ ASSERT_IS_OK(stream.get()->getStreamCommon(&streamCommon));
+ ASSERT_NE(nullptr, streamCommon);
+
+ bool isGetterSupported = false;
+ EXPECT_NO_FATAL_FAILURE(TestGetVendorParameters(module.get(), &isGetterSupported));
+ ndk::ScopedAStatus status = module->setVendorParameters({}, false);
+ EXPECT_EQ(isGetterSupported, status.getExceptionCode() != EX_UNSUPPORTED_OPERATION)
+ << "Support for getting and setting of vendor parameters must be consistent";
+ if (!isGetterSupported) {
+ GTEST_SKIP() << "Vendor parameters are not supported";
+ }
+ }
+
+ void SetVendorParameters() {
+ const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
+ if (!portConfig.has_value()) {
+ GTEST_SKIP() << "No mix port for attached devices";
+ }
+ WithStream<Stream> stream(portConfig.value());
+ ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+ std::shared_ptr<IStreamCommon> streamCommon;
+ ASSERT_IS_OK(stream.get()->getStreamCommon(&streamCommon));
+ ASSERT_NE(nullptr, streamCommon);
+
+ bool isSupported = false;
+ EXPECT_NO_FATAL_FAILURE(TestSetVendorParameters(module.get(), &isSupported));
+ if (!isSupported) {
+ GTEST_SKIP() << "Vendor parameters are not supported";
+ }
+ }
+
+ void HwGainHwVolume() {
+ const auto ports =
+ moduleConfig->getMixPorts(IOTraits<Stream>::is_input, false /*attachedOnly*/);
+ if (ports.empty()) {
+ GTEST_SKIP() << "No mix ports";
+ }
+ bool atLeastOneSupports = false;
+ for (const auto& port : ports) {
+ const auto portConfig = moduleConfig->getSingleConfigForMixPort(true, port);
+ if (!portConfig.has_value()) continue;
+ WithStream<Stream> stream(portConfig.value());
+ ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+ std::vector<std::vector<float>> validValues, invalidValues;
+ bool isSupported = false;
+ if constexpr (IOTraits<Stream>::is_input) {
+ GenerateTestArrays<float>(getChannelCount(portConfig.value().channelMask.value()),
+ IStreamIn::HW_GAIN_MIN, IStreamIn::HW_GAIN_MAX,
+ &validValues, &invalidValues);
+ EXPECT_NO_FATAL_FAILURE(TestAccessors<std::vector<float>>(
+ stream.get(), &IStreamIn::getHwGain, &IStreamIn::setHwGain, validValues,
+ invalidValues, &isSupported));
+ } else {
+ GenerateTestArrays<float>(getChannelCount(portConfig.value().channelMask.value()),
+ IStreamOut::HW_VOLUME_MIN, IStreamOut::HW_VOLUME_MAX,
+ &validValues, &invalidValues);
+ EXPECT_NO_FATAL_FAILURE(TestAccessors<std::vector<float>>(
+ stream.get(), &IStreamOut::getHwVolume, &IStreamOut::setHwVolume,
+ validValues, invalidValues, &isSupported));
+ }
+ if (isSupported) atLeastOneSupports = true;
+ }
+ if (!atLeastOneSupports) {
+ GTEST_SKIP() << "Hardware gain / volume is not supported";
+ }
+ }
+
+ // See b/262930731. In the absence of offloaded effect implementations,
+ // currently we can only pass a nullptr, and the HAL module must either reject
+ // it as an invalid argument, or say that offloaded effects are not supported.
+ void AddRemoveEffectInvalidArguments() {
+ const auto ports =
+ moduleConfig->getMixPorts(IOTraits<Stream>::is_input, false /*attachedOnly*/);
+ if (ports.empty()) {
+ GTEST_SKIP() << "No mix ports";
+ }
+ bool atLeastOneSupports = false;
+ for (const auto& port : ports) {
+ const auto portConfig = moduleConfig->getSingleConfigForMixPort(true, port);
+ if (!portConfig.has_value()) continue;
+ WithStream<Stream> stream(portConfig.value());
+ ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+ std::shared_ptr<IStreamCommon> streamCommon;
+ ASSERT_IS_OK(stream.get()->getStreamCommon(&streamCommon));
+ ASSERT_NE(nullptr, streamCommon);
+ ndk::ScopedAStatus addEffectStatus = streamCommon->addEffect(nullptr);
+ ndk::ScopedAStatus removeEffectStatus = streamCommon->removeEffect(nullptr);
+ const bool isSupported = addEffectStatus.getExceptionCode() != EX_UNSUPPORTED_OPERATION;
+ if (isSupported) {
+ EXPECT_EQ(EX_ILLEGAL_ARGUMENT, addEffectStatus.getExceptionCode());
+ EXPECT_EQ(EX_ILLEGAL_ARGUMENT, removeEffectStatus.getExceptionCode());
+ atLeastOneSupports = true;
+ } else if (EX_UNSUPPORTED_OPERATION != removeEffectStatus.getExceptionCode()) {
+ ADD_FAILURE()
+ << "addEffect and removeEffect must be either supported or not supported "
+ << "together";
+ atLeastOneSupports = true;
+ }
+ }
+ if (!atLeastOneSupports) {
+ GTEST_SKIP() << "Offloaded effects not supported";
+ }
+ }
+
void OpenTwiceSamePortConfigImpl(const AudioPortConfig& portConfig) {
WithStream<Stream> stream1(portConfig);
ASSERT_NO_FATAL_FAILURE(stream1.SetUp(module.get(), kDefaultBufferSizeFrames));
@@ -1912,6 +2207,7 @@
}
TEST_IN_AND_OUT_STREAM(CloseTwice);
+TEST_IN_AND_OUT_STREAM(GetStreamCommon);
TEST_IN_AND_OUT_STREAM(OpenAllConfigs);
TEST_IN_AND_OUT_STREAM(OpenInvalidBufferSize);
TEST_IN_AND_OUT_STREAM(OpenInvalidDirection);
@@ -1919,6 +2215,11 @@
TEST_IN_AND_OUT_STREAM(OpenTwiceSamePortConfig);
TEST_IN_AND_OUT_STREAM(ResetPortConfigWithOpenStream);
TEST_IN_AND_OUT_STREAM(SendInvalidCommand);
+TEST_IN_AND_OUT_STREAM(UpdateHwAvSyncId);
+TEST_IN_AND_OUT_STREAM(GetVendorParameters);
+TEST_IN_AND_OUT_STREAM(SetVendorParameters);
+TEST_IN_AND_OUT_STREAM(HwGainHwVolume);
+TEST_IN_AND_OUT_STREAM(AddRemoveEffectInvalidArguments);
namespace aidl::android::hardware::audio::core {
std::ostream& operator<<(std::ostream& os, const IStreamIn::MicrophoneDirection& md) {
@@ -2468,6 +2769,92 @@
}
}
+class AudioCoreSoundDose : public AudioCoreModuleBase, public testing::TestWithParam<std::string> {
+ public:
+ class NoOpHalSoundDoseCallback : public ISoundDose::BnHalSoundDoseCallback {
+ public:
+ ndk::ScopedAStatus onMomentaryExposureWarning(float in_currentDbA,
+ const AudioDevice& in_audioDevice) override;
+ ndk::ScopedAStatus onNewMelValues(
+ const ISoundDose::IHalSoundDoseCallback::MelRecord& in_melRecord,
+ const AudioDevice& in_audioDevice) override;
+ };
+
+ void SetUp() override {
+ ASSERT_NO_FATAL_FAILURE(SetUpImpl(GetParam()));
+ ASSERT_IS_OK(module->getSoundDose(&soundDose));
+ callback = ndk::SharedRefBase::make<NoOpHalSoundDoseCallback>();
+ }
+
+ void TearDown() override { ASSERT_NO_FATAL_FAILURE(TearDownImpl()); }
+
+ std::shared_ptr<ISoundDose> soundDose;
+ std::shared_ptr<ISoundDose::IHalSoundDoseCallback> callback;
+};
+
+ndk::ScopedAStatus AudioCoreSoundDose::NoOpHalSoundDoseCallback::onMomentaryExposureWarning(
+ float in_currentDbA, const AudioDevice& in_audioDevice) {
+ // Do nothing
+ (void)in_currentDbA;
+ (void)in_audioDevice;
+ LOG(INFO) << "NoOpHalSoundDoseCallback::onMomentaryExposureWarning called";
+
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus AudioCoreSoundDose::NoOpHalSoundDoseCallback::onNewMelValues(
+ const ISoundDose::IHalSoundDoseCallback::MelRecord& in_melRecord,
+ const AudioDevice& in_audioDevice) {
+ // Do nothing
+ (void)in_melRecord;
+ (void)in_audioDevice;
+ LOG(INFO) << "NoOpHalSoundDoseCallback::onNewMelValues called";
+
+ return ndk::ScopedAStatus::ok();
+}
+
+TEST_P(AudioCoreSoundDose, GetSetOutputRs2) {
+ if (soundDose == nullptr) {
+ GTEST_SKIP() << "SoundDose is not supported";
+ }
+
+ bool isSupported = false;
+ EXPECT_NO_FATAL_FAILURE(TestAccessors<float>(soundDose.get(), &ISoundDose::getOutputRs2,
+ &ISoundDose::setOutputRs2,
+ /*validValues=*/{80.f, 90.f, 100.f},
+ /*invalidValues=*/{79.f, 101.f}, &isSupported));
+ EXPECT_TRUE(isSupported) << "Getting/Setting RS2 must be supported";
+}
+
+TEST_P(AudioCoreSoundDose, CheckDefaultRs2Value) {
+ if (soundDose == nullptr) {
+ GTEST_SKIP() << "SoundDose is not supported";
+ }
+
+ float rs2Value;
+ ASSERT_IS_OK(soundDose->getOutputRs2(&rs2Value));
+ EXPECT_EQ(rs2Value, ISoundDose::DEFAULT_MAX_RS2);
+}
+
+TEST_P(AudioCoreSoundDose, RegisterSoundDoseCallbackTwiceThrowsException) {
+ if (soundDose == nullptr) {
+ GTEST_SKIP() << "SoundDose is not supported";
+ }
+
+ ASSERT_IS_OK(soundDose->registerSoundDoseCallback(callback));
+ EXPECT_STATUS(EX_ILLEGAL_STATE, soundDose->registerSoundDoseCallback(callback))
+ << "Registering sound dose callback twice should throw EX_ILLEGAL_STATE";
+}
+
+TEST_P(AudioCoreSoundDose, RegisterSoundDoseNullCallbackThrowsException) {
+ if (soundDose == nullptr) {
+ GTEST_SKIP() << "SoundDose is not supported";
+ }
+
+ EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, soundDose->registerSoundDoseCallback(nullptr))
+ << "Registering nullptr sound dose callback should throw EX_ILLEGAL_ARGUMENT";
+}
+
INSTANTIATE_TEST_SUITE_P(AudioCoreModuleTest, AudioCoreModule,
testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
android::PrintInstanceNameToString);
@@ -2484,6 +2871,10 @@
testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
android::PrintInstanceNameToString);
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioStreamOut);
+INSTANTIATE_TEST_SUITE_P(AudioCoreSoundDoseTest, AudioCoreSoundDose,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
+ android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioCoreSoundDose);
// This is the value used in test sequences for which the test needs to ensure
// that the HAL stays in a transient state long enough to receive the next command.
diff --git a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
index 4f14bf0..8938618 100644
--- a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
@@ -49,18 +49,30 @@
using aidl::android::hardware::audio::effect::State;
enum ParamName { PARAM_INSTANCE_NAME };
-using EffectTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>>;
+using EffectTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>>;
class AudioEffectTest : public testing::TestWithParam<EffectTestParam>, public EffectHelper {
public:
- AudioEffectTest() { std::tie(mFactory, mIdentity) = std::get<PARAM_INSTANCE_NAME>(GetParam()); }
+ AudioEffectTest() {
+ std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
+ }
void SetUp() override {}
- void TearDown() override {}
+
+ void TearDown() override {
+ // Do the cleanup for every test case
+ if (mEffect) {
+ ASSERT_NO_FATAL_FAILURE(commandIgnoreRet(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(closeIgnoreRet(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroyIgnoreRet(mFactory, mEffect));
+ mEffect.reset();
+ }
+ }
static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
std::shared_ptr<IFactory> mFactory;
- Descriptor::Identity mIdentity;
+ std::shared_ptr<IEffect> mEffect;
+ Descriptor mDescriptor;
};
TEST_P(AudioEffectTest, SetupAndTearDown) {
@@ -68,30 +80,27 @@
}
TEST_P(AudioEffectTest, CreateAndDestroy) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
TEST_P(AudioEffectTest, OpenAndClose) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
TEST_P(AudioEffectTest, CloseUnopenedEffect) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
TEST_P(AudioEffectTest, DoubleOpenAndClose) {
std::shared_ptr<IEffect> effect1, effect2;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect1, mIdentity));
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect2, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect1, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect2, mDescriptor));
ASSERT_NO_FATAL_FAILURE(open(effect1));
ASSERT_NO_FATAL_FAILURE(open(effect2, 1 /* session */));
ASSERT_NO_FATAL_FAILURE(close(effect1));
@@ -102,9 +111,9 @@
TEST_P(AudioEffectTest, TripleOpenAndClose) {
std::shared_ptr<IEffect> effect1, effect2, effect3;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect1, mIdentity));
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect2, mIdentity));
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect3, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect1, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect2, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect3, mDescriptor));
ASSERT_NO_FATAL_FAILURE(open(effect1));
ASSERT_NO_FATAL_FAILURE(open(effect2, 1 /* session */));
ASSERT_NO_FATAL_FAILURE(open(effect3, 2 /* session */));
@@ -117,513 +126,505 @@
}
TEST_P(AudioEffectTest, GetDescritorBeforeOpen) {
- std::shared_ptr<IEffect> effect;
Descriptor desc;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(getDescriptor(effect, desc));
- EXPECT_EQ(mIdentity.toString(), desc.common.id.toString());
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(getDescriptor(mEffect, desc));
+ EXPECT_EQ(mDescriptor.common, desc.common);
+ // Effect implementation Must fill in implementor and name
EXPECT_NE("", desc.common.name);
EXPECT_NE("", desc.common.implementor);
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
TEST_P(AudioEffectTest, GetDescritorAfterOpen) {
- std::shared_ptr<IEffect> effect;
Descriptor beforeOpen, afterOpen, afterClose;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(getDescriptor(effect, beforeOpen));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(getDescriptor(effect, afterOpen));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(getDescriptor(mEffect, beforeOpen));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(getDescriptor(mEffect, afterOpen));
EXPECT_EQ(beforeOpen.toString(), afterOpen.toString()) << "\n"
<< beforeOpen.toString() << "\n"
<< afterOpen.toString();
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(getDescriptor(effect, afterClose));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(getDescriptor(mEffect, afterClose));
EXPECT_EQ(beforeOpen.toString(), afterClose.toString()) << "\n"
<< beforeOpen.toString() << "\n"
<< afterClose.toString();
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
TEST_P(AudioEffectTest, DescriptorExistAndUnique) {
- std::shared_ptr<IEffect> effect;
Descriptor desc;
auto descList = EffectFactoryHelper::getAllEffectDescriptors(IFactory::descriptor);
std::set<Descriptor::Identity> idSet;
for (const auto& it : descList) {
- auto& id = it.second;
+ auto& id = it.second.common.id;
EXPECT_EQ(0ul, idSet.count(id));
idSet.insert(id);
}
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(getDescriptor(effect, desc));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(getDescriptor(mEffect, desc));
EXPECT_EQ(1ul, idSet.count(desc.common.id));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
/// State testing.
// An effect instance is in INIT state by default after it was created.
TEST_P(AudioEffectTest, InitStateAfterCreation) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::INIT));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::INIT));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// An effect instance transfer to IDLE state after IEffect.ASSERT_NO_FATAL_FAILURE(open().
TEST_P(AudioEffectTest, IdleStateAfterOpen) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// An effect instance is in PROCESSING state after it receive an START command.
TEST_P(AudioEffectTest, ProcessingStateAfterStart) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::INIT));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::INIT));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// An effect instance transfer to IDLE state after Command.Id.STOP in PROCESSING state.
TEST_P(AudioEffectTest, IdleStateAfterStop) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// An effect instance transfer to IDLE state after Command.Id.RESET in PROCESSING state.
TEST_P(AudioEffectTest, IdleStateAfterReset) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::RESET));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// An effect instance transfer to INIT after IEffect.ASSERT_NO_FATAL_FAILURE(close().
TEST_P(AudioEffectTest, InitStateAfterClose) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::INIT));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::INIT));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// An effect instance shouldn't accept any command before open.
TEST_P(AudioEffectTest, NoCommandAcceptedBeforeOpen) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START, EX_ILLEGAL_STATE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP, EX_ILLEGAL_STATE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET, EX_ILLEGAL_STATE));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START, EX_ILLEGAL_STATE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP, EX_ILLEGAL_STATE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::RESET, EX_ILLEGAL_STATE));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// No-op when receive STOP command in IDLE state.
TEST_P(AudioEffectTest, StopCommandInIdleStateNoOp) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// No-op when receive RESET command in IDLE state.
TEST_P(AudioEffectTest, ResetCommandInIdleStateNoOp) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::RESET));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Repeat START and STOP command.
TEST_P(AudioEffectTest, RepeatStartAndStop) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Repeat START and RESET command.
TEST_P(AudioEffectTest, RepeatStartAndReset) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::RESET));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::RESET));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Try to close an effect instance at PROCESSING state.
TEST_P(AudioEffectTest, CloseProcessingStateEffects) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(close(effect, EX_ILLEGAL_STATE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect, EX_ILLEGAL_STATE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
TEST_P(AudioEffectTest, DestroyOpenEffects) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect, EX_ILLEGAL_STATE));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect, EX_ILLEGAL_STATE));
+
+ // cleanup
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
TEST_P(AudioEffectTest, DestroyProcessingEffects) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect, EX_ILLEGAL_STATE));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect, EX_ILLEGAL_STATE));
+
+ // cleanup
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
TEST_P(AudioEffectTest, NormalSequenceStates) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::INIT));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::INIT));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::RESET));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
/// Parameter testing.
// Verify parameters pass in open can be successfully get.
TEST_P(AudioEffectTest, VerifyCommonParametersAfterOpen) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Common common = EffectHelper::createParamCommon();
IEffect::OpenEffectReturn ret;
- ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt /* specific */, &ret, EX_NONE));
Parameter get = Parameter(), expect = Parameter();
expect.set<Parameter::common>(common);
Parameter::Id id;
id.set<Parameter::Id::commonTag>(Parameter::common);
- EXPECT_IS_OK(effect->getParameter(id, &get));
+ EXPECT_IS_OK(mEffect->getParameter(id, &get));
EXPECT_EQ(expect, get) << expect.toString() << " vs " << get.toString();
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Verify parameters pass in set can be successfully get.
TEST_P(AudioEffectTest, SetAndGetCommonParameter) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
Parameter::Common common = EffectHelper::createParamCommon(
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */);
Parameter get = Parameter(), set = Parameter();
set.set<Parameter::common>(common);
- EXPECT_IS_OK(effect->setParameter(set));
+ EXPECT_IS_OK(mEffect->setParameter(set));
Parameter::Id id;
id.set<Parameter::Id::commonTag>(Parameter::common);
- EXPECT_IS_OK(effect->getParameter(id, &get));
+ EXPECT_IS_OK(mEffect->getParameter(id, &get));
EXPECT_EQ(set, get) << set.toString() << " vs " << get.toString();
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Verify parameters set and get in PROCESSING state.
TEST_P(AudioEffectTest, SetAndGetParameterInProcessing) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
Parameter::Common common = EffectHelper::createParamCommon(
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */);
Parameter get = Parameter(), set = Parameter();
set.set<Parameter::common>(common);
- EXPECT_IS_OK(effect->setParameter(set));
+ EXPECT_IS_OK(mEffect->setParameter(set));
Parameter::Id id;
id.set<Parameter::Id::commonTag>(Parameter::common);
- EXPECT_IS_OK(effect->getParameter(id, &get));
+ EXPECT_IS_OK(mEffect->getParameter(id, &get));
EXPECT_EQ(set, get) << set.toString() << " vs " << get.toString();
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Verify parameters set and get in IDLE state.
TEST_P(AudioEffectTest, SetAndGetParameterInIdle) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
Parameter::Common common = EffectHelper::createParamCommon(
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */);
Parameter get = Parameter(), set = Parameter();
set.set<Parameter::common>(common);
- EXPECT_IS_OK(effect->setParameter(set));
+ EXPECT_IS_OK(mEffect->setParameter(set));
Parameter::Id id;
id.set<Parameter::Id::commonTag>(Parameter::common);
- EXPECT_IS_OK(effect->getParameter(id, &get));
+ EXPECT_IS_OK(mEffect->getParameter(id, &get));
EXPECT_EQ(set, get) << set.toString() << " vs " << get.toString();
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Verify Parameters kept after stop.
TEST_P(AudioEffectTest, SetAndGetParameterAfterStop) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
Parameter::Common common = EffectHelper::createParamCommon(
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */);
Parameter get = Parameter(), set = Parameter();
set.set<Parameter::common>(common);
- EXPECT_IS_OK(effect->setParameter(set));
+ EXPECT_IS_OK(mEffect->setParameter(set));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
Parameter::Id id;
id.set<Parameter::Id::commonTag>(Parameter::common);
- EXPECT_IS_OK(effect->getParameter(id, &get));
+ EXPECT_IS_OK(mEffect->getParameter(id, &get));
EXPECT_EQ(set, get) << set.toString() << " vs " << get.toString();
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Verify Parameters kept after reset.
TEST_P(AudioEffectTest, SetAndGetParameterAfterReset) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
Parameter::Common common = EffectHelper::createParamCommon(
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */);
Parameter get = Parameter(), set = Parameter();
set.set<Parameter::common>(common);
- EXPECT_IS_OK(effect->setParameter(set));
+ EXPECT_IS_OK(mEffect->setParameter(set));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::RESET));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
Parameter::Id id;
id.set<Parameter::Id::commonTag>(Parameter::common);
- EXPECT_IS_OK(effect->getParameter(id, &get));
+ EXPECT_IS_OK(mEffect->getParameter(id, &get));
EXPECT_EQ(set, get) << set.toString() << " vs " << get.toString();
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
-
/// Data processing test
// Send data to effects and expect it to be consumed by checking statusMQ.
TEST_P(AudioEffectTest, ConsumeDataInProcessingState) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
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(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt /* specific */, &ret, EX_NONE));
auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
+ ASSERT_TRUE(statusMQ->isValid());
auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
+ ASSERT_TRUE(inputMQ->isValid());
auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
+ ASSERT_TRUE(outputMQ->isValid());
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
std::vector<float> buffer;
EffectHelper::allocateInputData(common, inputMQ, buffer);
EffectHelper::writeToFmq(inputMQ, buffer);
EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Send data to effects and expect it to be consumed after effect restart.
TEST_P(AudioEffectTest, ConsumeDataAfterRestart) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
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(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt /* specific */, &ret, EX_NONE));
auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
+ ASSERT_TRUE(statusMQ->isValid());
auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
+ ASSERT_TRUE(inputMQ->isValid());
auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
+ ASSERT_TRUE(outputMQ->isValid());
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
std::vector<float> buffer;
EffectHelper::allocateInputData(common, inputMQ, buffer);
EffectHelper::writeToFmq(inputMQ, buffer);
EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Send data to IDLE effects and expect it to be consumed after effect start.
TEST_P(AudioEffectTest, SendDataAtIdleAndConsumeDataInProcessing) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
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(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt /* specific */, &ret, EX_NONE));
auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
+ ASSERT_TRUE(statusMQ->isValid());
auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
+ ASSERT_TRUE(inputMQ->isValid());
auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
+ ASSERT_TRUE(outputMQ->isValid());
std::vector<float> buffer;
EffectHelper::allocateInputData(common, inputMQ, buffer);
EffectHelper::writeToFmq(inputMQ, buffer);
EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Send data multiple times.
TEST_P(AudioEffectTest, ProcessDataMultipleTimes) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
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(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt /* specific */, &ret, EX_NONE));
auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
+ ASSERT_TRUE(statusMQ->isValid());
auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
+ ASSERT_TRUE(inputMQ->isValid());
auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
+ ASSERT_TRUE(outputMQ->isValid());
std::vector<float> buffer;
EffectHelper::allocateInputData(common, inputMQ, buffer);
EffectHelper::writeToFmq(inputMQ, buffer);
EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
// expect no status and data after consume
@@ -634,77 +635,81 @@
// expect no status and data after consume
EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Send data to IDLE state effects and expect it not be consumed.
TEST_P(AudioEffectTest, NotConsumeDataInIdleState) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
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(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt /* specific */, &ret, EX_NONE));
auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
+ ASSERT_TRUE(statusMQ->isValid());
auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
+ ASSERT_TRUE(inputMQ->isValid());
auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
+ ASSERT_TRUE(outputMQ->isValid());
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
std::vector<float> buffer;
EffectHelper::allocateInputData(common, inputMQ, buffer);
EffectHelper::writeToFmq(inputMQ, buffer);
EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Send data to closed effects and expect it not be consumed.
TEST_P(AudioEffectTest, NotConsumeDataByClosedEffect) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
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(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt /* specific */, &ret, EX_NONE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
+ ASSERT_TRUE(statusMQ->isValid());
auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
+ ASSERT_TRUE(inputMQ->isValid());
auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
+ ASSERT_TRUE(outputMQ->isValid());
std::vector<float> buffer;
EffectHelper::allocateInputData(common, inputMQ, buffer);
EffectHelper::writeToFmq(inputMQ, buffer);
EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Send data to multiple effects.
TEST_P(AudioEffectTest, ConsumeDataMultipleEffects) {
std::shared_ptr<IEffect> effect1, effect2;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect1, mIdentity));
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect2, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect1, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect2, mDescriptor));
Parameter::Common common1 = EffectHelper::createParamCommon(
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
@@ -721,8 +726,11 @@
ASSERT_NO_FATAL_FAILURE(expectState(effect2, State::PROCESSING));
auto statusMQ1 = std::make_unique<EffectHelper::StatusMQ>(ret1.statusMQ);
+ ASSERT_TRUE(statusMQ1->isValid());
auto inputMQ1 = std::make_unique<EffectHelper::DataMQ>(ret1.inputDataMQ);
+ ASSERT_TRUE(inputMQ1->isValid());
auto outputMQ1 = std::make_unique<EffectHelper::DataMQ>(ret1.outputDataMQ);
+ ASSERT_TRUE(outputMQ1->isValid());
std::vector<float> buffer1, buffer2;
EffectHelper::allocateInputData(common1, inputMQ1, buffer1);
@@ -730,8 +738,11 @@
EffectHelper::readFromFmq(statusMQ1, 1, outputMQ1, buffer1.size(), buffer1);
auto statusMQ2 = std::make_unique<EffectHelper::StatusMQ>(ret2.statusMQ);
+ ASSERT_TRUE(statusMQ2->isValid());
auto inputMQ2 = std::make_unique<EffectHelper::DataMQ>(ret2.inputDataMQ);
+ ASSERT_TRUE(inputMQ2->isValid());
auto outputMQ2 = std::make_unique<EffectHelper::DataMQ>(ret2.outputDataMQ);
+ ASSERT_TRUE(outputMQ2->isValid());
EffectHelper::allocateInputData(common2, inputMQ2, buffer2);
EffectHelper::writeToFmq(inputMQ2, buffer2);
EffectHelper::readFromFmq(statusMQ2, 1, outputMQ2, buffer2.size(), buffer2);
@@ -752,9 +763,11 @@
::testing::Combine(testing::ValuesIn(
EffectFactoryHelper::getAllEffectDescriptors(IFactory::descriptor))),
[](const testing::TestParamInfo<AudioEffectTest::ParamType>& info) {
- auto instance = std::get<PARAM_INSTANCE_NAME>(info.param);
- std::string name = "TYPE_" + instance.second.type.toString() + "_UUID_" +
- instance.second.uuid.toString();
+ auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_TYPE_" +
+ descriptor.common.id.type.toString() + "_UUID_" +
+ descriptor.common.id.uuid.toString();
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
diff --git a/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp b/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
index 7adf63c..724a9c3 100644
--- a/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
@@ -37,8 +37,7 @@
* VtsAudioEffectTargetTest.
*/
enum ParamName { PARAM_INSTANCE_NAME, PARAM_STRENGTH };
-using BassBoostParamTestParam =
- std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>, int>;
+using BassBoostParamTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>;
/*
* Testing parameter range, assuming the parameter supported by effect is in this range.
@@ -60,12 +59,12 @@
public EffectHelper {
public:
BassBoostParamTest() : mParamStrength(std::get<PARAM_STRENGTH>(GetParam())) {
- std::tie(mFactory, mIdentity) = std::get<PARAM_INSTANCE_NAME>(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, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Specific specific = getDefaultParamSpecific();
Parameter::Common common = EffectHelper::createParamCommon(
@@ -91,7 +90,7 @@
static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
std::shared_ptr<IFactory> mFactory;
std::shared_ptr<IEffect> mEffect;
- Descriptor::Identity mIdentity;
+ Descriptor mDescriptor;
int mParamStrength = BassBoost::MIN_PER_MILLE_STRENGTH;
void SetAndGetBassBoostParameters() {
@@ -167,9 +166,11 @@
IFactory::descriptor, kBassBoostTypeUUID)),
testing::ValuesIn(kStrengthValues)),
[](const testing::TestParamInfo<BassBoostParamTest::ParamType>& info) {
- auto instance = std::get<PARAM_INSTANCE_NAME>(info.param);
+ auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
std::string strength = std::to_string(std::get<PARAM_STRENGTH>(info.param));
- std::string name = instance.second.uuid.toString() + "_strength_" + strength;
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_strength_" + strength;
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
diff --git a/audio/aidl/vts/VtsHalDownmixTargetTest.cpp b/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
new file mode 100644
index 0000000..8612660
--- /dev/null
+++ b/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VtsHalDownmixTargetTest"
+
+#include <Utils.h>
+#include <aidl/Vintf.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::Downmix;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::kDownmixTypeUUID;
+using aidl::android::hardware::audio::effect::kEffectNullUuid;
+using aidl::android::hardware::audio::effect::Parameter;
+
+/**
+ * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
+ * VtsAudioEffectTargetTest.
+ */
+enum ParamName { PARAM_INSTANCE_NAME, PARAM_TYPE };
+using DownmixParamTestParam =
+ std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, Downmix::Type>;
+
+// Testing for enum values
+const std::vector<Downmix::Type> kTypeValues = {Downmix::Type::STRIP, Downmix::Type::FOLD};
+
+class DownmixParamTest : public ::testing::TestWithParam<DownmixParamTestParam>,
+ public EffectHelper {
+ public:
+ DownmixParamTest() : mParamType(std::get<PARAM_TYPE>(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));
+ }
+
+ static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+ std::shared_ptr<IFactory> mFactory;
+ std::shared_ptr<IEffect> mEffect;
+ Descriptor mDescriptor;
+ Downmix::Type mParamType = Downmix::Type::STRIP;
+
+ void SetAndGetDownmixParameters() {
+ for (auto& it : mTags) {
+ auto& tag = it.first;
+ auto& dm = it.second;
+
+ // set parameter
+ Parameter expectParam;
+ Parameter::Specific specific;
+ specific.set<Parameter::Specific::downmix>(dm);
+ expectParam.set<Parameter::specific>(specific);
+ // All values are valid, set parameter should succeed
+ EXPECT_STATUS(EX_NONE, mEffect->setParameter(expectParam)) << expectParam.toString();
+
+ // get parameter
+ Parameter getParam;
+ Parameter::Id id;
+ Downmix::Id dmId;
+ dmId.set<Downmix::Id::commonTag>(tag);
+ id.set<Parameter::Id::downmixTag>(dmId);
+ EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
+
+ EXPECT_EQ(expectParam, getParam);
+ }
+ }
+
+ void addTypeParam(Downmix::Type type) {
+ Downmix dm;
+ dm.set<Downmix::type>(type);
+ mTags.push_back({Downmix::type, dm});
+ }
+
+ Parameter::Specific getDefaultParamSpecific() {
+ Downmix dm = Downmix::make<Downmix::type>(Downmix::Type::STRIP);
+ Parameter::Specific specific = Parameter::Specific::make<Parameter::Specific::downmix>(dm);
+ return specific;
+ }
+
+ private:
+ std::vector<std::pair<Downmix::Tag, Downmix>> mTags;
+ void CleanUp() { mTags.clear(); }
+};
+
+TEST_P(DownmixParamTest, SetAndGetType) {
+ EXPECT_NO_FATAL_FAILURE(addTypeParam(mParamType));
+ SetAndGetDownmixParameters();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ DownmixTest, DownmixParamTest,
+ ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kDownmixTypeUUID)),
+ testing::ValuesIn(kTypeValues)),
+ [](const testing::TestParamInfo<DownmixParamTest::ParamType>& info) {
+ auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
+ std::string type = std::to_string(static_cast<int>(std::get<PARAM_TYPE>(info.param)));
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_type" + type;
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DownmixParamTest);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp b/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
new file mode 100644
index 0000000..73fe077
--- /dev/null
+++ b/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
@@ -0,0 +1,620 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VtsHalEnvironmentalReverbTest"
+
+#include <Utils.h>
+#include <aidl/Vintf.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::EnvironmentalReverb;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::kEnvReverbTypeUUID;
+using aidl::android::hardware::audio::effect::Parameter;
+
+/**
+ * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
+ * VtsAudioEffectTargetTest.
+ * Testing parameter range, assuming the parameter supported by effect is in this range.
+ * This range is verified with IEffect.getDescriptor() and range defined in the documentation, for
+ * any index supported value test expects EX_NONE from IEffect.setParameter(), otherwise expects
+ * EX_ILLEGAL_ARGUMENT.
+ */
+const std::vector<int> kRoomLevelValues = {
+ EnvironmentalReverb::MIN_ROOM_LEVEL_MB - 1, EnvironmentalReverb::MIN_ROOM_LEVEL_MB,
+ EnvironmentalReverb::MAX_ROOM_LEVEL_MB, EnvironmentalReverb::MAX_ROOM_LEVEL_MB + 1};
+const std::vector<int> kRoomHfLevelValues = {
+ EnvironmentalReverb::MIN_ROOM_HF_LEVEL_MB - 1, EnvironmentalReverb::MIN_ROOM_HF_LEVEL_MB,
+ EnvironmentalReverb::MAX_ROOM_HF_LEVEL_MB, EnvironmentalReverb::MAX_ROOM_HF_LEVEL_MB + 1};
+const std::vector<int> kDecayTimeValues = {
+ EnvironmentalReverb::MIN_DECAY_TIME_MS - 1, EnvironmentalReverb::MIN_DECAY_TIME_MS,
+ EnvironmentalReverb::MAX_DECAY_TIME_MS, EnvironmentalReverb::MAX_DECAY_TIME_MS + 1};
+const std::vector<int> kDecayHfRatioValues = {
+ EnvironmentalReverb::MIN_DECAY_HF_RATIO_PM - 1, EnvironmentalReverb::MIN_DECAY_HF_RATIO_PM,
+ EnvironmentalReverb::MAX_DECAY_HF_RATIO_PM, EnvironmentalReverb::MAX_DECAY_HF_RATIO_PM + 1};
+const std::vector<int> kLevelValues = {
+ EnvironmentalReverb::MIN_LEVEL_MB - 1, EnvironmentalReverb::MIN_LEVEL_MB,
+ EnvironmentalReverb::MAX_LEVEL_MB, EnvironmentalReverb::MAX_LEVEL_MB + 1};
+const std::vector<int> kDelayValues = {
+ EnvironmentalReverb::MIN_DELAY_MS - 1, EnvironmentalReverb::MIN_DELAY_MS,
+ EnvironmentalReverb::MAX_DELAY_MS, EnvironmentalReverb::MAX_DELAY_MS + 1};
+const std::vector<int> kDiffusionValues = {
+ EnvironmentalReverb::MIN_DIFFUSION_PM - 1, EnvironmentalReverb::MIN_DIFFUSION_PM,
+ EnvironmentalReverb::MAX_DIFFUSION_PM, EnvironmentalReverb::MAX_DIFFUSION_PM + 1};
+const std::vector<int> kDensityValues = {
+ EnvironmentalReverb::MIN_DENSITY_PM - 1, EnvironmentalReverb::MIN_DENSITY_PM,
+ EnvironmentalReverb::MAX_DENSITY_PM, EnvironmentalReverb::MAX_DENSITY_PM + 1};
+
+class EnvironmentalReverbHelper : public EffectHelper {
+ public:
+ EnvironmentalReverbHelper(std::pair<std::shared_ptr<IFactory>, Descriptor> pair) {
+ std::tie(mFactory, mDescriptor) = pair;
+ }
+
+ void SetUpReverb() {
+ 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 TearDownReverb() {
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+ }
+
+ Parameter::Specific getDefaultParamSpecific() {
+ EnvironmentalReverb er = EnvironmentalReverb::make<EnvironmentalReverb::roomLevelMb>(
+ EnvironmentalReverb::MIN_ROOM_LEVEL_MB);
+ Parameter::Specific specific =
+ Parameter::Specific::make<Parameter::Specific::environmentalReverb>(er);
+ return specific;
+ }
+
+ static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+ std::shared_ptr<IFactory> mFactory;
+ std::shared_ptr<IEffect> mEffect;
+ Descriptor mDescriptor;
+ int mRoomLevel = EnvironmentalReverb::MIN_ROOM_LEVEL_MB;
+ int mRoomHfLevel = EnvironmentalReverb::MAX_ROOM_HF_LEVEL_MB;
+ int mDecayTime = 1000;
+ int mDecayHfRatio = 500;
+ int mLevel = EnvironmentalReverb::MIN_LEVEL_MB;
+ int mDelay = 40;
+ int mDiffusion = EnvironmentalReverb::MAX_DIFFUSION_PM;
+ int mDensity = EnvironmentalReverb::MAX_DENSITY_PM;
+ bool mBypass = false;
+
+ void SetAndGetReverbParameters() {
+ for (auto& it : mTags) {
+ auto& tag = it.first;
+ auto& er = it.second;
+
+ // validate parameter
+ Descriptor desc;
+ ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
+ const bool valid = isTagInRange(it.first, it.second, desc);
+ const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
+
+ // set
+ Parameter expectParam;
+ Parameter::Specific specific;
+ specific.set<Parameter::Specific::environmentalReverb>(er);
+ 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;
+ EnvironmentalReverb::Id erId;
+ erId.set<EnvironmentalReverb::Id::commonTag>(tag);
+ id.set<Parameter::Id::environmentalReverbTag>(erId);
+ // if set success, then get should match
+ EXPECT_STATUS(expected, mEffect->getParameter(id, &getParam));
+ EXPECT_EQ(expectParam, getParam);
+ }
+ }
+ }
+
+ void addRoomLevelParam() {
+ EnvironmentalReverb er;
+ er.set<EnvironmentalReverb::roomLevelMb>(mRoomLevel);
+ mTags.push_back({EnvironmentalReverb::roomLevelMb, er});
+ }
+
+ void addRoomHfLevelParam(int roomHfLevel) {
+ EnvironmentalReverb er;
+ er.set<EnvironmentalReverb::roomHfLevelMb>(roomHfLevel);
+ mTags.push_back({EnvironmentalReverb::roomHfLevelMb, er});
+ }
+
+ void addDecayTimeParam(int decayTime) {
+ EnvironmentalReverb er;
+ er.set<EnvironmentalReverb::decayTimeMs>(decayTime);
+ mTags.push_back({EnvironmentalReverb::decayTimeMs, er});
+ }
+
+ void addDecayHfRatioParam(int decayHfRatio) {
+ EnvironmentalReverb er;
+ er.set<EnvironmentalReverb::decayHfRatioPm>(decayHfRatio);
+ mTags.push_back({EnvironmentalReverb::decayHfRatioPm, er});
+ }
+
+ void addLevelParam(int level) {
+ EnvironmentalReverb er;
+ er.set<EnvironmentalReverb::levelMb>(level);
+ mTags.push_back({EnvironmentalReverb::levelMb, er});
+ }
+
+ void addDelayParam(int delay) {
+ EnvironmentalReverb er;
+ er.set<EnvironmentalReverb::delayMs>(delay);
+ mTags.push_back({EnvironmentalReverb::delayMs, er});
+ }
+
+ void addDiffusionParam(int diffusion) {
+ EnvironmentalReverb er;
+ er.set<EnvironmentalReverb::diffusionPm>(diffusion);
+ mTags.push_back({EnvironmentalReverb::diffusionPm, er});
+ }
+
+ void addDensityParam(int density) {
+ EnvironmentalReverb er;
+ er.set<EnvironmentalReverb::densityPm>(density);
+ mTags.push_back({EnvironmentalReverb::densityPm, er});
+ }
+
+ void addBypassParam(bool bypass) {
+ EnvironmentalReverb er;
+ er.set<EnvironmentalReverb::bypass>(bypass);
+ mTags.push_back({EnvironmentalReverb::bypass, er});
+ }
+
+ bool isTagInRange(const EnvironmentalReverb::Tag& tag, const EnvironmentalReverb er,
+ const Descriptor& desc) const {
+ const EnvironmentalReverb::Capability& erCap =
+ desc.capability.get<Capability::environmentalReverb>();
+ switch (tag) {
+ case EnvironmentalReverb::roomLevelMb: {
+ int roomLevel = er.get<EnvironmentalReverb::roomLevelMb>();
+ return isRoomLevelInRange(roomLevel);
+ }
+ case EnvironmentalReverb::roomHfLevelMb: {
+ int roomHfLevel = er.get<EnvironmentalReverb::roomHfLevelMb>();
+ return isRoomHfLevelInRange(roomHfLevel);
+ }
+ case EnvironmentalReverb::decayTimeMs: {
+ int decayTime = er.get<EnvironmentalReverb::decayTimeMs>();
+ return isDecayTimeInRange(erCap, decayTime);
+ }
+ case EnvironmentalReverb::decayHfRatioPm: {
+ int decayHfRatio = er.get<EnvironmentalReverb::decayHfRatioPm>();
+ return isDecayHfRatioInRange(decayHfRatio);
+ }
+ case EnvironmentalReverb::levelMb: {
+ int level = er.get<EnvironmentalReverb::levelMb>();
+ return isLevelInRange(level);
+ }
+ case EnvironmentalReverb::delayMs: {
+ int delay = er.get<EnvironmentalReverb::delayMs>();
+ return isDelayInRange(delay);
+ }
+ case EnvironmentalReverb::diffusionPm: {
+ int diffusion = er.get<EnvironmentalReverb::diffusionPm>();
+ return isDiffusionInRange(diffusion);
+ }
+ case EnvironmentalReverb::densityPm: {
+ int density = er.get<EnvironmentalReverb::densityPm>();
+ return isDensityInRange(density);
+ }
+ case EnvironmentalReverb::bypass: {
+ return true;
+ }
+ default:
+ return false;
+ }
+ return false;
+ }
+
+ bool isRoomLevelInRange(int roomLevel) const {
+ return roomLevel >= EnvironmentalReverb::MIN_ROOM_LEVEL_MB &&
+ roomLevel <= EnvironmentalReverb::MAX_ROOM_LEVEL_MB;
+ }
+
+ bool isRoomHfLevelInRange(int roomHfLevel) const {
+ return roomHfLevel >= EnvironmentalReverb::MIN_ROOM_HF_LEVEL_MB &&
+ roomHfLevel <= EnvironmentalReverb::MAX_ROOM_HF_LEVEL_MB;
+ }
+
+ bool isDecayTimeInRange(const EnvironmentalReverb::Capability& cap, int decayTime) const {
+ return decayTime >= EnvironmentalReverb::MIN_DECAY_TIME_MS &&
+ decayTime <= EnvironmentalReverb::MAX_DECAY_TIME_MS &&
+ decayTime <= cap.maxDecayTimeMs;
+ }
+
+ bool isDecayHfRatioInRange(int decayHfRatio) const {
+ return decayHfRatio >= EnvironmentalReverb::MIN_DECAY_HF_RATIO_PM &&
+ decayHfRatio <= EnvironmentalReverb::MAX_DECAY_HF_RATIO_PM;
+ }
+
+ bool isLevelInRange(int level) const {
+ return level >= EnvironmentalReverb::MIN_LEVEL_MB &&
+ level <= EnvironmentalReverb::MAX_LEVEL_MB;
+ }
+
+ bool isDelayInRange(int delay) const {
+ return delay >= EnvironmentalReverb::MIN_DELAY_MS &&
+ delay <= EnvironmentalReverb::MAX_DELAY_MS;
+ }
+
+ bool isDiffusionInRange(int diffusion) const {
+ return diffusion >= EnvironmentalReverb::MIN_DIFFUSION_PM &&
+ diffusion <= EnvironmentalReverb::MAX_DIFFUSION_PM;
+ }
+
+ bool isDensityInRange(int density) const {
+ return density >= EnvironmentalReverb::MIN_DENSITY_PM &&
+ density <= EnvironmentalReverb::MAX_DENSITY_PM;
+ }
+
+ private:
+ std::vector<std::pair<EnvironmentalReverb::Tag, EnvironmentalReverb>> mTags;
+ void CleanUp() { mTags.clear(); }
+};
+
+class EnvironmentalReverbRoomLevelTest
+ : public ::testing::TestWithParam<
+ std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>>,
+ public EnvironmentalReverbHelper {
+ public:
+ EnvironmentalReverbRoomLevelTest() : EnvironmentalReverbHelper(std::get<0>(GetParam())) {
+ mRoomLevel = std::get<1>(GetParam());
+ }
+
+ void SetUp() override { SetUpReverb(); }
+
+ void TearDown() override { TearDownReverb(); }
+};
+
+TEST_P(EnvironmentalReverbRoomLevelTest, SetAndGetRoomLevel) {
+ EXPECT_NO_FATAL_FAILURE(addRoomLevelParam());
+ SetAndGetReverbParameters();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ EnvironmentalReverbTest, EnvironmentalReverbRoomLevelTest,
+ ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kEnvReverbTypeUUID)),
+ testing::ValuesIn(kRoomLevelValues)),
+ [](const testing::TestParamInfo<EnvironmentalReverbRoomLevelTest::ParamType>& info) {
+ auto descriptor = std::get<0>(info.param).second;
+ std::string roomLevel = std::to_string(std::get<1>(info.param));
+
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_roomLevel" + roomLevel;
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+
+class EnvironmentalReverbRoomHfLevelTest
+ : public ::testing::TestWithParam<
+ std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>>,
+ public EnvironmentalReverbHelper {
+ public:
+ EnvironmentalReverbRoomHfLevelTest() : EnvironmentalReverbHelper(std::get<0>(GetParam())) {
+ mRoomHfLevel = std::get<1>(GetParam());
+ }
+
+ void SetUp() override { SetUpReverb(); }
+
+ void TearDown() override { TearDownReverb(); }
+};
+
+TEST_P(EnvironmentalReverbRoomHfLevelTest, SetAndGetRoomHfLevel) {
+ EXPECT_NO_FATAL_FAILURE(addRoomHfLevelParam(mRoomHfLevel));
+ SetAndGetReverbParameters();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ EnvironmentalReverbTest, EnvironmentalReverbRoomHfLevelTest,
+ ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kEnvReverbTypeUUID)),
+ testing::ValuesIn(kRoomHfLevelValues)),
+ [](const testing::TestParamInfo<EnvironmentalReverbRoomHfLevelTest::ParamType>& info) {
+ auto descriptor = std::get<0>(info.param).second;
+ std::string roomHfLevel = std::to_string(std::get<1>(info.param));
+
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_roomHfLevel" + roomHfLevel;
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+
+class EnvironmentalReverbDecayTimeTest
+ : public ::testing::TestWithParam<
+ std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>>,
+ public EnvironmentalReverbHelper {
+ public:
+ EnvironmentalReverbDecayTimeTest() : EnvironmentalReverbHelper(std::get<0>(GetParam())) {
+ mDecayTime = std::get<1>(GetParam());
+ }
+
+ void SetUp() override { SetUpReverb(); }
+
+ void TearDown() override { TearDownReverb(); }
+};
+
+TEST_P(EnvironmentalReverbDecayTimeTest, SetAndGetDecayTime) {
+ EXPECT_NO_FATAL_FAILURE(addDecayTimeParam(mDecayTime));
+ SetAndGetReverbParameters();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ EnvironmentalReverbTest, EnvironmentalReverbDecayTimeTest,
+ ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kEnvReverbTypeUUID)),
+ testing::ValuesIn(kDecayTimeValues)),
+ [](const testing::TestParamInfo<EnvironmentalReverbDecayTimeTest::ParamType>& info) {
+ auto descriptor = std::get<0>(info.param).second;
+ std::string decayTime = std::to_string(std::get<1>(info.param));
+
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_decayTime" + decayTime;
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+
+class EnvironmentalReverbDecayHfRatioTest
+ : public ::testing::TestWithParam<
+ std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>>,
+ public EnvironmentalReverbHelper {
+ public:
+ EnvironmentalReverbDecayHfRatioTest() : EnvironmentalReverbHelper(std::get<0>(GetParam())) {
+ mDecayHfRatio = std::get<1>(GetParam());
+ }
+
+ void SetUp() override { SetUpReverb(); }
+
+ void TearDown() override { TearDownReverb(); }
+};
+
+TEST_P(EnvironmentalReverbDecayHfRatioTest, SetAndGetDecayHfRatio) {
+ EXPECT_NO_FATAL_FAILURE(addDecayHfRatioParam(mDecayHfRatio));
+ SetAndGetReverbParameters();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ EnvironmentalReverbTest, EnvironmentalReverbDecayHfRatioTest,
+ ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kEnvReverbTypeUUID)),
+ testing::ValuesIn(kDecayHfRatioValues)),
+ [](const testing::TestParamInfo<EnvironmentalReverbDecayHfRatioTest::ParamType>& info) {
+ auto descriptor = std::get<0>(info.param).second;
+ std::string decayHfRatio = std::to_string(std::get<1>(info.param));
+
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_decayHfRatio" +
+ decayHfRatio;
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+
+class EnvironmentalReverbLevelTest
+ : public ::testing::TestWithParam<
+ std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>>,
+ public EnvironmentalReverbHelper {
+ public:
+ EnvironmentalReverbLevelTest() : EnvironmentalReverbHelper(std::get<0>(GetParam())) {
+ mLevel = std::get<1>(GetParam());
+ }
+
+ void SetUp() override { SetUpReverb(); }
+
+ void TearDown() override { TearDownReverb(); }
+};
+
+TEST_P(EnvironmentalReverbLevelTest, SetAndGetLevel) {
+ EXPECT_NO_FATAL_FAILURE(addLevelParam(mLevel));
+ SetAndGetReverbParameters();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ EnvironmentalReverbTest, EnvironmentalReverbLevelTest,
+ ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kEnvReverbTypeUUID)),
+ testing::ValuesIn(kLevelValues)),
+ [](const testing::TestParamInfo<EnvironmentalReverbDecayHfRatioTest::ParamType>& info) {
+ auto descriptor = std::get<0>(info.param).second;
+ std::string level = std::to_string(std::get<1>(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;
+ });
+
+class EnvironmentalReverbDelayTest
+ : public ::testing::TestWithParam<
+ std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>>,
+ public EnvironmentalReverbHelper {
+ public:
+ EnvironmentalReverbDelayTest() : EnvironmentalReverbHelper(std::get<0>(GetParam())) {
+ mDelay = std::get<1>(GetParam());
+ }
+
+ void SetUp() override { SetUpReverb(); }
+
+ void TearDown() override { TearDownReverb(); }
+};
+
+TEST_P(EnvironmentalReverbDelayTest, SetAndGetDelay) {
+ EXPECT_NO_FATAL_FAILURE(addDelayParam(mDelay));
+ SetAndGetReverbParameters();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ EnvironmentalReverbTest, EnvironmentalReverbDelayTest,
+ ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kEnvReverbTypeUUID)),
+ testing::ValuesIn(kDelayValues)),
+ [](const testing::TestParamInfo<EnvironmentalReverbDelayTest::ParamType>& info) {
+ auto descriptor = std::get<0>(info.param).second;
+ std::string delay = std::to_string(std::get<1>(info.param));
+
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_delay" + delay;
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+
+class EnvironmentalReverbDiffusionTest
+ : public ::testing::TestWithParam<
+ std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>>,
+ public EnvironmentalReverbHelper {
+ public:
+ EnvironmentalReverbDiffusionTest() : EnvironmentalReverbHelper(std::get<0>(GetParam())) {
+ mDiffusion = std::get<1>(GetParam());
+ }
+
+ void SetUp() override { SetUpReverb(); }
+
+ void TearDown() override { TearDownReverb(); }
+};
+
+TEST_P(EnvironmentalReverbDiffusionTest, SetAndGetDiffusion) {
+ EXPECT_NO_FATAL_FAILURE(addDiffusionParam(mDiffusion));
+ SetAndGetReverbParameters();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ EnvironmentalReverbTest, EnvironmentalReverbDiffusionTest,
+ ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kEnvReverbTypeUUID)),
+ testing::ValuesIn(kDiffusionValues)),
+ [](const testing::TestParamInfo<EnvironmentalReverbDiffusionTest::ParamType>& info) {
+ auto descriptor = std::get<0>(info.param).second;
+ std::string diffusion = std::to_string(std::get<1>(info.param));
+
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_diffusion" + diffusion;
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+
+class EnvironmentalReverbDensityTest
+ : public ::testing::TestWithParam<
+ std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>>,
+ public EnvironmentalReverbHelper {
+ public:
+ EnvironmentalReverbDensityTest() : EnvironmentalReverbHelper(std::get<0>(GetParam())) {
+ mDensity = std::get<1>(GetParam());
+ }
+
+ void SetUp() override { SetUpReverb(); }
+
+ void TearDown() override { TearDownReverb(); }
+};
+
+TEST_P(EnvironmentalReverbDensityTest, SetAndGetDensity) {
+ EXPECT_NO_FATAL_FAILURE(addDensityParam(mDensity));
+ SetAndGetReverbParameters();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ EnvironmentalReverbTest, EnvironmentalReverbDensityTest,
+ ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kEnvReverbTypeUUID)),
+ testing::ValuesIn(kDensityValues)),
+ [](const testing::TestParamInfo<EnvironmentalReverbDensityTest::ParamType>& info) {
+ auto descriptor = std::get<0>(info.param).second;
+ std::string density = std::to_string(std::get<1>(info.param));
+
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_density" + density;
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+
+class EnvironmentalReverbBypassTest
+ : public ::testing::TestWithParam<
+ std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, bool>>,
+ public EnvironmentalReverbHelper {
+ public:
+ EnvironmentalReverbBypassTest() : EnvironmentalReverbHelper(std::get<0>(GetParam())) {
+ mBypass = std::get<1>(GetParam());
+ }
+
+ void SetUp() override { SetUpReverb(); }
+
+ void TearDown() override { TearDownReverb(); }
+};
+
+TEST_P(EnvironmentalReverbBypassTest, SetAndGetBypass) {
+ EXPECT_NO_FATAL_FAILURE(addBypassParam(mBypass));
+ SetAndGetReverbParameters();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ EnvironmentalReverbTest, EnvironmentalReverbBypassTest,
+ ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kEnvReverbTypeUUID)),
+ testing::Bool()),
+ [](const testing::TestParamInfo<EnvironmentalReverbBypassTest::ParamType>& info) {
+ auto descriptor = std::get<0>(info.param).second;
+ std::string bypass = std::to_string(std::get<1>(info.param));
+
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_bypass" + bypass;
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
index 1b147a6..e11a936 100644
--- a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
@@ -57,8 +57,7 @@
*/
enum ParamName { PARAM_INSTANCE_NAME, PARAM_BAND_LEVEL };
-using EqualizerParamTestParam =
- std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>, int>;
+using EqualizerParamTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>;
/*
Testing parameter range, assuming the parameter supported by effect is in this range.
@@ -71,12 +70,12 @@
public EffectHelper {
public:
EqualizerTest() : mBandLevel(std::get<PARAM_BAND_LEVEL>(GetParam())) {
- std::tie(mFactory, mIdentity) = std::get<PARAM_INSTANCE_NAME>(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, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Specific specific = getDefaultParamSpecific();
Parameter::Common common = EffectHelper::createParamCommon(
@@ -115,7 +114,7 @@
static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
std::shared_ptr<IFactory> mFactory;
std::shared_ptr<IEffect> mEffect;
- Descriptor::Identity mIdentity;
+ Descriptor mDescriptor;
std::pair<int, int> mPresetIndex;
std::pair<int, int> mBandIndex;
const int mBandLevel;
@@ -327,9 +326,11 @@
IFactory::descriptor, kEqualizerTypeUUID)),
testing::ValuesIn(kBandLevels)),
[](const testing::TestParamInfo<EqualizerTest::ParamType>& info) {
- auto instance = std::get<PARAM_INSTANCE_NAME>(info.param);
+ auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
std::string bandLevel = std::to_string(std::get<PARAM_BAND_LEVEL>(info.param));
- std::string name = instance.second.uuid.toString() + "_bandLevel_" + bandLevel;
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_bandLevel_" + bandLevel;
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
diff --git a/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp b/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
new file mode 100644
index 0000000..a1daec2
--- /dev/null
+++ b/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VtsHalHapticGeneratorTargetTest"
+
+#include <Utils.h>
+#include <aidl/Vintf.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::HapticGenerator;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::kHapticGeneratorTypeUUID;
+using aidl::android::hardware::audio::effect::Parameter;
+
+/**
+ * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
+ * VtsAudioEffectTargetTest.
+ */
+enum ParamName {
+ PARAM_INSTANCE_NAME,
+ PARAM_HAPTIC_SCALE_ID,
+ PARAM_HAPTIC_SCALE_VIBRATOR_SCALE,
+ PARAM_VIBRATION_INFORMATION_RESONANT_FREQUENCY,
+ PARAM_VIBRATION_INFORMATION_Q_FACTOR,
+ PARAM_VIBRATION_INFORMATION_MAX_AMPLITUDE,
+};
+using HapticGeneratorParamTestParam =
+ std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int,
+ HapticGenerator::VibratorScale, float, float, float>;
+
+/*
+ * Testing parameter range, assuming the parameter supported by effect is in this range.
+ * Parameter should be within the valid range defined in the documentation,
+ * for any supported value test expects EX_NONE from IEffect.setParameter(),
+ * otherwise expect EX_ILLEGAL_ARGUMENT.
+ */
+
+// TODO : Update the test values once range/capability is updated by implementation
+const int MIN_ID = std::numeric_limits<int>::min();
+const int MAX_ID = std::numeric_limits<int>::max();
+const float MIN_FLOAT = std::numeric_limits<float>::min();
+const float MAX_FLOAT = std::numeric_limits<float>::max();
+
+const std::vector<int> kHapticScaleIdValues = {MIN_ID, 0, MAX_ID};
+const std::vector<HapticGenerator::VibratorScale> kVibratorScaleValues = {
+ HapticGenerator::VibratorScale::MUTE, HapticGenerator::VibratorScale::VERY_LOW,
+ HapticGenerator::VibratorScale::LOW, HapticGenerator::VibratorScale::NONE,
+ HapticGenerator::VibratorScale::HIGH, HapticGenerator::VibratorScale::VERY_HIGH};
+
+const std::vector<float> kResonantFrequencyValues = {MIN_FLOAT, 100, MAX_FLOAT};
+const std::vector<float> kQFactorValues = {MIN_FLOAT, 100, MAX_FLOAT};
+const std::vector<float> kMaxAmplitude = {MIN_FLOAT, 100, MAX_FLOAT};
+
+class HapticGeneratorParamTest : public ::testing::TestWithParam<HapticGeneratorParamTestParam>,
+ public EffectHelper {
+ public:
+ HapticGeneratorParamTest()
+ : mParamHapticScaleId(std::get<PARAM_HAPTIC_SCALE_ID>(GetParam())),
+ mParamVibratorScale(std::get<PARAM_HAPTIC_SCALE_VIBRATOR_SCALE>(GetParam())),
+ mParamResonantFrequency(
+ std::get<PARAM_VIBRATION_INFORMATION_RESONANT_FREQUENCY>(GetParam())),
+ mParamQFactor(std::get<PARAM_VIBRATION_INFORMATION_Q_FACTOR>(GetParam())),
+ mParamMaxAmplitude(std::get<PARAM_VIBRATION_INFORMATION_MAX_AMPLITUDE>(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() {
+ HapticGenerator::HapticScale hapticScale = {.id = 0,
+ .scale = HapticGenerator::VibratorScale::MUTE};
+ HapticGenerator hg = HapticGenerator::make<HapticGenerator::hapticScale>(hapticScale);
+ Parameter::Specific specific =
+ Parameter::Specific::make<Parameter::Specific::hapticGenerator>(hg);
+ return specific;
+ }
+
+ static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+ std::shared_ptr<IFactory> mFactory;
+ std::shared_ptr<IEffect> mEffect;
+ Descriptor mDescriptor;
+ int mParamHapticScaleId = 0;
+ HapticGenerator::VibratorScale mParamVibratorScale = HapticGenerator::VibratorScale::MUTE;
+ float mParamResonantFrequency = 0;
+ float mParamQFactor = 0;
+ float mParamMaxAmplitude = 0;
+
+ void SetAndGetHapticGeneratorParameters() {
+ for (auto& it : mTags) {
+ auto& tag = it.first;
+ auto& hg = it.second;
+
+ // set parameter
+ Parameter expectParam;
+ Parameter::Specific specific;
+ specific.set<Parameter::Specific::hapticGenerator>(hg);
+ expectParam.set<Parameter::specific>(specific);
+ EXPECT_STATUS(EX_NONE, mEffect->setParameter(expectParam)) << expectParam.toString();
+
+ // get parameter
+ Parameter getParam;
+ Parameter::Id id;
+ HapticGenerator::Id hgId;
+ hgId.set<HapticGenerator::Id::commonTag>(tag);
+ id.set<Parameter::Id::hapticGeneratorTag>(hgId);
+ EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
+ EXPECT_EQ(expectParam, getParam);
+ }
+ }
+
+ void addHapticScaleParam(int id, HapticGenerator::VibratorScale scale) {
+ HapticGenerator hg;
+ HapticGenerator::HapticScale hapticScale = {.id = id, .scale = scale};
+ hg.set<HapticGenerator::hapticScale>(hapticScale);
+ mTags.push_back({HapticGenerator::hapticScale, hg});
+ }
+
+ void addVibratorInformationParam(float resonantFrequencyHz, float qFactor, float maxAmplitude) {
+ HapticGenerator hg;
+ HapticGenerator::VibratorInformation vibrationInfo = {
+ .resonantFrequencyHz = resonantFrequencyHz,
+ .qFactor = qFactor,
+ .maxAmplitude = maxAmplitude};
+ hg.set<HapticGenerator::vibratorInfo>(vibrationInfo);
+ mTags.push_back({HapticGenerator::vibratorInfo, hg});
+ }
+
+ private:
+ std::vector<std::pair<HapticGenerator::Tag, HapticGenerator>> mTags;
+
+ void CleanUp() { mTags.clear(); }
+};
+
+TEST_P(HapticGeneratorParamTest, SetAndGetHapticScale) {
+ EXPECT_NO_FATAL_FAILURE(addHapticScaleParam(mParamHapticScaleId, mParamVibratorScale));
+ SetAndGetHapticGeneratorParameters();
+}
+
+TEST_P(HapticGeneratorParamTest, SetAndGetVibratorInformation) {
+ EXPECT_NO_FATAL_FAILURE(addVibratorInformationParam(mParamResonantFrequency, mParamQFactor,
+ mParamMaxAmplitude));
+ SetAndGetHapticGeneratorParameters();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ HapticGeneratorValidTest, HapticGeneratorParamTest,
+ ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kHapticGeneratorTypeUUID)),
+ testing::ValuesIn(kHapticScaleIdValues),
+ testing::ValuesIn(kVibratorScaleValues),
+ testing::ValuesIn(kResonantFrequencyValues),
+ testing::ValuesIn(kQFactorValues), testing::ValuesIn(kMaxAmplitude)),
+ [](const testing::TestParamInfo<HapticGeneratorParamTest::ParamType>& info) {
+ auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
+ std::string hapticScaleID = std::to_string(std::get<PARAM_HAPTIC_SCALE_ID>(info.param));
+ std::string hapticScaleVibScale = std::to_string(
+ static_cast<int>(std::get<PARAM_HAPTIC_SCALE_VIBRATOR_SCALE>(info.param)));
+ std::string resonantFrequency = std::to_string(
+ std::get<PARAM_VIBRATION_INFORMATION_RESONANT_FREQUENCY>(info.param));
+ std::string qFactor =
+ std::to_string(std::get<PARAM_VIBRATION_INFORMATION_Q_FACTOR>(info.param));
+ std::string maxAmplitude =
+ std::to_string(std::get<PARAM_VIBRATION_INFORMATION_MAX_AMPLITUDE>(info.param));
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_hapticScaleId" +
+ hapticScaleID + "_hapticScaleVibScale" + hapticScaleVibScale +
+ "_resonantFrequency" + resonantFrequency + "_qFactor" + qFactor +
+ "_maxAmplitude" + maxAmplitude;
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+
+INSTANTIATE_TEST_SUITE_P(
+ HapticGeneratorInvalidTest, HapticGeneratorParamTest,
+ ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kHapticGeneratorTypeUUID)),
+ testing::Values(MIN_ID - 1),
+ testing::Values(HapticGenerator::VibratorScale::MUTE),
+ testing::Values(MIN_FLOAT), testing::Values(MIN_FLOAT),
+ testing::Values(MIN_FLOAT)),
+ [](const testing::TestParamInfo<HapticGeneratorParamTest::ParamType>& info) {
+ auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
+ std::string hapticScaleID = std::to_string(std::get<PARAM_HAPTIC_SCALE_ID>(info.param));
+ std::string hapticScaleVibScale = std::to_string(
+ static_cast<int>(std::get<PARAM_HAPTIC_SCALE_VIBRATOR_SCALE>(info.param)));
+ std::string resonantFrequency = std::to_string(
+ std::get<PARAM_VIBRATION_INFORMATION_RESONANT_FREQUENCY>(info.param));
+ std::string qFactor =
+ std::to_string(std::get<PARAM_VIBRATION_INFORMATION_Q_FACTOR>(info.param));
+ std::string maxAmplitude =
+ std::to_string(std::get<PARAM_VIBRATION_INFORMATION_MAX_AMPLITUDE>(info.param));
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_hapticScaleId" +
+ hapticScaleID + "_hapticScaleVibScale" + hapticScaleVibScale +
+ "_resonantFrequency" + resonantFrequency + "_qFactor" + qFactor +
+ "_maxAmplitude" + maxAmplitude;
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HapticGeneratorParamTest);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
index 3fd2812..305c243 100644
--- a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
@@ -38,7 +38,7 @@
*/
enum ParamName { PARAM_INSTANCE_NAME, PARAM_GAIN_MB };
using LoudnessEnhancerParamTestParam =
- std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>, int>;
+ std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>;
// Every int 32 bit value is a valid gain, so testing the corner cases and one regular value.
// TODO : Update the test values once range/capability is updated by implementation.
@@ -49,12 +49,12 @@
public EffectHelper {
public:
LoudnessEnhancerParamTest() : mParamGainMb(std::get<PARAM_GAIN_MB>(GetParam())) {
- std::tie(mFactory, mIdentity) = std::get<PARAM_INSTANCE_NAME>(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, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Specific specific = getDefaultParamSpecific();
Parameter::Common common = EffectHelper::createParamCommon(
@@ -79,7 +79,7 @@
static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
std::shared_ptr<IFactory> mFactory;
std::shared_ptr<IEffect> mEffect;
- Descriptor::Identity mIdentity;
+ Descriptor mDescriptor;
int mParamGainMb = 0;
void SetAndGetParameters() {
@@ -130,9 +130,11 @@
IFactory::descriptor, kLoudnessEnhancerTypeUUID)),
testing::ValuesIn(kGainMbValues)),
[](const testing::TestParamInfo<LoudnessEnhancerParamTest::ParamType>& info) {
- auto instance = std::get<PARAM_INSTANCE_NAME>(info.param);
+ auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
std::string gainMb = std::to_string(std::get<PARAM_GAIN_MB>(info.param));
- std::string name = instance.second.uuid.toString() + "_gainMb_" + gainMb;
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_gainMb_" + gainMb;
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
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
diff --git a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
new file mode 100644
index 0000000..a7834fb
--- /dev/null
+++ b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
@@ -0,0 +1,329 @@
+/*
+ * 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 "VtsHalVisualizerTest"
+
+#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::kVisualizerTypeUUID;
+using aidl::android::hardware::audio::effect::Parameter;
+using aidl::android::hardware::audio::effect::Visualizer;
+
+/**
+ * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
+ * VtsAudioEffectTargetTest.
+ */
+enum ParamName {
+ PARAM_INSTANCE_NAME,
+ PARAM_CAPTURE_SIZE,
+ PARAM_SCALING_MODE,
+ PARAM_MEASUREMENT_MODE,
+ PARAM_LATENCY,
+};
+using VisualizerParamTestParam =
+ std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int, Visualizer::ScalingMode,
+ Visualizer::MeasurementMode, int>;
+
+const int MIN_CAPTURE_SIZE = 128;
+const int MAX_CAPTURE_SIZE = 1024;
+const int MAX_LATENCY = 3000;
+
+const std::vector<int> kCaptureSizeValues = {MIN_CAPTURE_SIZE - 1, MIN_CAPTURE_SIZE,
+ MAX_CAPTURE_SIZE, MAX_CAPTURE_SIZE + 1};
+const std::vector<Visualizer::ScalingMode> kScalingModeValues = {
+ Visualizer::ScalingMode::NORMALIZED, Visualizer::ScalingMode::AS_PLAYED};
+const std::vector<Visualizer::MeasurementMode> kMeasurementModeValues = {
+ Visualizer::MeasurementMode::NONE, Visualizer::MeasurementMode::PEAK_RMS};
+const std::vector<int> kLatencyValues = {-1, 0, MAX_LATENCY, MAX_LATENCY + 1};
+
+class VisualizerParamTest : public ::testing::TestWithParam<VisualizerParamTestParam>,
+ public EffectHelper {
+ public:
+ VisualizerParamTest()
+ : mCaptureSize(std::get<PARAM_CAPTURE_SIZE>(GetParam())),
+ mScalingMode(std::get<PARAM_SCALING_MODE>(GetParam())),
+ mMeasurementMode(std::get<PARAM_MEASUREMENT_MODE>(GetParam())),
+ mLatency(std::get<PARAM_LATENCY>(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() {
+ Visualizer vs = Visualizer::make<Visualizer::captureSizeBytes>(MIN_CAPTURE_SIZE);
+ Parameter::Specific specific =
+ Parameter::Specific::make<Parameter::Specific::visualizer>(vs);
+ return specific;
+ }
+
+ static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+ std::shared_ptr<IFactory> mFactory;
+ std::shared_ptr<IEffect> mEffect;
+ Descriptor mDescriptor;
+ int mCaptureSize = MAX_CAPTURE_SIZE;
+ Visualizer::ScalingMode mScalingMode = Visualizer::ScalingMode::NORMALIZED;
+ Visualizer::MeasurementMode mMeasurementMode = Visualizer::MeasurementMode::NONE;
+ int mLatency = 0;
+
+ void SetAndGetCommonParameters() {
+ for (auto& it : mCommonTags) {
+ auto& tag = it.first;
+ auto& vs = it.second;
+
+ // validate parameter
+ Descriptor desc;
+ ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
+ const bool valid = isTagInRange(tag, vs, desc);
+ const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
+
+ // set parameter
+ Parameter expectParam;
+ Parameter::Specific specific;
+ specific.set<Parameter::Specific::visualizer>(vs);
+ 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;
+ Visualizer::Id vsId;
+ vsId.set<Visualizer::Id::commonTag>(tag);
+ id.set<Parameter::Id::visualizerTag>(vsId);
+ EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
+
+ EXPECT_EQ(expectParam, getParam) << "\nexpect:" << expectParam.toString()
+ << "\ngetParam:" << getParam.toString();
+ }
+ }
+ }
+
+ void SetAndGetSetOnlyParameters() {
+ for (auto& it : mSetOnlyParamTags) {
+ auto& tag = it.first;
+ auto& vs = it.second;
+
+ // validate parameter
+ Descriptor desc;
+ ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
+ const bool valid = isSetOnlyParamTagInRange(tag, vs, desc);
+ const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
+
+ // set parameter
+ Parameter expectParam;
+ Parameter::Specific specific;
+ specific.set<Parameter::Specific::visualizer>(vs);
+ expectParam.set<Parameter::specific>(specific);
+ ASSERT_STATUS(expected, mEffect->setParameter(expectParam));
+
+ // parameter defined in this setOnlyParameter union must be settable via
+ // setParameter(), but must not be gettable
+ Parameter getParam;
+ Parameter::Id id;
+ Visualizer::Id vsId;
+ vsId.set<Visualizer::Id::setOnlyParamTag>(tag);
+ id.set<Parameter::Id::visualizerTag>(vsId);
+ EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, mEffect->getParameter(id, &getParam));
+ }
+ }
+
+ void GetandSetGetOnlyParameters() {
+ for (auto& tag : mGetOnlyParamTags) {
+ // get parameter
+ Parameter getParam;
+ Parameter::Id id;
+ Visualizer::Id vsId;
+ vsId.set<Visualizer::Id::getOnlyParamTag>(tag);
+ id.set<Parameter::Id::visualizerTag>(vsId);
+ ASSERT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
+
+ // parameter defined in this getOnlyParameter union must be gettable via
+ // getParameter(), but must not be settable
+ // set parameter
+ ASSERT_STATUS(EX_ILLEGAL_ARGUMENT, mEffect->setParameter(getParam));
+ }
+ }
+
+ void addCaptureSizeParam(int captureSize) {
+ Visualizer vs;
+ vs.set<Visualizer::captureSizeBytes>(captureSize);
+ mCommonTags.push_back({Visualizer::captureSizeBytes, vs});
+ }
+
+ void addScalingModeParam(Visualizer::ScalingMode scalingMode) {
+ Visualizer vs;
+ vs.set<Visualizer::scalingMode>(scalingMode);
+ mCommonTags.push_back({Visualizer::scalingMode, vs});
+ }
+
+ void addMeasurementModeParam(Visualizer::MeasurementMode measurementMode) {
+ Visualizer vs;
+ vs.set<Visualizer::measurementMode>(measurementMode);
+ mCommonTags.push_back({Visualizer::measurementMode, vs});
+ }
+
+ void addLatencyParam(int latency) {
+ Visualizer vs;
+ Visualizer::SetOnlyParameters setOnlyParam;
+ setOnlyParam.set<Visualizer::SetOnlyParameters::latencyMs>(latency);
+ vs.set<Visualizer::setOnlyParameters>(setOnlyParam);
+ mSetOnlyParamTags.push_back({Visualizer::SetOnlyParameters::latencyMs, vs});
+ }
+
+ void addMeasurementTag() {
+ mGetOnlyParamTags.push_back(Visualizer::GetOnlyParameters::measurement);
+ }
+
+ void addCaptureBytesTag() {
+ mGetOnlyParamTags.push_back(Visualizer::GetOnlyParameters::captureBytes);
+ }
+
+ bool isTagInRange(const Visualizer::Tag& tag, const Visualizer& vs,
+ const Descriptor& desc) const {
+ const Visualizer::Capability& vsCap = desc.capability.get<Capability::visualizer>();
+ switch (tag) {
+ case Visualizer::captureSizeBytes: {
+ int captureSize = vs.get<Visualizer::captureSizeBytes>();
+ return isCaptureSizeInRange(vsCap, captureSize);
+ }
+ case Visualizer::scalingMode:
+ case Visualizer::measurementMode:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ bool isSetOnlyParamTagInRange(Visualizer::SetOnlyParameters::Tag, const Visualizer& vs,
+ const Descriptor& desc) const {
+ const Visualizer::Capability& vsCap = desc.capability.get<Capability::visualizer>();
+ if (vs.getTag() != Visualizer::setOnlyParameters) return false;
+ Visualizer::SetOnlyParameters setOnlyParam = vs.get<Visualizer::setOnlyParameters>();
+ if (setOnlyParam.getTag() != Visualizer::SetOnlyParameters::latencyMs) return false;
+ int latency = setOnlyParam.get<Visualizer::SetOnlyParameters::latencyMs>();
+ return isLatencyInRange(vsCap, latency);
+ }
+
+ bool isCaptureSizeInRange(const Visualizer::Capability& cap, int captureSize) const {
+ return (captureSize >= cap.captureSizeRange.minBytes &&
+ captureSize <= cap.captureSizeRange.maxBytes);
+ }
+
+ bool isLatencyInRange(const Visualizer::Capability& cap, int latency) const {
+ return (latency >= 0 && latency <= cap.maxLatencyMs);
+ }
+
+ private:
+ std::vector<std::pair<Visualizer::Tag, Visualizer>> mCommonTags;
+ std::vector<std::pair<Visualizer::SetOnlyParameters::Tag, Visualizer>> mSetOnlyParamTags;
+ std::vector<Visualizer::GetOnlyParameters::Tag> mGetOnlyParamTags;
+ void CleanUp() {
+ mCommonTags.clear();
+ mSetOnlyParamTags.clear();
+ mGetOnlyParamTags.clear();
+ }
+};
+
+TEST_P(VisualizerParamTest, SetAndGetCaptureSize) {
+ EXPECT_NO_FATAL_FAILURE(addCaptureSizeParam(mCaptureSize));
+ SetAndGetCommonParameters();
+}
+
+TEST_P(VisualizerParamTest, SetAndGetScalingMode) {
+ EXPECT_NO_FATAL_FAILURE(addScalingModeParam(mScalingMode));
+ SetAndGetCommonParameters();
+}
+
+TEST_P(VisualizerParamTest, SetAndGetMeasurementMode) {
+ EXPECT_NO_FATAL_FAILURE(addMeasurementModeParam(mMeasurementMode));
+ SetAndGetCommonParameters();
+}
+
+TEST_P(VisualizerParamTest, SetAndGetLatency) {
+ EXPECT_NO_FATAL_FAILURE(addLatencyParam(mLatency));
+ SetAndGetSetOnlyParameters();
+}
+
+TEST_P(VisualizerParamTest, GetAndSetMeasurement) {
+ EXPECT_NO_FATAL_FAILURE(addMeasurementTag());
+ GetandSetGetOnlyParameters();
+}
+
+TEST_P(VisualizerParamTest, GetAndSetCaptureBytes) {
+ EXPECT_NO_FATAL_FAILURE(addCaptureBytesTag());
+ GetandSetGetOnlyParameters();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ VisualizerTest, VisualizerParamTest,
+ ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kVisualizerTypeUUID)),
+ testing::ValuesIn(kCaptureSizeValues),
+ testing::ValuesIn(kScalingModeValues),
+ testing::ValuesIn(kMeasurementModeValues),
+ testing::ValuesIn(kLatencyValues)),
+ [](const testing::TestParamInfo<VisualizerParamTest::ParamType>& info) {
+ auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
+ std::string captureSize = std::to_string(std::get<PARAM_CAPTURE_SIZE>(info.param));
+ std::string scalingMode =
+ std::to_string(static_cast<int>(std::get<PARAM_SCALING_MODE>(info.param)));
+ std::string measurementMode =
+ std::to_string(static_cast<int>(std::get<PARAM_MEASUREMENT_MODE>(info.param)));
+ std::string latency = std::to_string(std::get<PARAM_LATENCY>(info.param));
+
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_captureSize" + captureSize +
+ "_scalingMode" + scalingMode + "_measurementMode" + measurementMode +
+ "_latency" + latency;
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VisualizerParamTest);
+
+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/common/all-versions/default/service/Android.bp b/audio/common/all-versions/default/service/Android.bp
index 9890be2..2fcfb23 100644
--- a/audio/common/all-versions/default/service/Android.bp
+++ b/audio/common/all-versions/default/service/Android.bp
@@ -38,9 +38,15 @@
name: "android.hardware.audio.service",
init_rc: ["android.hardware.audio.service.rc"],
+ vintf_fragments: ["android.hardware.audio.sounddose-aidl.xml"],
relative_install_path: "hw",
vendor: true,
+ defaults: [
+ "android_hardware_audio_config_defaults",
+ "latest_android_hardware_audio_sounddose_ndk_shared",
+ ],
+
srcs: ["service.cpp"],
cflags: [
@@ -50,6 +56,7 @@
],
shared_libs: [
+ "//hardware/interfaces/audio/aidl/sounddose/default:libsounddoseserviceexampleimpl",
"libcutils",
"libbinder",
"libbinder_ndk",
@@ -58,10 +65,6 @@
"libutils",
"libhardware",
],
-
- defaults: [
- "android_hardware_audio_config_defaults",
- ],
}
// Legacy service name, use android.hardware.audio.service instead
diff --git a/audio/common/all-versions/default/service/android.hardware.audio.sounddose-aidl.xml b/audio/common/all-versions/default/service/android.hardware.audio.sounddose-aidl.xml
new file mode 100644
index 0000000..a297bfb
--- /dev/null
+++ b/audio/common/all-versions/default/service/android.hardware.audio.sounddose-aidl.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.audio.sounddose</name>
+ <version>1</version>
+ <fqname>ISoundDoseFactory/default</fqname>
+ </hal>
+</manifest>
diff --git a/audio/common/all-versions/default/service/service.cpp b/audio/common/all-versions/default/service/service.cpp
index fbf6165..e79ad75 100644
--- a/audio/common/all-versions/default/service/service.cpp
+++ b/audio/common/all-versions/default/service/service.cpp
@@ -20,6 +20,10 @@
#include <string>
#include <vector>
+#include <SoundDoseFactory.h>
+#include <android-base/logging.h>
+#include <android/binder_ibinder_platform.h>
+#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <binder/ProcessState.h>
#include <cutils/properties.h>
@@ -33,6 +37,8 @@
using InterfacesList = std::vector<std::string>;
+using aidl::android::hardware::audio::sounddose::SoundDoseFactory;
+
/** Try to register the provided factories in the provided order.
* If any registers successfully, do not register any other and return true.
* If all fail, return false.
@@ -164,5 +170,13 @@
}
}
+ // Register ISoundDoseFactory interface as a workaround for using the audio AIDL HAL
+ auto soundDoseDefault = ndk::SharedRefBase::make<SoundDoseFactory>();
+ const std::string soundDoseDefaultName =
+ std::string() + SoundDoseFactory::descriptor + "/default";
+ binder_status_t status = AServiceManager_addService(soundDoseDefault->asBinder().get(),
+ soundDoseDefaultName.c_str());
+ CHECK_EQ(STATUS_OK, status);
+
joinRpcThreadpool();
}
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index f51a8d0..9d93bb0 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -30,6 +30,7 @@
"android.hardware.audio.common.test.utility",
"audioclient-types-aidl-cpp",
"libaudioclient_aidl_conversion",
+ "libaudio_aidl_conversion_common_cpp",
"libstagefright_foundation",
],
shared_libs: [
diff --git a/automotive/vehicle/aidl/Android.bp b/automotive/vehicle/aidl/Android.bp
index 9aeb4d2..88d1c74 100644
--- a/automotive/vehicle/aidl/Android.bp
+++ b/automotive/vehicle/aidl/Android.bp
@@ -27,6 +27,7 @@
srcs: [
"android/hardware/automotive/vehicle/**/*.aidl",
],
+ frozen: true,
stability: "vintf",
backend: {
cpp: {
diff --git a/biometrics/common/aidl/Android.bp b/biometrics/common/aidl/Android.bp
index 167e0c7..0f795f8 100644
--- a/biometrics/common/aidl/Android.bp
+++ b/biometrics/common/aidl/Android.bp
@@ -13,6 +13,7 @@
srcs: [
"android/hardware/biometrics/common/*.aidl",
],
+ frozen: true,
stability: "vintf",
backend: {
java: {
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/AidlCasPluginDescriptor.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/AidlCasPluginDescriptor.aidl
index 7b8099f..89d8625 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/AidlCasPluginDescriptor.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/AidlCasPluginDescriptor.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
parcelable AidlCasPluginDescriptor {
int caSystemId;
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/DestinationBuffer.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/DestinationBuffer.aidl
index dd355af..b69cc33 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/DestinationBuffer.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/DestinationBuffer.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
union DestinationBuffer {
android.hardware.cas.SharedBuffer nonsecureMemory;
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICas.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICas.aidl
index e169beb..28c9eb0 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICas.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICas.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
interface ICas {
void closeSession(in byte[] sessionId);
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICasListener.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICasListener.aidl
index ebc13ce..db75062 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICasListener.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICasListener.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
interface ICasListener {
void onEvent(in int event, in int arg, in byte[] data);
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IDescrambler.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IDescrambler.aidl
index 9bf7903..411891b 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IDescrambler.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IDescrambler.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
interface IDescrambler {
int descramble(in android.hardware.cas.ScramblingControl scramblingControl, in android.hardware.cas.SubSample[] subSamples, in android.hardware.cas.SharedBuffer srcBuffer, in long srcOffset, in android.hardware.cas.DestinationBuffer dstBuffer, in long dstOffset);
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IMediaCasService.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IMediaCasService.aidl
index f5c8018..1f945a7 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IMediaCasService.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IMediaCasService.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
interface IMediaCasService {
android.hardware.cas.IDescrambler createDescrambler(in int CA_system_id);
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingMode.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingMode.aidl
index f34da4e..a0b08c9 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingMode.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingMode.aidl
@@ -45,9 +45,9 @@
DVB_IDSA = 7,
MULTI2 = 8,
AES128 = 9,
- AES_CBC = 10,
- AES_ECB = 11,
- AES_SCTE52 = 12,
- TDES_ECB = 13,
- TDES_SCTE52 = 14,
+ AES_ECB = 10,
+ AES_SCTE52 = 11,
+ TDES_ECB = 12,
+ TDES_SCTE52 = 13,
+ AES_CBC = 14,
}
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SharedBuffer.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SharedBuffer.aidl
index a18aa57..9200b1d 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SharedBuffer.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SharedBuffer.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
parcelable SharedBuffer {
android.hardware.common.Ashmem heapBase;
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/Status.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/Status.aidl
index 3d3a8a0..343c810 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/Status.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/Status.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
parcelable Status {
const int OK = 0;
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/StatusEvent.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/StatusEvent.aidl
index 178cabc..165c0d4 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/StatusEvent.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/StatusEvent.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@Backing(type="byte") @VintfStability
enum StatusEvent {
PLUGIN_PHYSICAL_MODULE_CHANGED = 0,
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SubSample.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SubSample.aidl
index d9ee3b4..5bd1a1e 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SubSample.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SubSample.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
parcelable SubSample {
int numBytesOfClearData;
diff --git a/cas/aidl/android/hardware/cas/AidlCasPluginDescriptor.aidl b/cas/aidl/android/hardware/cas/AidlCasPluginDescriptor.aidl
index 55b328a..1dc7ac6 100644
--- a/cas/aidl/android/hardware/cas/AidlCasPluginDescriptor.aidl
+++ b/cas/aidl/android/hardware/cas/AidlCasPluginDescriptor.aidl
@@ -18,6 +18,7 @@
/**
* Describes a CAS plugin with its system ID and name.
+ * @hide
*/
@VintfStability
parcelable AidlCasPluginDescriptor {
diff --git a/cas/aidl/android/hardware/cas/DestinationBuffer.aidl b/cas/aidl/android/hardware/cas/DestinationBuffer.aidl
index 068f29d..74336c2 100644
--- a/cas/aidl/android/hardware/cas/DestinationBuffer.aidl
+++ b/cas/aidl/android/hardware/cas/DestinationBuffer.aidl
@@ -19,6 +19,9 @@
import android.hardware.cas.SharedBuffer;
import android.hardware.common.NativeHandle;
+/**
+ * @hide
+ */
@VintfStability
union DestinationBuffer {
/**
diff --git a/cas/aidl/android/hardware/cas/ICas.aidl b/cas/aidl/android/hardware/cas/ICas.aidl
index 4c938c7..e6494ae 100644
--- a/cas/aidl/android/hardware/cas/ICas.aidl
+++ b/cas/aidl/android/hardware/cas/ICas.aidl
@@ -23,6 +23,7 @@
* ICas is the API to control the CAS. It is used to manage sessions, provision/refresh the cas
* system, and process the EMM/ECM messages. It also allows bi-directional, scheme-specific
* communications between the client and the cas system.
+ * @hide
*/
@VintfStability
interface ICas {
diff --git a/cas/aidl/android/hardware/cas/ICasListener.aidl b/cas/aidl/android/hardware/cas/ICasListener.aidl
index 32d843f..21cd257 100644
--- a/cas/aidl/android/hardware/cas/ICasListener.aidl
+++ b/cas/aidl/android/hardware/cas/ICasListener.aidl
@@ -18,6 +18,9 @@
import android.hardware.cas.StatusEvent;
+/**
+ * @hide
+ */
@VintfStability
interface ICasListener {
/**
diff --git a/cas/aidl/android/hardware/cas/IDescrambler.aidl b/cas/aidl/android/hardware/cas/IDescrambler.aidl
index 33fbe75..0ac995c 100644
--- a/cas/aidl/android/hardware/cas/IDescrambler.aidl
+++ b/cas/aidl/android/hardware/cas/IDescrambler.aidl
@@ -23,6 +23,7 @@
/**
* IDescrambler is the API to control the descrambling operations.
+ * @hide
*/
@VintfStability
interface IDescrambler {
diff --git a/cas/aidl/android/hardware/cas/IMediaCasService.aidl b/cas/aidl/android/hardware/cas/IMediaCasService.aidl
index 8bc31f6..641c4a9 100644
--- a/cas/aidl/android/hardware/cas/IMediaCasService.aidl
+++ b/cas/aidl/android/hardware/cas/IMediaCasService.aidl
@@ -26,6 +26,7 @@
* cas HAL to create cas and descrambler plugin instances. A cas plugin instance
* opens cas sessions which are used to obtain keys for a descrambler session,
* which can in turn be used to descramble protected video content.
+ * @hide
*/
@VintfStability
interface IMediaCasService {
diff --git a/cas/aidl/android/hardware/cas/ScramblingMode.aidl b/cas/aidl/android/hardware/cas/ScramblingMode.aidl
index cf4d4e7..dfca8dc 100644
--- a/cas/aidl/android/hardware/cas/ScramblingMode.aidl
+++ b/cas/aidl/android/hardware/cas/ScramblingMode.aidl
@@ -71,11 +71,6 @@
AES128,
/**
- * Advanced Encryption System (AES) Cipher Block Chaining (CBC) mode.
- */
- AES_CBC,
-
- /**
* Advanced Encryption System (AES) Electronic Code Book (ECB) mode.
*/
AES_ECB,
@@ -96,4 +91,9 @@
* Engineers (SCTE) 52 mode.
*/
TDES_SCTE52,
+
+ /**
+ * Advanced Encryption System (AES) Cipher Block Chaining (CBC) mode.
+ */
+ AES_CBC,
}
diff --git a/cas/aidl/android/hardware/cas/SharedBuffer.aidl b/cas/aidl/android/hardware/cas/SharedBuffer.aidl
index 8a94ff7..0c89cfe 100644
--- a/cas/aidl/android/hardware/cas/SharedBuffer.aidl
+++ b/cas/aidl/android/hardware/cas/SharedBuffer.aidl
@@ -22,6 +22,7 @@
* SharedBuffer describes a shared buffer which is defined by a heapBase, an
* offset and a size. The offset is relative to the shared memory base for the
* memory region identified by heapBase.
+ * @hide
*/
@VintfStability
parcelable SharedBuffer {
diff --git a/cas/aidl/android/hardware/cas/Status.aidl b/cas/aidl/android/hardware/cas/Status.aidl
index b2be34b..e7ae8ff 100644
--- a/cas/aidl/android/hardware/cas/Status.aidl
+++ b/cas/aidl/android/hardware/cas/Status.aidl
@@ -16,6 +16,9 @@
package android.hardware.cas;
+/**
+ * @hide
+ */
@VintfStability
parcelable Status {
/**
diff --git a/cas/aidl/android/hardware/cas/StatusEvent.aidl b/cas/aidl/android/hardware/cas/StatusEvent.aidl
index 0f62634..1fe732e 100644
--- a/cas/aidl/android/hardware/cas/StatusEvent.aidl
+++ b/cas/aidl/android/hardware/cas/StatusEvent.aidl
@@ -18,6 +18,7 @@
/**
* The Event Type for status change.
+ * @hide
*/
@VintfStability
@Backing(type="byte")
diff --git a/cas/aidl/android/hardware/cas/SubSample.aidl b/cas/aidl/android/hardware/cas/SubSample.aidl
index c1353cb..8e1ff77 100644
--- a/cas/aidl/android/hardware/cas/SubSample.aidl
+++ b/cas/aidl/android/hardware/cas/SubSample.aidl
@@ -19,6 +19,7 @@
/**
* A subsample consists of some number of bytes of clear (unscrambled)
* data followed by a number of bytes of scrambled data.
+ * @hide
*/
@VintfStability
parcelable SubSample {
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index c4a5d25..5e1589b 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -53,6 +53,14 @@
</interface>
</hal>
<hal format="aidl" optional="true">
+ <name>android.hardware.audio.sounddose</name>
+ <version>1</version>
+ <interface>
+ <name>ISoundDoseFactory</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="aidl" optional="true">
<name>android.hardware.authsecret</name>
<version>1</version>
<interface>
@@ -461,6 +469,15 @@
</interface>
</hal>
<hal format="aidl" optional="true">
+ <name>android.hardware.media.c2</name>
+ <version>1</version>
+ <interface>
+ <name>IComponentStore</name>
+ <regex-instance>default[0-9]*</regex-instance>
+ <regex-instance>vendor[0-9]*_software</regex-instance>
+ </interface>
+ </hal>
+ <hal format="aidl" optional="true">
<name>android.hardware.memtrack</name>
<version>1</version>
<interface>
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index cb77c7b..cf1e138 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -61,6 +61,7 @@
"android.hardware.graphics.common",
"android.hardware.input.common",
"android.hardware.keymaster",
+ "android.hardware.media.bufferpool2",
"android.hardware.radio",
"android.hardware.uwb.fira_android",
diff --git a/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl b/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl
index 8126143..4bca795 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl
@@ -22,9 +22,9 @@
* This is an enum that defines the common types of gralloc 4 buffer metadata. The comments for
* each enum include a description of the metadata that is associated with the type.
*
- * IMapper@4.x must support getting the following standard buffer metadata types, with the exception
- * of SMPTE 2094-10 metadata. IMapper@4.x may support setting these standard buffer metadata types
- * as well.
+ * IMapper@4.x & later must support getting the following standard buffer metadata types, with the
+ * exception of SMPTE 2094-10 and SMPTE 2094-40 metadata. IMapper@4.x & later may support setting
+ * these standard buffer metadata types as well.
*
* When encoding these StandardMetadataTypes into a byte stream, the associated MetadataType is
* is first encoded followed by the StandardMetadataType value. The MetadataType is encoded by
diff --git a/graphics/mapper/stable-c/Android.bp b/graphics/mapper/stable-c/Android.bp
index c03f67e..d40e160 100644
--- a/graphics/mapper/stable-c/Android.bp
+++ b/graphics/mapper/stable-c/Android.bp
@@ -61,6 +61,10 @@
srcs: [
"implutils/impltests.cpp",
],
+ shared_libs: [
+ "libgralloctypes",
+ "libhidlbase",
+ ],
visibility: [":__subpackages__"],
cpp_std: "experimental",
}
diff --git a/graphics/mapper/stable-c/implutils/impltests.cpp b/graphics/mapper/stable-c/implutils/impltests.cpp
index 9c5d70b..f12b069 100644
--- a/graphics/mapper/stable-c/implutils/impltests.cpp
+++ b/graphics/mapper/stable-c/implutils/impltests.cpp
@@ -18,123 +18,29 @@
#include <android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h>
#include <android/hardware/graphics/mapper/utils/IMapperProvider.h>
+#include <drm/drm_fourcc.h>
+#include <gralloctypes/Gralloc4.h>
+#include <span>
#include <vector>
+using namespace ::android;
using namespace ::android::hardware::graphics::mapper;
using namespace ::aidl::android::hardware::graphics::common;
+namespace gralloc4 = ::android::gralloc4;
+using ::android::hardware::hidl_vec;
// These tests are primarily interested in hitting all the different *types* that can be
// serialized/deserialized than in exhaustively testing all the StandardMetadataTypes.
// Exhaustive testing of the actual metadata types is relegated for IMapper's VTS suite
// where meaning & correctness of values are more narrowly defined (eg, read-only values)
-TEST(Metadata, setGetBufferId) {
- using BufferId = StandardMetadata<StandardMetadataType::BUFFER_ID>::value;
+static constexpr auto HeaderSize = 69;
- std::vector<char> buffer;
- buffer.resize(12, 0);
- *reinterpret_cast<int64_t*>(buffer.data()) = 42;
-
- EXPECT_EQ(8, BufferId::encode(18, buffer.data(), 0));
- EXPECT_EQ(42, *reinterpret_cast<int64_t*>(buffer.data()));
- EXPECT_EQ(8, BufferId::encode(18, buffer.data(), buffer.size()));
- EXPECT_EQ(18, *reinterpret_cast<int64_t*>(buffer.data()));
- EXPECT_FALSE(BufferId::decode(buffer.data(), 0));
- auto read = BufferId::decode(buffer.data(), buffer.size());
- EXPECT_TRUE(read.has_value());
- EXPECT_EQ(18, read.value_or(0));
+static std::span<uint8_t> SkipHeader(std::vector<uint8_t>& buffer) {
+ return std::span<uint8_t>(buffer).subspan(HeaderSize);
}
-TEST(Metadata, setGetDataspace) {
- using DataspaceValue = StandardMetadata<StandardMetadataType::DATASPACE>::value;
- using intType = std::underlying_type_t<Dataspace>;
- std::vector<char> buffer;
- buffer.resize(12, 0);
-
- EXPECT_EQ(4, DataspaceValue::encode(Dataspace::BT2020, buffer.data(), 0));
- EXPECT_EQ(0, *reinterpret_cast<intType*>(buffer.data()));
- EXPECT_EQ(4, DataspaceValue::encode(Dataspace::BT2020, buffer.data(), buffer.size()));
- EXPECT_EQ(static_cast<intType>(Dataspace::BT2020), *reinterpret_cast<intType*>(buffer.data()));
- EXPECT_FALSE(DataspaceValue::decode(buffer.data(), 0));
- auto read = DataspaceValue::decode(buffer.data(), buffer.size());
- ASSERT_TRUE(read.has_value());
- EXPECT_EQ(Dataspace::BT2020, *read);
-}
-
-TEST(Metadata, setGetValidName) {
- using NameValue = StandardMetadata<StandardMetadataType::NAME>::value;
-
- std::vector<char> buffer;
- buffer.resize(100, 'a');
- buffer[buffer.size() - 1] = '\0';
-
- // len("Hello") + sizeof(int64)
- constexpr int expectedSize = 5 + sizeof(int64_t);
- EXPECT_EQ(expectedSize, NameValue::encode("Hello", buffer.data(), buffer.size()));
- EXPECT_EQ(5, *reinterpret_cast<int64_t*>(buffer.data()));
- // Verify didn't write past the end of the desired size
- EXPECT_EQ('a', buffer[expectedSize]);
-
- auto readValue = NameValue::decode(buffer.data(), buffer.size());
- ASSERT_TRUE(readValue.has_value());
- EXPECT_EQ(5, readValue->length());
- EXPECT_EQ("Hello", *readValue);
-}
-
-TEST(Metadata, setGetInvalidName) {
- using NameValue = StandardMetadata<StandardMetadataType::NAME>::value;
-
- std::vector<char> buffer;
- buffer.resize(12, 'a');
- buffer[buffer.size() - 1] = '\0';
-
- // len("This is a long string") + sizeof(int64)
- constexpr int expectedSize = 21 + sizeof(int64_t);
- EXPECT_EQ(expectedSize,
- NameValue::encode("This is a long string", buffer.data(), buffer.size()));
- EXPECT_EQ(21, *reinterpret_cast<int64_t*>(buffer.data()));
- // Verify didn't write the too-long string
- EXPECT_EQ('a', buffer[9]);
- EXPECT_EQ('\0', buffer[buffer.size() - 1]);
-
- auto readValue = NameValue::decode(buffer.data(), buffer.size());
- EXPECT_FALSE(readValue.has_value());
- readValue = NameValue::decode(buffer.data(), 0);
- ASSERT_FALSE(readValue.has_value());
-}
-
-TEST(Metadata, wouldOverflowName) {
- using NameValue = StandardMetadata<StandardMetadataType::NAME>::value;
- std::vector<char> buffer(100, 0);
-
- // int_max + sizeof(int64) overflows int32
- std::string_view bad_string{"badbeef", std::numeric_limits<int32_t>::max()};
- EXPECT_EQ(-AIMAPPER_ERROR_BAD_VALUE,
- NameValue::encode(bad_string, buffer.data(), buffer.size()));
-
- // check barely overflows
- bad_string = std::string_view{"badbeef", std::numeric_limits<int32_t>::max() - 7};
- EXPECT_EQ(-AIMAPPER_ERROR_BAD_VALUE,
- NameValue::encode(bad_string, buffer.data(), buffer.size()));
-}
-
-TEST(Metadata, setGetCompression) {
- using CompressionValue = StandardMetadata<StandardMetadataType::COMPRESSION>::value;
- ExtendableType myCompression{"bestest_compression_ever", 42};
- std::vector<char> buffer(100, '\0');
- const int expectedSize = myCompression.name.length() + sizeof(int64_t) + sizeof(int64_t);
- EXPECT_EQ(expectedSize, CompressionValue::encode(myCompression, buffer.data(), 0));
- EXPECT_EQ(0, buffer[0]);
- EXPECT_EQ(expectedSize, CompressionValue::encode(myCompression, buffer.data(), buffer.size()));
- EXPECT_EQ(myCompression.name.length(), *reinterpret_cast<int64_t*>(buffer.data()));
- EXPECT_FALSE(CompressionValue::decode(buffer.data(), 0).has_value());
- auto read = CompressionValue::decode(buffer.data(), buffer.size());
- ASSERT_TRUE(read.has_value());
- EXPECT_EQ(myCompression, read.value());
-}
-
-TEST(Metadata, setGetPlaneLayout) {
- using PlaneLayoutValue = StandardMetadata<StandardMetadataType::PLANE_LAYOUTS>::value;
+static std::vector<PlaneLayout> fakePlaneLayouts() {
PlaneLayout myPlaneLayout;
myPlaneLayout.offsetInBytes = 10;
myPlaneLayout.sampleIncrementInBits = 11;
@@ -153,23 +59,147 @@
it.sizeInBits = 30 + i;
}
- std::vector<PlaneLayout> layouts{myPlaneLayout, PlaneLayout{}};
+ return std::vector<PlaneLayout>{myPlaneLayout, PlaneLayout{}};
+}
- std::vector<char> buffer(5000, '\0');
+TEST(Metadata, setGetBufferId) {
+ using BufferId = StandardMetadata<StandardMetadataType::BUFFER_ID>::value;
+
+ std::vector<uint8_t> buffer(10000, 0);
+ int64_t* payload = reinterpret_cast<int64_t*>(SkipHeader(buffer).data());
+ *payload = 42;
+
+ EXPECT_EQ(8 + HeaderSize, BufferId::encode(18, buffer.data(), 0));
+ EXPECT_EQ(42, *payload);
+ EXPECT_EQ(8 + HeaderSize, BufferId::encode(18, buffer.data(), buffer.size()));
+ EXPECT_EQ(18, *payload);
+ EXPECT_FALSE(BufferId::decode(buffer.data(), 0));
+ auto read = BufferId::decode(buffer.data(), buffer.size());
+ EXPECT_TRUE(read.has_value());
+ EXPECT_EQ(18, read.value_or(0));
+}
+
+TEST(Metadata, setGetDataspace) {
+ using DataspaceValue = StandardMetadata<StandardMetadataType::DATASPACE>::value;
+ using intType = std::underlying_type_t<Dataspace>;
+ std::vector<uint8_t> buffer(10000, 0);
+ auto data = SkipHeader(buffer);
+
+ EXPECT_EQ(4 + HeaderSize, DataspaceValue::encode(Dataspace::BT2020, buffer.data(), 0));
+ EXPECT_EQ(0, *reinterpret_cast<intType*>(data.data()));
+ EXPECT_EQ(4 + HeaderSize,
+ DataspaceValue::encode(Dataspace::BT2020, buffer.data(), buffer.size()));
+ EXPECT_EQ(static_cast<intType>(Dataspace::BT2020), *reinterpret_cast<intType*>(data.data()));
+ EXPECT_FALSE(DataspaceValue::decode(buffer.data(), 0));
+ auto read = DataspaceValue::decode(buffer.data(), buffer.size());
+ ASSERT_TRUE(read.has_value());
+ EXPECT_EQ(Dataspace::BT2020, *read);
+}
+
+TEST(Metadata, setGetValidName) {
+ using NameValue = StandardMetadata<StandardMetadataType::NAME>::value;
+
+ std::vector<uint8_t> buffer(10000, 'a');
+
+ // len("Hello") + sizeof(int64)
+ constexpr int expectedSize = 5 + sizeof(int64_t) + HeaderSize;
+ EXPECT_EQ(expectedSize, NameValue::encode("Hello", buffer.data(), buffer.size()));
+ EXPECT_EQ(5, *reinterpret_cast<int64_t*>(SkipHeader(buffer).data()));
+ // Verify didn't write past the end of the desired size
+ EXPECT_EQ('a', buffer[expectedSize]);
+
+ auto readValue = NameValue::decode(buffer.data(), buffer.size());
+ ASSERT_TRUE(readValue.has_value());
+ EXPECT_EQ(5, readValue->length());
+ EXPECT_EQ("Hello", *readValue);
+}
+
+TEST(Metadata, setGetInvalidName) {
+ using NameValue = StandardMetadata<StandardMetadataType::NAME>::value;
+
+ std::vector<uint8_t> buffer;
+ buffer.resize(12 + HeaderSize, 'a');
+ buffer[buffer.size() - 1] = '\0';
+
+ // len("This is a long string") + sizeof(int64)
+ constexpr int expectedSize = 21 + sizeof(int64_t) + HeaderSize;
+ EXPECT_EQ(expectedSize,
+ NameValue::encode("This is a long string", buffer.data(), buffer.size()));
+ EXPECT_EQ(21, *reinterpret_cast<int64_t*>(SkipHeader(buffer).data()));
+
+ auto readValue = NameValue::decode(buffer.data(), buffer.size());
+ EXPECT_FALSE(readValue.has_value());
+ readValue = NameValue::decode(buffer.data(), 0);
+ ASSERT_FALSE(readValue.has_value());
+}
+
+TEST(Metadata, wouldOverflowName) {
+ using NameValue = StandardMetadata<StandardMetadataType::NAME>::value;
+ std::vector<uint8_t> buffer(10000, 0);
+
+ // int_max + sizeof(int64) overflows int32
+ std::string_view bad_string{"badbeef", std::numeric_limits<int32_t>::max()};
+ EXPECT_EQ(-AIMAPPER_ERROR_BAD_VALUE,
+ NameValue::encode(bad_string, buffer.data(), buffer.size()));
+
+ // check barely overflows
+ bad_string = std::string_view{"badbeef", std::numeric_limits<int32_t>::max() - 7};
+ EXPECT_EQ(-AIMAPPER_ERROR_BAD_VALUE,
+ NameValue::encode(bad_string, buffer.data(), buffer.size()));
+}
+
+TEST(Metadata, setGetMismatchedWidthHight) {
+ // Validates that the header is properly validated on decode
+ using WidthValue = StandardMetadata<StandardMetadataType::WIDTH>::value;
+ using HeightValue = StandardMetadata<StandardMetadataType::HEIGHT>::value;
+ std::vector<uint8_t> buffer(10000, 0);
+
+ EXPECT_EQ(8 + HeaderSize, WidthValue::encode(100, buffer.data(), buffer.size()));
+ EXPECT_EQ(100, *reinterpret_cast<uint64_t*>(SkipHeader(buffer).data()));
+ auto read = WidthValue::decode(buffer.data(), buffer.size());
+ ASSERT_TRUE(read.has_value());
+ EXPECT_EQ(100, *read);
+ read = HeightValue::decode(buffer.data(), buffer.size());
+ EXPECT_FALSE(read.has_value());
+}
+
+TEST(Metadata, setGetCompression) {
+ using CompressionValue = StandardMetadata<StandardMetadataType::COMPRESSION>::value;
+ ExtendableType myCompression{"bestest_compression_ever", 42};
+ std::vector<uint8_t> buffer(10000, 0);
+ const int expectedSize =
+ myCompression.name.length() + sizeof(int64_t) + sizeof(int64_t) + HeaderSize;
+ EXPECT_EQ(expectedSize, CompressionValue::encode(myCompression, buffer.data(), 0));
+ EXPECT_EQ(0, buffer[0]);
+ EXPECT_EQ(expectedSize, CompressionValue::encode(myCompression, buffer.data(), buffer.size()));
+ EXPECT_EQ(myCompression.name.length(), *reinterpret_cast<int64_t*>(SkipHeader(buffer).data()));
+ EXPECT_FALSE(CompressionValue::decode(buffer.data(), 0).has_value());
+ auto read = CompressionValue::decode(buffer.data(), buffer.size());
+ ASSERT_TRUE(read.has_value());
+ EXPECT_EQ(myCompression, read.value());
+}
+
+TEST(Metadata, setGetPlaneLayout) {
+ using PlaneLayoutValue = StandardMetadata<StandardMetadataType::PLANE_LAYOUTS>::value;
+
+ std::vector<PlaneLayout> layouts = fakePlaneLayouts();
+
+ std::vector<uint8_t> buffer(10000, 0);
constexpr int componentSize = 8 + (4 * sizeof(int64_t));
constexpr int firstLayoutSize = (8 + 1) * sizeof(int64_t) + (3 * componentSize);
constexpr int secondLayoutSize = (8 + 1) * sizeof(int64_t);
- constexpr int expectedSize = firstLayoutSize + secondLayoutSize + sizeof(int64_t);
+ constexpr int expectedSize = firstLayoutSize + secondLayoutSize + sizeof(int64_t) + HeaderSize;
EXPECT_EQ(expectedSize, PlaneLayoutValue::encode(layouts, buffer.data(), 0));
EXPECT_EQ(0, buffer[0]);
EXPECT_EQ(expectedSize, PlaneLayoutValue::encode(layouts, buffer.data(), buffer.size()));
- EXPECT_EQ(3, reinterpret_cast<int64_t*>(buffer.data())[1]);
- EXPECT_EQ(8, reinterpret_cast<int64_t*>(buffer.data())[2]);
- EXPECT_EQ(40, reinterpret_cast<int64_t*>(buffer.data())[4]);
- EXPECT_EQ(31, reinterpret_cast<int64_t*>(buffer.data())[11]);
- EXPECT_EQ(22, reinterpret_cast<int64_t*>(buffer.data())[15]);
- EXPECT_EQ(10, reinterpret_cast<int64_t*>(buffer.data())[17]);
- EXPECT_EQ(11, reinterpret_cast<int64_t*>(buffer.data())[18]);
+ int64_t* payload = reinterpret_cast<int64_t*>(SkipHeader(buffer).data());
+ EXPECT_EQ(3, payload[1]);
+ EXPECT_EQ(8, payload[2]);
+ EXPECT_EQ(40, payload[4]);
+ EXPECT_EQ(31, payload[11]);
+ EXPECT_EQ(22, payload[15]);
+ EXPECT_EQ(10, payload[17]);
+ EXPECT_EQ(11, payload[18]);
EXPECT_FALSE(PlaneLayoutValue::decode(buffer.data(), 0).has_value());
auto read = PlaneLayoutValue::decode(buffer.data(), buffer.size());
ASSERT_TRUE(read.has_value());
@@ -178,15 +208,15 @@
TEST(Metadata, setGetRects) {
using RectsValue = StandardMetadata<StandardMetadataType::CROP>::value;
- std::vector<uint8_t> buffer(500, 0);
+ std::vector<uint8_t> buffer(10000, 0);
std::vector<Rect> cropRects{2};
cropRects[0] = Rect{10, 11, 12, 13};
cropRects[1] = Rect{20, 21, 22, 23};
- constexpr int expectedSize = sizeof(int64_t) + (8 * sizeof(int32_t));
+ constexpr int expectedSize = sizeof(int64_t) + (8 * sizeof(int32_t)) + HeaderSize;
EXPECT_EQ(expectedSize, RectsValue::encode(cropRects, buffer.data(), buffer.size()));
- EXPECT_EQ(2, reinterpret_cast<int64_t*>(buffer.data())[0]);
- EXPECT_EQ(10, reinterpret_cast<int32_t*>(buffer.data())[2]);
+ EXPECT_EQ(2, reinterpret_cast<int64_t*>(SkipHeader(buffer).data())[0]);
+ EXPECT_EQ(10, reinterpret_cast<int32_t*>(SkipHeader(buffer).data())[2]);
auto read = RectsValue::decode(buffer.data(), buffer.size());
ASSERT_TRUE(read.has_value());
EXPECT_EQ(cropRects.size(), read->size());
@@ -203,8 +233,8 @@
source.primaryGreen = XyColor{.3f, .4f};
source.primaryBlue = XyColor{.5f, .6f};
- constexpr int expectedSize = 10 * sizeof(float);
- std::vector<uint8_t> buffer(500, 0);
+ constexpr int expectedSize = 10 * sizeof(float) + HeaderSize;
+ std::vector<uint8_t> buffer(10000, 0);
EXPECT_EQ(expectedSize, Smpte2086Value::encode(source, buffer.data(), buffer.size()));
auto read = Smpte2086Value::decode(buffer.data(), buffer.size());
ASSERT_TRUE(read.has_value());
@@ -223,8 +253,8 @@
source.maxFrameAverageLightLevel = 244.55f;
source.maxContentLightLevel = 202.202f;
- constexpr int expectedSize = 2 * sizeof(float);
- std::vector<uint8_t> buffer(500, 0);
+ constexpr int expectedSize = 2 * sizeof(float) + HeaderSize;
+ std::vector<uint8_t> buffer(10000, 0);
EXPECT_EQ(expectedSize, Cta861_3Value::encode(source, buffer.data(), buffer.size()));
auto read = Cta861_3Value::decode(buffer.data(), buffer.size());
ASSERT_TRUE(read.has_value());
@@ -240,14 +270,14 @@
TEST(Metadata, setGetSmpte2094_10) {
using SMPTE2094_10Value = StandardMetadata<StandardMetadataType::SMPTE2094_10>::value;
- std::vector<uint8_t> buffer(500, 0);
+ std::vector<uint8_t> buffer(10000, 0);
EXPECT_EQ(0, SMPTE2094_10Value::encode(std::nullopt, buffer.data(), buffer.size()));
auto read = SMPTE2094_10Value::decode(buffer.data(), 0);
ASSERT_TRUE(read.has_value());
EXPECT_FALSE(read->has_value());
const std::vector<uint8_t> emptyBuffer;
- EXPECT_EQ(sizeof(int64_t),
+ EXPECT_EQ(sizeof(int64_t) + HeaderSize,
SMPTE2094_10Value::encode(emptyBuffer, buffer.data(), buffer.size()));
read = SMPTE2094_10Value::decode(buffer.data(), buffer.size());
ASSERT_TRUE(read.has_value());
@@ -255,7 +285,7 @@
EXPECT_EQ(0, read->value().size());
const std::vector<uint8_t> simpleBuffer{0, 1, 2, 3, 4, 5};
- EXPECT_EQ(sizeof(int64_t) + 6,
+ EXPECT_EQ(sizeof(int64_t) + 6 + HeaderSize,
SMPTE2094_10Value::encode(simpleBuffer, buffer.data(), buffer.size()));
read = SMPTE2094_10Value::decode(buffer.data(), buffer.size());
ASSERT_TRUE(read.has_value());
@@ -266,7 +296,7 @@
TEST(MetadataProvider, bufferId) {
using BufferId = StandardMetadata<StandardMetadataType::BUFFER_ID>::value;
- std::vector<uint8_t> buffer(500, 0);
+ std::vector<uint8_t> buffer(10000, 0);
int result = provideStandardMetadata(StandardMetadataType::BUFFER_ID, buffer.data(),
buffer.size(), []<StandardMetadataType T>(auto&& provide) {
if constexpr (T == StandardMetadataType::BUFFER_ID) {
@@ -275,7 +305,7 @@
return 0;
});
- EXPECT_EQ(8, result);
+ EXPECT_EQ(8 + HeaderSize, result);
auto read = BufferId::decode(buffer.data(), buffer.size());
EXPECT_EQ(42, read.value_or(0));
}
@@ -312,3 +342,193 @@
EXPECT_EQ(-AIMAPPER_ERROR_UNSUPPORTED, result)
<< "100 (out of range) should have resulted in UNSUPPORTED";
}
+
+template <StandardMetadataType T>
+std::vector<uint8_t> encode(const typename StandardMetadata<T>::value_type& value) {
+ using Value = typename StandardMetadata<T>::value;
+
+ int desiredSize = Value::encode(value, nullptr, 0);
+ EXPECT_GE(desiredSize, 0);
+ std::vector<uint8_t> buffer;
+ buffer.resize(desiredSize);
+ EXPECT_EQ(desiredSize, Value::encode(value, buffer.data(), buffer.size()));
+ return buffer;
+}
+
+TEST(MetadataGralloc4Interop, BufferId) {
+ auto mpbuf = encode<StandardMetadataType::BUFFER_ID>(42);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeBufferId(42, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Name) {
+ auto mpbuf = encode<StandardMetadataType::NAME>("Hello, Interop!");
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeName("Hello, Interop!", &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Width) {
+ auto mpbuf = encode<StandardMetadataType::WIDTH>(128);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeWidth(128, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Height) {
+ auto mpbuf = encode<StandardMetadataType::HEIGHT>(64);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeHeight(64, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, LayerCount) {
+ auto mpbuf = encode<StandardMetadataType::LAYER_COUNT>(3);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeLayerCount(3, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, PixelFormatRequested) {
+ auto mpbuf = encode<StandardMetadataType::PIXEL_FORMAT_REQUESTED>(PixelFormat::RGBX_8888);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodePixelFormatRequested(
+ hardware::graphics::common::V1_2::PixelFormat::RGBX_8888, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, PixelFormatFourcc) {
+ auto mpbuf = encode<StandardMetadataType::PIXEL_FORMAT_FOURCC>(DRM_FORMAT_ABGR8888);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodePixelFormatFourCC(DRM_FORMAT_ABGR8888, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, PixelFormatModifier) {
+ auto mpbuf = encode<StandardMetadataType::PIXEL_FORMAT_MODIFIER>(123456);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodePixelFormatModifier(123456, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Usage) {
+ auto mpbuf = encode<StandardMetadataType::USAGE>(BufferUsage::COMPOSER_OVERLAY);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR,
+ gralloc4::encodeUsage(
+ static_cast<uint64_t>(
+ hardware::graphics::common::V1_2::BufferUsage::COMPOSER_OVERLAY),
+ &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, AllocationSize) {
+ auto mpbuf = encode<StandardMetadataType::ALLOCATION_SIZE>(10200);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeAllocationSize(10200, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, ProtectedContent) {
+ auto mpbuf = encode<StandardMetadataType::PROTECTED_CONTENT>(1);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeProtectedContent(1, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Compression) {
+ auto mpbuf = encode<StandardMetadataType::COMPRESSION>(
+ gralloc4::Compression_DisplayStreamCompression);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR,
+ gralloc4::encodeCompression(gralloc4::Compression_DisplayStreamCompression, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Interlaced) {
+ auto mpbuf = encode<StandardMetadataType::INTERLACED>(gralloc4::Interlaced_TopBottom);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeInterlaced(gralloc4::Interlaced_TopBottom, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, ChromeSitting) {
+ auto mpbuf =
+ encode<StandardMetadataType::CHROMA_SITING>(gralloc4::ChromaSiting_SitedInterstitial);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR,
+ gralloc4::encodeChromaSiting(gralloc4::ChromaSiting_SitedInterstitial, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, PlaneLayouts) {
+ auto mpbuf = encode<StandardMetadataType::PLANE_LAYOUTS>(fakePlaneLayouts());
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodePlaneLayouts(fakePlaneLayouts(), &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Crop) {
+ std::vector<Rect> cropRects{Rect{10, 11, 12, 13}, Rect{20, 21, 22, 23}};
+ auto mpbuf = encode<StandardMetadataType::CROP>(cropRects);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeCrop(cropRects, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Dataspace) {
+ auto mpbuf = encode<StandardMetadataType::DATASPACE>(Dataspace::DISPLAY_P3);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(Dataspace::DISPLAY_P3, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, BlendMode) {
+ auto mpbuf = encode<StandardMetadataType::BLEND_MODE>(BlendMode::PREMULTIPLIED);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeBlendMode(BlendMode::PREMULTIPLIED, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Smpte2086) {
+ Smpte2086 hdrdata{XyColor{.1f, .2f}, XyColor{.3f, .4f}, XyColor{.5f, .6f},
+ XyColor{.7f, .8f}, 452.889f, 12.335f};
+
+ auto mpbuf = encode<StandardMetadataType::SMPTE2086>(hdrdata);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeSmpte2086(hdrdata, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Cta861_3) {
+ Cta861_3 hdrdata{302.202f, 244.55f};
+ auto mpbuf = encode<StandardMetadataType::CTA861_3>(hdrdata);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeCta861_3(hdrdata, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Smpte2094_10) {
+ auto mpbuf = encode<StandardMetadataType::SMPTE2094_10>(std::nullopt);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeSmpte2094_10(std::nullopt, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+
+ std::vector<uint8_t> hdrdata{1, 2, 3, 4, 5, 6};
+ mpbuf = encode<StandardMetadataType::SMPTE2094_10>(hdrdata);
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeSmpte2094_10(hdrdata, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Smpte2094_40) {
+ auto mpbuf = encode<StandardMetadataType::SMPTE2094_40>(std::nullopt);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeSmpte2094_40(std::nullopt, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+
+ std::vector<uint8_t> hdrdata{1, 2, 3, 4, 5, 6};
+ mpbuf = encode<StandardMetadataType::SMPTE2094_40>(hdrdata);
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeSmpte2094_40(hdrdata, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
diff --git a/graphics/mapper/stable-c/implutils/include/android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h b/graphics/mapper/stable-c/implutils/include/android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h
index 7861af8..25af6d1 100644
--- a/graphics/mapper/stable-c/implutils/include/android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h
+++ b/graphics/mapper/stable-c/implutils/include/android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h
@@ -82,7 +82,12 @@
explicit MetadataWriter(void* _Nullable destBuffer, size_t destBufferSize)
: mDest(reinterpret_cast<uint8_t*>(destBuffer)), mSizeRemaining(destBufferSize) {}
- int32_t desiredSize() const { return mDesiredSize; }
+ [[nodiscard]] int32_t desiredSize() const { return mDesiredSize; }
+
+ template <typename HEADER>
+ MetadataWriter& writeHeader() {
+ return write(HEADER::name).template write<int64_t>(HEADER::value);
+ }
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
MetadataWriter& write(T value) {
@@ -150,6 +155,18 @@
[[nodiscard]] size_t remaining() const { return mSizeRemaining; }
[[nodiscard]] bool ok() const { return mOk; }
+ template <typename HEADER>
+ MetadataReader& checkHeader() {
+ if (HEADER::name != readString()) {
+ mOk = false;
+ }
+ auto value = readInt<int64_t>();
+ if (!value || *value != HEADER::value) {
+ mOk = false;
+ }
+ return *this;
+ }
+
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
MetadataReader& read(T& dest) {
if (const void* src = advance(sizeof(T))) {
@@ -228,27 +245,33 @@
}
};
-template <typename T, class Enable = void>
+template <typename HEADER, typename T, class Enable = void>
struct MetadataValue {};
-template <typename T>
-struct MetadataValue<T, std::enable_if_t<std::is_integral_v<T>>> {
+template <typename HEADER, typename T>
+struct MetadataValue<HEADER, T, std::enable_if_t<std::is_integral_v<T>>> {
[[nodiscard]] static int32_t encode(T value, void* _Nullable destBuffer,
size_t destBufferSize) {
- return MetadataWriter{destBuffer, destBufferSize}.write(value).desiredSize();
+ return MetadataWriter{destBuffer, destBufferSize}
+ .template writeHeader<HEADER>()
+ .write(value)
+ .desiredSize();
}
[[nodiscard]] static std::optional<T> decode(const void* _Nonnull metadata,
size_t metadataSize) {
- return MetadataReader{metadata, metadataSize}.readInt<T>();
+ return MetadataReader{metadata, metadataSize}
+ .template checkHeader<HEADER>()
+ .template readInt<T>();
}
};
-template <typename T>
-struct MetadataValue<T, std::enable_if_t<std::is_enum_v<T>>> {
+template <typename HEADER, typename T>
+struct MetadataValue<HEADER, T, std::enable_if_t<std::is_enum_v<T>>> {
[[nodiscard]] static int32_t encode(T value, void* _Nullable destBuffer,
size_t destBufferSize) {
return MetadataWriter{destBuffer, destBufferSize}
+ .template writeHeader<HEADER>()
.write(static_cast<std::underlying_type_t<T>>(value))
.desiredSize();
}
@@ -256,47 +279,56 @@
[[nodiscard]] static std::optional<T> decode(const void* _Nonnull metadata,
size_t metadataSize) {
std::underlying_type_t<T> temp;
- return MetadataReader{metadata, metadataSize}.read(temp).ok()
+ return MetadataReader{metadata, metadataSize}.template checkHeader<HEADER>().read(temp).ok()
? std::optional<T>(static_cast<T>(temp))
: std::nullopt;
}
};
-template <>
-struct MetadataValue<std::string> {
+template <typename HEADER>
+struct MetadataValue<HEADER, std::string> {
[[nodiscard]] static int32_t encode(const std::string_view& value, void* _Nullable destBuffer,
size_t destBufferSize) {
- return MetadataWriter{destBuffer, destBufferSize}.write(value).desiredSize();
+ return MetadataWriter{destBuffer, destBufferSize}
+ .template writeHeader<HEADER>()
+ .write(value)
+ .desiredSize();
}
[[nodiscard]] static std::optional<std::string> decode(const void* _Nonnull metadata,
size_t metadataSize) {
- auto reader = MetadataReader{metadata, metadataSize};
+ auto reader = MetadataReader{metadata, metadataSize}.template checkHeader<HEADER>();
auto result = reader.readString();
return reader.ok() ? std::optional<std::string>{result} : std::nullopt;
}
};
-template <>
-struct MetadataValue<ExtendableType> {
+template <typename HEADER>
+struct MetadataValue<HEADER, ExtendableType> {
static_assert(sizeof(int64_t) == sizeof(ExtendableType::value));
[[nodiscard]] static int32_t encode(const ExtendableType& value, void* _Nullable destBuffer,
size_t destBufferSize) {
- return MetadataWriter{destBuffer, destBufferSize}.write(value).desiredSize();
+ return MetadataWriter{destBuffer, destBufferSize}
+ .template writeHeader<HEADER>()
+ .write(value)
+ .desiredSize();
}
[[nodiscard]] static std::optional<ExtendableType> decode(const void* _Nonnull metadata,
size_t metadataSize) {
- return MetadataReader{metadata, metadataSize}.readExtendable();
+ return MetadataReader{metadata, metadataSize}
+ .template checkHeader<HEADER>()
+ .readExtendable();
}
};
-template <>
-struct MetadataValue<std::vector<PlaneLayout>> {
+template <typename HEADER>
+struct MetadataValue<HEADER, std::vector<PlaneLayout>> {
[[nodiscard]] static int32_t encode(const std::vector<PlaneLayout>& values,
void* _Nullable destBuffer, size_t destBufferSize) {
MetadataWriter writer{destBuffer, destBufferSize};
+ writer.template writeHeader<HEADER>();
writer.write<int64_t>(values.size());
for (const auto& value : values) {
writer.write<int64_t>(value.components.size());
@@ -321,13 +353,14 @@
[[nodiscard]] static DecodeResult decode(const void* _Nonnull metadata, size_t metadataSize) {
std::vector<PlaneLayout> values;
MetadataReader reader{metadata, metadataSize};
+ reader.template checkHeader<HEADER>();
auto numPlanes = reader.readInt<int64_t>().value_or(0);
values.reserve(numPlanes);
for (int i = 0; i < numPlanes && reader.ok(); i++) {
PlaneLayout& value = values.emplace_back();
auto numPlaneComponents = reader.readInt<int64_t>().value_or(0);
value.components.reserve(numPlaneComponents);
- for (int i = 0; i < numPlaneComponents && reader.ok(); i++) {
+ for (int j = 0; j < numPlaneComponents && reader.ok(); j++) {
PlaneLayoutComponent& component = value.components.emplace_back();
reader.read(component.type)
.read<int64_t>(component.offsetInBits)
@@ -346,11 +379,12 @@
}
};
-template <>
-struct MetadataValue<std::vector<Rect>> {
+template <typename HEADER>
+struct MetadataValue<HEADER, std::vector<Rect>> {
[[nodiscard]] static int32_t encode(const std::vector<Rect>& value, void* _Nullable destBuffer,
size_t destBufferSize) {
MetadataWriter writer{destBuffer, destBufferSize};
+ writer.template writeHeader<HEADER>();
writer.write<int64_t>(value.size());
for (auto& rect : value) {
writer.write<int32_t>(rect.left)
@@ -364,6 +398,7 @@
using DecodeResult = std::optional<std::vector<Rect>>;
[[nodiscard]] static DecodeResult decode(const void* _Nonnull metadata, size_t metadataSize) {
MetadataReader reader{metadata, metadataSize};
+ reader.template checkHeader<HEADER>();
std::vector<Rect> value;
auto numRects = reader.readInt<int64_t>().value_or(0);
value.reserve(numRects);
@@ -378,13 +413,14 @@
}
};
-template <>
-struct MetadataValue<std::optional<Smpte2086>> {
+template <typename HEADER>
+struct MetadataValue<HEADER, std::optional<Smpte2086>> {
[[nodiscard]] static int32_t encode(const std::optional<Smpte2086>& optValue,
void* _Nullable destBuffer, size_t destBufferSize) {
if (optValue.has_value()) {
const auto& value = *optValue;
return MetadataWriter{destBuffer, destBufferSize}
+ .template writeHeader<HEADER>()
.write(value.primaryRed)
.write(value.primaryGreen)
.write(value.primaryBlue)
@@ -404,6 +440,7 @@
if (metadataSize > 0) {
Smpte2086 value;
MetadataReader reader{metadata, metadataSize};
+ reader.template checkHeader<HEADER>();
reader.read(value.primaryRed)
.read(value.primaryGreen)
.read(value.primaryBlue)
@@ -420,13 +457,14 @@
}
};
-template <>
-struct MetadataValue<std::optional<Cta861_3>> {
+template <typename HEADER>
+struct MetadataValue<HEADER, std::optional<Cta861_3>> {
[[nodiscard]] static int32_t encode(const std::optional<Cta861_3>& optValue,
void* _Nullable destBuffer, size_t destBufferSize) {
if (optValue.has_value()) {
const auto& value = *optValue;
return MetadataWriter{destBuffer, destBufferSize}
+ .template writeHeader<HEADER>()
.write(value.maxContentLightLevel)
.write(value.maxFrameAverageLightLevel)
.desiredSize();
@@ -441,6 +479,7 @@
std::optional<Cta861_3> optValue{std::nullopt};
if (metadataSize > 0) {
MetadataReader reader{metadata, metadataSize};
+ reader.template checkHeader<HEADER>();
Cta861_3 value;
reader.read(value.maxContentLightLevel).read(value.maxFrameAverageLightLevel);
if (reader.ok()) {
@@ -453,14 +492,17 @@
}
};
-template <>
-struct MetadataValue<std::optional<std::vector<uint8_t>>> {
+template <typename HEADER>
+struct MetadataValue<HEADER, std::optional<std::vector<uint8_t>>> {
[[nodiscard]] static int32_t encode(const std::optional<std::vector<uint8_t>>& value,
void* _Nullable destBuffer, size_t destBufferSize) {
if (!value.has_value()) {
return 0;
}
- return MetadataWriter{destBuffer, destBufferSize}.write(*value).desiredSize();
+ return MetadataWriter{destBuffer, destBufferSize}
+ .template writeHeader<HEADER>()
+ .write(*value)
+ .desiredSize();
}
using DecodeResult = std::optional<std::optional<std::vector<uint8_t>>>;
@@ -468,6 +510,7 @@
std::optional<std::vector<uint8_t>> optValue;
if (metadataSize > 0) {
MetadataReader reader{metadata, metadataSize};
+ reader.template checkHeader<HEADER>();
auto value = reader.readBuffer();
if (reader.ok()) {
optValue = std::move(value);
@@ -482,16 +525,20 @@
template <StandardMetadataType>
struct StandardMetadata {};
-#define DEFINE_TYPE(name, typeArg) \
- template <> \
- struct StandardMetadata<StandardMetadataType::name> { \
- using value_type = typeArg; \
- using value = MetadataValue<value_type>; \
- static_assert( \
- StandardMetadataType::name == \
- ndk::internal::enum_values<StandardMetadataType>[static_cast<size_t>( \
- StandardMetadataType::name)], \
- "StandardMetadataType must have equivalent value to index"); \
+#define DEFINE_TYPE(typeName, typeArg) \
+ template <> \
+ struct StandardMetadata<StandardMetadataType::typeName> { \
+ using value_type = typeArg; \
+ struct Header { \
+ static constexpr auto name = "android.hardware.graphics.common.StandardMetadataType"; \
+ static constexpr auto value = static_cast<int64_t>(StandardMetadataType::typeName); \
+ }; \
+ using value = MetadataValue<Header, value_type>; \
+ static_assert( \
+ StandardMetadataType::typeName == \
+ ndk::internal::enum_values<StandardMetadataType>[static_cast<size_t>( \
+ StandardMetadataType::typeName)], \
+ "StandardMetadataType must have equivalent value to index"); \
}
DEFINE_TYPE(BUFFER_ID, uint64_t);
diff --git a/graphics/mapper/stable-c/include/android/hardware/graphics/mapper/IMapper.h b/graphics/mapper/stable-c/include/android/hardware/graphics/mapper/IMapper.h
index f27b0f4..0f6d146 100644
--- a/graphics/mapper/stable-c/include/android/hardware/graphics/mapper/IMapper.h
+++ b/graphics/mapper/stable-c/include/android/hardware/graphics/mapper/IMapper.h
@@ -509,11 +509,12 @@
* particular Metadata field.
*
* The framework will attempt to set the following StandardMetadataType
- * values: DATASPACE, SMPTE2086, CTA861_3, SMPTE2094_40 and BLEND_MODE.
- * We require everyone to support setting those fields. If a device's Composer
- * implementation supports a field, it should be supported here. Over time these
- * metadata fields will be moved out of Composer/BufferQueue/etc. and into the
- * buffer's Metadata fields.
+ * values: DATASPACE, SMPTE2086, CTA861_3, and BLEND_MODE.
+ * We require everyone to support setting those fields. Framework will also attempt to set
+ * SMPTE2094_40 and SMPTE2094_10 if available, and it is required to support setting those
+ * if it is possible to get them. If a device's Composer implementation supports a field,
+ * it should be supported here. Over time these metadata fields will be moved out of
+ * Composer/BufferQueue/etc. and into the buffer's Metadata fields.
*
* @param buffer Buffer receiving desired metadata
* @param metadataType MetadataType for the metadata value being set
@@ -546,11 +547,12 @@
* particular Metadata field.
*
* The framework will attempt to set the following StandardMetadataType
- * values: DATASPACE, SMPTE2086, CTA861_3, SMPTE2094_40 and BLEND_MODE.
- * We require everyone to support setting those fields. If a device's Composer
- * implementation supports a field, it should be supported here. Over time these
- * metadata fields will be moved out of Composer/BufferQueue/etc. and into the
- * buffer's Metadata fields.
+ * values: DATASPACE, SMPTE2086, CTA861_3, and BLEND_MODE.
+ * We require everyone to support setting those fields. Framework will also attempt to set
+ * SMPTE2094_40 and SMPTE2094_10 if available, and it is required to support setting those
+ * if it is possible to get them. If a device's Composer implementation supports a field,
+ * it should be supported here. Over time these metadata fields will be moved out of
+ * Composer/BufferQueue/etc. and into the buffer's Metadata fields.
*
* @param buffer Buffer receiving desired metadata
* @param standardMetadataType StandardMetadataType for the metadata value being set
diff --git a/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp b/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
index 6ab11a3..85246ee 100644
--- a/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
+++ b/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
@@ -24,6 +24,7 @@
#include <aidl/android/hardware/graphics/common/BufferUsage.h>
#include <aidl/android/hardware/graphics/common/PixelFormat.h>
#include <aidlcommonsupport/NativeHandle.h>
+#include <android/binder_enums.h>
#include <android/binder_manager.h>
#include <android/dlext.h>
#include <android/hardware/graphics/mapper/IMapper.h>
@@ -66,6 +67,24 @@
int64_t verticalSubSampling;
};
+constexpr const char* STANDARD_METADATA_NAME =
+ "android.hardware.graphics.common.StandardMetadataType";
+
+static bool isStandardMetadata(AIMapper_MetadataType metadataType) {
+ return strcmp(STANDARD_METADATA_NAME, metadataType.name) == 0;
+}
+
+static std::string toString(const std::vector<StandardMetadataType> types) {
+ std::stringstream buf;
+ buf << "[";
+ for (auto type : types) {
+ buf << toString(type) << ", ";
+ }
+ buf.seekp(-2, buf.cur);
+ buf << "]";
+ return buf.str();
+}
+
class BufferHandle {
AIMapper* mIMapper;
buffer_handle_t mHandle = nullptr;
@@ -215,7 +234,7 @@
sizeRequired = mapper()->v5.getStandardMetadata(bufferHandle, static_cast<int64_t>(T),
buffer.data(), buffer.size());
}
- if (sizeRequired < 0 || sizeRequired >= buffer.size()) {
+ if (sizeRequired < 0 || sizeRequired > buffer.size()) {
ADD_FAILURE() << "getStandardMetadata failed, received " << sizeRequired
<< " with buffer size " << buffer.size();
// Generate a fail type
@@ -1533,8 +1552,187 @@
auto bufferHandle = buffer->import();
ASSERT_TRUE(bufferHandle);
auto value = getStandardMetadata<StandardMetadataType::SMPTE2094_40>(*bufferHandle);
- ASSERT_TRUE(value.has_value());
- EXPECT_FALSE(value->has_value());
+ if (value.has_value()) {
+ EXPECT_FALSE(value->has_value());
+ }
+}
+
+TEST_P(GraphicsMapperStableCTests, SupportsRequiredGettersSetters) {
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+ const AIMapper_MetadataTypeDescription* descriptions = nullptr;
+ size_t descriptionCount = 0;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE,
+ mapper()->v5.listSupportedMetadataTypes(&descriptions, &descriptionCount));
+ std::vector<StandardMetadataType> requiredGetters = {
+ StandardMetadataType::BUFFER_ID,
+ StandardMetadataType::NAME,
+ StandardMetadataType::WIDTH,
+ StandardMetadataType::HEIGHT,
+ StandardMetadataType::LAYER_COUNT,
+ StandardMetadataType::PIXEL_FORMAT_REQUESTED,
+ StandardMetadataType::PIXEL_FORMAT_FOURCC,
+ StandardMetadataType::PIXEL_FORMAT_MODIFIER,
+ StandardMetadataType::USAGE,
+ StandardMetadataType::ALLOCATION_SIZE,
+ StandardMetadataType::PROTECTED_CONTENT,
+ StandardMetadataType::COMPRESSION,
+ StandardMetadataType::INTERLACED,
+ StandardMetadataType::CHROMA_SITING,
+ StandardMetadataType::PLANE_LAYOUTS,
+ StandardMetadataType::CROP,
+ StandardMetadataType::DATASPACE,
+ StandardMetadataType::BLEND_MODE,
+ StandardMetadataType::SMPTE2086,
+ StandardMetadataType::CTA861_3,
+ };
+
+ std::vector<StandardMetadataType> requiredSetters = {
+ StandardMetadataType::DATASPACE,
+ StandardMetadataType::BLEND_MODE,
+ StandardMetadataType::SMPTE2086,
+ StandardMetadataType::CTA861_3,
+ };
+
+ for (int i = 0; i < descriptionCount; i++) {
+ const auto& it = descriptions[i];
+ if (isStandardMetadata(it.metadataType)) {
+ EXPECT_GT(it.metadataType.value, static_cast<int64_t>(StandardMetadataType::INVALID));
+ EXPECT_LT(it.metadataType.value,
+ ndk::internal::enum_values<StandardMetadataType>.size());
+
+ if (it.isGettable) {
+ std::erase(requiredGetters,
+ static_cast<StandardMetadataType>(it.metadataType.value));
+ }
+ if (it.isSettable) {
+ std::erase(requiredSetters,
+ static_cast<StandardMetadataType>(it.metadataType.value));
+ }
+ } else {
+ EXPECT_NE(nullptr, it.description) << "Non-standard metadata must have a description";
+ int len = strlen(it.description);
+ EXPECT_GE(len, 0) << "Non-standard metadata must have a description";
+ }
+ }
+
+ EXPECT_EQ(0, requiredGetters.size()) << "Missing required getters" << toString(requiredGetters);
+ EXPECT_EQ(0, requiredSetters.size()) << "Missing required setters" << toString(requiredSetters);
+}
+
+/*
+ * Test that verifies that if the optional StandardMetadataTypes have getters, they have
+ * the required setters as well
+ */
+TEST_P(GraphicsMapperStableCTests, CheckRequiredSettersIfHasGetters) {
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+ const AIMapper_MetadataTypeDescription* descriptions = nullptr;
+ size_t descriptionCount = 0;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE,
+ mapper()->v5.listSupportedMetadataTypes(&descriptions, &descriptionCount));
+
+ for (int i = 0; i < descriptionCount; i++) {
+ const auto& it = descriptions[i];
+ if (isStandardMetadata(it.metadataType)) {
+ const auto type = static_cast<StandardMetadataType>(it.metadataType.value);
+ switch (type) {
+ case StandardMetadataType::SMPTE2094_10:
+ case StandardMetadataType::SMPTE2094_40:
+ if (it.isGettable) {
+ EXPECT_TRUE(it.isSettable)
+ << "Type " << toString(type) << " must be settable if gettable";
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+TEST_P(GraphicsMapperStableCTests, ListSupportedWorks) {
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+ const AIMapper_MetadataTypeDescription* descriptions = nullptr;
+ size_t descriptionCount = 0;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE,
+ mapper()->v5.listSupportedMetadataTypes(&descriptions, &descriptionCount));
+
+ std::vector<uint8_t> metadataBuffer;
+ auto get = [&](AIMapper_MetadataType metadataType) -> int32_t {
+ int32_t size = mapper()->v5.getMetadata(*bufferHandle, metadataType, nullptr, 0);
+ if (size >= 0) {
+ metadataBuffer.resize(size);
+ size = mapper()->v5.getMetadata(*bufferHandle, metadataType, metadataBuffer.data(),
+ metadataBuffer.size());
+ EXPECT_EQ(size, metadataBuffer.size());
+ }
+ return size;
+ };
+
+ for (int i = 0; i < descriptionCount; i++) {
+ const auto& it = descriptions[i];
+ if (!isStandardMetadata(it.metadataType)) {
+ continue;
+ }
+ if (!it.isGettable) {
+ EXPECT_FALSE(it.isSettable)
+ << "StandardMetadata that isn't gettable must not be settable";
+ continue;
+ }
+ EXPECT_GE(get(it.metadataType), 0)
+ << "Get failed for claimed supported getter of "
+ << toString(static_cast<StandardMetadataType>(it.metadataType.value));
+ if (it.isSettable) {
+ EXPECT_EQ(AIMAPPER_ERROR_NONE,
+ mapper()->v5.setMetadata(*bufferHandle, it.metadataType,
+ metadataBuffer.data(), metadataBuffer.size()))
+ << "Failed to set metadata for "
+ << toString(static_cast<StandardMetadataType>(it.metadataType.value));
+ }
+ }
+}
+
+TEST_P(GraphicsMapperStableCTests, GetMetadataBadValue) {
+ auto get = [this](StandardMetadataType type) -> AIMapper_Error {
+ // This is a _Nonnull parameter, but this is enough obfuscation to fool the linter
+ buffer_handle_t buffer = nullptr;
+ int32_t ret =
+ mapper()->v5.getStandardMetadata(buffer, static_cast<int64_t>(type), nullptr, 0);
+ return (ret < 0) ? (AIMapper_Error)-ret : AIMAPPER_ERROR_NONE;
+ };
+
+ for (auto type : ndk::enum_range<StandardMetadataType>()) {
+ if (type == StandardMetadataType::INVALID) {
+ continue;
+ }
+ EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, get(type)) << "Wrong error for " << toString(type);
+ }
+}
+
+TEST_P(GraphicsMapperStableCTests, GetUnsupportedMetadata) {
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+
+ int result = mapper()->v5.getMetadata(*bufferHandle, {"Fake", 1}, nullptr, 0);
+ EXPECT_EQ(AIMAPPER_ERROR_UNSUPPORTED, -result);
+
+ result = mapper()->v5.getStandardMetadata(
+ *bufferHandle, static_cast<int64_t>(StandardMetadataType::INVALID), nullptr, 0);
+ EXPECT_EQ(AIMAPPER_ERROR_UNSUPPORTED, -result);
+
+ constexpr int64_t unknownStandardType = ndk::internal::enum_values<StandardMetadataType>.size();
+ result = mapper()->v5.getStandardMetadata(*bufferHandle, unknownStandardType, nullptr, 0);
+ EXPECT_EQ(AIMAPPER_ERROR_UNSUPPORTED, -result);
}
std::vector<std::tuple<std::string, std::shared_ptr<IAllocator>>> getIAllocatorsAtLeastVersion(
diff --git a/identity/support/Android.bp b/identity/support/Android.bp
index 4e3d1f7..3096fe5 100644
--- a/identity/support/Android.bp
+++ b/identity/support/Android.bp
@@ -65,57 +65,3 @@
],
test_suites: ["general-tests"],
}
-
-// --
-
-cc_library {
- name: "libcppbor",
- vendor_available: true,
- host_supported: true,
- srcs: [
- "src/cppbor.cpp",
- "src/cppbor_parse.cpp",
- ],
- export_include_dirs: [
- "include/cppbor",
- ],
- shared_libs: [
- "libbase",
- ],
-}
-
-cc_test {
- name: "cppbor_test",
- tidy_timeout_srcs: [
- "tests/cppbor_test.cpp",
- ],
- srcs: [
- "tests/cppbor_test.cpp",
- ],
- shared_libs: [
- "libcppbor_external",
- "libbase",
- ],
- static_libs: [
- "libgmock",
- ],
- test_suites: ["general-tests"],
-}
-
-cc_test_host {
- name: "cppbor_host_test",
- tidy_timeout_srcs: [
- "tests/cppbor_test.cpp",
- ],
- srcs: [
- "tests/cppbor_test.cpp",
- ],
- shared_libs: [
- "libcppbor_external",
- "libbase",
- ],
- static_libs: [
- "libgmock",
- ],
- test_suites: ["general-tests"],
-}
diff --git a/identity/support/include/cppbor/README.md b/identity/support/include/cppbor/README.md
deleted file mode 100644
index 723bfcf..0000000
--- a/identity/support/include/cppbor/README.md
+++ /dev/null
@@ -1,216 +0,0 @@
-CppBor: A Modern C++ CBOR Parser and Generator
-==============================================
-
-CppBor provides a natural and easy-to-use syntax for constructing and
-parsing CBOR messages. It does not (yet) support all features of
-CBOR, nor (yet) support validation against CDDL schemata, though both
-are planned. CBOR features that aren't supported include:
-
-* Indefinite length values
-* Semantic tagging
-* Floating point
-
-CppBor requires C++-17.
-
-## CBOR representation
-
-CppBor represents CBOR data items as instances of the `Item` class or,
-more precisely, as instances of subclasses of `Item`, since `Item` is a
-pure interface. The subclasses of `Item` correspond almost one-to-one
-with CBOR major types, and are named to match the CDDL names to which
-they correspond. They are:
-
-* `Uint` corresponds to major type 0, and can hold unsigned integers
- up through (2^64 - 1).
-* `Nint` corresponds to major type 1. It can only hold values from -1
- to -(2^63 - 1), since it's internal representation is an int64_t.
- This can be fixed, but it seems unlikely that applications will need
- the omitted range from -(2^63) to (2^64 - 1), since it's
- inconvenient to represent them in many programming languages.
-* `Int` is an abstract base of `Uint` and `Nint` that facilitates
- working with all signed integers representable with int64_t.
-* `Bstr` corresponds to major type 2, a byte string.
-* `Tstr` corresponds to major type 3, a text string.
-* `Array` corresponds to major type 4, an Array. It holds a
- variable-length array of `Item`s.
-* `Map` corresponds to major type 5, a Map. It holds a
- variable-length array of pairs of `Item`s.
-* `Simple` corresponds to major type 7. It's an abstract class since
- items require more specific type.
-* `Bool` is the only currently-implemented subclass of `Simple`.
-
-Note that major type 6, semantic tag, is not yet implemented.
-
-In practice, users of CppBor will rarely use most of these classes
-when generating CBOR encodings. This is because CppBor provides
-straightforward conversions from the obvious normal C++ types.
-Specifically, the following conversions are provided in appropriate
-contexts:
-
-* Signed and unsigned integers convert to `Uint` or `Nint`, as
- appropriate.
-* `std::string`, `std::string_view`, `const char*` and
- `std::pair<char iterator, char iterator>` convert to `Tstr`.
-* `std::vector<uint8_t>`, `std::pair<uint8_t iterator, uint8_t
- iterator>` and `std::pair<uint8_t*, size_t>` convert to `Bstr`.
-* `bool` converts to `Bool`.
-
-## CBOR generation
-
-### Complete tree generation
-
-The set of `encode` methods in `Item` provide the interface for
-producing encoded CBOR. The basic process for "complete tree"
-generation (as opposed to "incremental" generation, which is discussed
-below) is to construct an `Item` which models the data to be encoded,
-and then call one of the `encode` methods, whichever is convenient for
-the encoding destination. A trivial example:
-
-```
-cppbor::Uint val(0);
-std::vector<uint8_t> encoding = val.encode();
-```
-
- It's relatively rare that single values are encoded as above. More often, the
- "root" data item will be an `Array` or `Map` which contains a more complex structure.For example
- :
-
-``` using cppbor::Map;
-using cppbor::Array;
-
-std::vector<uint8_t> vec = // ...
- Map val("key1", Array(Map("key_a", 99 "key_b", vec), "foo"), "key2", true);
-std::vector<uint8_t> encoding = val.encode();
-```
-
-This creates a map with two entries, with `Tstr` keys "Outer1" and
-"Outer2", respectively. The "Outer1" entry has as its value an
-`Array` containing a `Map` and a `Tstr`. The "Outer2" entry has a
-`Bool` value.
-
-This example demonstrates how automatic conversion of C++ types to
-CppBor `Item` subclass instances is done. Where the caller provides a
-C++ or C string, a `Tstr` entry is added. Where the caller provides
-an integer literal or variable, a `Uint` or `Nint` is added, depending
-on whether the value is positive or negative.
-
-As an alternative, a more fluent-style API is provided for building up
-structures. For example:
-
-```
-using cppbor::Map;
-using cppbor::Array;
-
-std::vector<uint8_t> vec = // ...
- Map val();
-val.add("key1", Array().add(Map().add("key_a", 99).add("key_b", vec)).add("foo")).add("key2", true);
-std::vector<uint8_t> encoding = val.encode();
-```
-
- An advantage of this interface over the constructor -
- based creation approach above is that it need not be done all at once
- .The `add` methods return a reference to the object added to to allow calls to be chained,
- but chaining is not necessary; calls can be made
-sequentially, as the data to add is available.
-
-#### `encode` methods
-
-There are several variations of `Item::encode`, all of which
-accomplish the same task but output the encoded data in different
-ways, and with somewhat different performance characteristics. The
-provided options are:
-
-* `bool encode(uint8\_t** pos, const uint8\_t* end)` encodes into the
- buffer referenced by the range [`*pos`, end). `*pos` is moved. If
- the encoding runs out of buffer space before finishing, the method
- returns false. This is the most efficient way to encode, into an
- already-allocated buffer.
-* `void encode(EncodeCallback encodeCallback)` calls `encodeCallback`
- for each encoded byte. It's the responsibility of the implementor
- of the callback to behave safely in the event that the output buffer
- (if applicable) is exhausted. This is less efficient than the prior
- method because it imposes an additional function call for each byte.
-* `template </*...*/> void encode(OutputIterator i)`
- encodes into the provided iterator. SFINAE ensures that the
- template doesn't match for non-iterators. The implementation
- actually uses the callback-based method, plus has whatever overhead
- the iterator adds.
-* `std::vector<uint8_t> encode()` creates a new std::vector, reserves
- sufficient capacity to hold the encoding, and inserts the encoded
- bytes with a std::pushback_iterator and the previous method.
-* `std::string toString()` does the same as the previous method, but
- returns a string instead of a vector.
-
-### Incremental generation
-
-Incremental generation requires deeper understanding of CBOR, because
-the library can't do as much to ensure that the output is valid. The
-basic tool for intcremental generation is the `encodeHeader`
-function. There are two variations, one which writes into a buffer,
-and one which uses a callback. Both simply write out the bytes of a
-header. To construct the same map as in the above examples,
-incrementally, one might write:
-
-```
-using namespace cppbor; // For example brevity
-
-std::vector encoding;
-auto iter = std::back_inserter(result);
-encodeHeader(MAP, 2 /* # of map entries */, iter);
-std::string s = "key1";
-encodeHeader(TSTR, s.size(), iter);
-std::copy(s.begin(), s.end(), iter);
-encodeHeader(ARRAY, 2 /* # of array entries */, iter);
-Map().add("key_a", 99).add("key_b", vec).encode(iter)
-s = "foo";
-encodeHeader(TSTR, foo.size(), iter);
-std::copy(s.begin(), s.end(), iter);
-s = "key2";
-encodeHeader(TSTR, foo.size(), iter);
-std::copy(s.begin(), s.end(), iter);
-encodeHeader(SIMPLE, TRUE, iter);
-```
-
-As the above example demonstrates, the styles can be mixed -- Note the
-creation and encoding of the inner Map using the fluent style.
-
-## Parsing
-
-CppBor also supports parsing of encoded CBOR data, with the same
-feature set as encoding. There are two basic approaches to parsing,
-"full" and "stream"
-
-### Full parsing
-
-Full parsing means completely parsing a (possibly-compound) data
-item from a byte buffer. The `parse` functions that do not take a
-`ParseClient` pointer do this. They return a `ParseResult` which is a
-tuple of three values:
-
-* std::unique_ptr<Item> that points to the parsed item, or is nullptr
- if there was a parse error.
-* const uint8_t* that points to the byte after the end of the decoded
- item, or to the first unparseable byte in the event of an error.
-* std::string that is empty on success or contains an error message if
- a parse error occurred.
-
-Assuming a successful parse, you can then use `Item::type()` to
-discover the type of the parsed item (e.g. MAP), and then use the
-appropriate `Item::as*()` method (e.g. `Item::asMap()`) to get a
-pointer to an interface which allows you to retrieve specific values.
-
-### Stream parsing
-
-Stream parsing is more complex, but more flexible. To use
-StreamParsing, you must create your own subclass of `ParseClient` and
-call one of the `parse` functions that accepts it. See the
-`ParseClient` methods docstrings for details.
-
-One unusual feature of stream parsing is that the `ParseClient`
-callback methods not only provide the parsed Item, but also pointers
-to the portion of the buffer that encode that Item. This is useful
-if, for example, you want to find an element inside of a structure,
-and then copy the encoding of that sub-structure, without bothering to
-parse the rest.
-
-The full parser is implemented with the stream parser.
diff --git a/identity/support/include/cppbor/cppbor.h b/identity/support/include/cppbor/cppbor.h
deleted file mode 100644
index af5d82e..0000000
--- a/identity/support/include/cppbor/cppbor.h
+++ /dev/null
@@ -1,827 +0,0 @@
-/*
- * Copyright (c) 2019, 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 <cstdint>
-#include <functional>
-#include <iterator>
-#include <memory>
-#include <numeric>
-#include <string>
-#include <vector>
-
-namespace cppbor {
-
-enum MajorType : uint8_t {
- UINT = 0 << 5,
- NINT = 1 << 5,
- BSTR = 2 << 5,
- TSTR = 3 << 5,
- ARRAY = 4 << 5,
- MAP = 5 << 5,
- SEMANTIC = 6 << 5,
- SIMPLE = 7 << 5,
-};
-
-enum SimpleType {
- BOOLEAN,
- NULL_T, // Only two supported, as yet.
-};
-
-enum SpecialAddlInfoValues : uint8_t {
- FALSE = 20,
- TRUE = 21,
- NULL_V = 22,
- ONE_BYTE_LENGTH = 24,
- TWO_BYTE_LENGTH = 25,
- FOUR_BYTE_LENGTH = 26,
- EIGHT_BYTE_LENGTH = 27,
-};
-
-class Item;
-class Uint;
-class Nint;
-class Int;
-class Tstr;
-class Bstr;
-class Simple;
-class Bool;
-class Array;
-class Map;
-class Null;
-class Semantic;
-
-/**
- * Returns the size of a CBOR header that contains the additional info value addlInfo.
- */
-size_t headerSize(uint64_t addlInfo);
-
-/**
- * Encodes a CBOR header with the specified type and additional info into the range [pos, end).
- * Returns a pointer to one past the last byte written, or nullptr if there isn't sufficient space
- * to write the header.
- */
-uint8_t* encodeHeader(MajorType type, uint64_t addlInfo, uint8_t* pos, const uint8_t* end);
-
-using EncodeCallback = std::function<void(uint8_t)>;
-
-/**
- * Encodes a CBOR header with the specified type and additional info, passing each byte in turn to
- * encodeCallback.
- */
-void encodeHeader(MajorType type, uint64_t addlInfo, EncodeCallback encodeCallback);
-
-/**
- * Encodes a CBOR header with the specified type and additional info, writing each byte to the
- * provided OutputIterator.
- */
-template <typename OutputIterator,
- typename = std::enable_if_t<std::is_base_of_v<
- std::output_iterator_tag,
- typename std::iterator_traits<OutputIterator>::iterator_category>>>
-void encodeHeader(MajorType type, uint64_t addlInfo, OutputIterator iter) {
- return encodeHeader(type, addlInfo, [&](uint8_t v) { *iter++ = v; });
-}
-
-/**
- * Item represents a CBOR-encodeable data item. Item is an abstract interface with a set of virtual
- * methods that allow encoding of the item or conversion to the appropriate derived type.
- */
-class Item {
- public:
- virtual ~Item() {}
-
- /**
- * Returns the CBOR type of the item.
- */
- virtual MajorType type() const = 0;
-
- // These methods safely downcast an Item to the appropriate subclass.
- virtual const Int* asInt() const { return nullptr; }
- virtual const Uint* asUint() const { return nullptr; }
- virtual const Nint* asNint() const { return nullptr; }
- virtual const Tstr* asTstr() const { return nullptr; }
- virtual const Bstr* asBstr() const { return nullptr; }
- virtual const Simple* asSimple() const { return nullptr; }
- virtual const Map* asMap() const { return nullptr; }
- virtual const Array* asArray() const { return nullptr; }
- virtual const Semantic* asSemantic() const { return nullptr; }
-
- /**
- * Returns true if this is a "compound" item, i.e. one that contains one or more other items.
- */
- virtual bool isCompound() const { return false; }
-
- bool operator==(const Item& other) const&;
- bool operator!=(const Item& other) const& { return !(*this == other); }
-
- /**
- * Returns the number of bytes required to encode this Item into CBOR. Note that if this is a
- * complex Item, calling this method will require walking the whole tree.
- */
- virtual size_t encodedSize() const = 0;
-
- /**
- * Encodes the Item into buffer referenced by range [*pos, end). Returns a pointer to one past
- * the last position written. Returns nullptr if there isn't enough space to encode.
- */
- virtual uint8_t* encode(uint8_t* pos, const uint8_t* end) const = 0;
-
- /**
- * Encodes the Item by passing each encoded byte to encodeCallback.
- */
- virtual void encode(EncodeCallback encodeCallback) const = 0;
-
- /**
- * Clones the Item
- */
- virtual std::unique_ptr<Item> clone() const = 0;
-
- /**
- * Encodes the Item into the provided OutputIterator.
- */
- template <typename OutputIterator,
- typename = typename std::iterator_traits<OutputIterator>::iterator_category>
- void encode(OutputIterator i) const {
- return encode([&](uint8_t v) { *i++ = v; });
- }
-
- /**
- * Encodes the Item into a new std::vector<uint8_t>.
- */
- std::vector<uint8_t> encode() const {
- std::vector<uint8_t> retval;
- retval.reserve(encodedSize());
- encode(std::back_inserter(retval));
- return retval;
- }
-
- /**
- * Encodes the Item into a new std::string.
- */
- std::string toString() const {
- std::string retval;
- retval.reserve(encodedSize());
- encode([&](uint8_t v) { retval.push_back(v); });
- return retval;
- }
-
- /**
- * Encodes only the header of the Item.
- */
- inline uint8_t* encodeHeader(uint64_t addlInfo, uint8_t* pos, const uint8_t* end) const {
- return ::cppbor::encodeHeader(type(), addlInfo, pos, end);
- }
-
- /**
- * Encodes only the header of the Item.
- */
- inline void encodeHeader(uint64_t addlInfo, EncodeCallback encodeCallback) const {
- ::cppbor::encodeHeader(type(), addlInfo, encodeCallback);
- }
-};
-
-/**
- * Int is an abstraction that allows Uint and Nint objects to be manipulated without caring about
- * the sign.
- */
-class Int : public Item {
- public:
- bool operator==(const Int& other) const& { return value() == other.value(); }
-
- virtual int64_t value() const = 0;
-
- const Int* asInt() const override { return this; }
-};
-
-/**
- * Uint is a concrete Item that implements CBOR major type 0.
- */
-class Uint : public Int {
- public:
- static constexpr MajorType kMajorType = UINT;
-
- explicit Uint(uint64_t v) : mValue(v) {}
-
- bool operator==(const Uint& other) const& { return mValue == other.mValue; }
-
- MajorType type() const override { return kMajorType; }
- const Uint* asUint() const override { return this; }
-
- size_t encodedSize() const override { return headerSize(mValue); }
-
- int64_t value() const override { return mValue; }
- uint64_t unsignedValue() const { return mValue; }
-
- using Item::encode;
- uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
- return encodeHeader(mValue, pos, end);
- }
- void encode(EncodeCallback encodeCallback) const override {
- encodeHeader(mValue, encodeCallback);
- }
-
- virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Uint>(mValue); }
-
- private:
- uint64_t mValue;
-};
-
-/**
- * Nint is a concrete Item that implements CBOR major type 1.
-
- * Note that it is incapable of expressing the full range of major type 1 values, becaue it can only
- * express values that fall into the range [std::numeric_limits<int64_t>::min(), -1]. It cannot
- * express values in the range [std::numeric_limits<int64_t>::min() - 1,
- * -std::numeric_limits<uint64_t>::max()].
- */
-class Nint : public Int {
- public:
- static constexpr MajorType kMajorType = NINT;
-
- explicit Nint(int64_t v);
-
- bool operator==(const Nint& other) const& { return mValue == other.mValue; }
-
- MajorType type() const override { return kMajorType; }
- const Nint* asNint() const override { return this; }
- size_t encodedSize() const override { return headerSize(addlInfo()); }
-
- int64_t value() const override { return mValue; }
-
- using Item::encode;
- uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
- return encodeHeader(addlInfo(), pos, end);
- }
- void encode(EncodeCallback encodeCallback) const override {
- encodeHeader(addlInfo(), encodeCallback);
- }
-
- virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Nint>(mValue); }
-
- private:
- uint64_t addlInfo() const { return -1LL - mValue; }
-
- int64_t mValue;
-};
-
-/**
- * Bstr is a concrete Item that implements major type 2.
- */
-class Bstr : public Item {
- public:
- static constexpr MajorType kMajorType = BSTR;
-
- // Construct from a vector
- explicit Bstr(std::vector<uint8_t> v) : mValue(std::move(v)) {}
-
- // Construct from a string
- explicit Bstr(const std::string& v)
- : mValue(reinterpret_cast<const uint8_t*>(v.data()),
- reinterpret_cast<const uint8_t*>(v.data()) + v.size()) {}
-
- // Construct from a pointer/size pair
- explicit Bstr(const std::pair<const uint8_t*, size_t>& buf)
- : mValue(buf.first, buf.first + buf.second) {}
-
- // Construct from a pair of iterators
- template <typename I1, typename I2,
- typename = typename std::iterator_traits<I1>::iterator_category,
- typename = typename std::iterator_traits<I2>::iterator_category>
- explicit Bstr(const std::pair<I1, I2>& pair) : mValue(pair.first, pair.second) {}
-
- // Construct from an iterator range.
- template <typename I1, typename I2,
- typename = typename std::iterator_traits<I1>::iterator_category,
- typename = typename std::iterator_traits<I2>::iterator_category>
- Bstr(I1 begin, I2 end) : mValue(begin, end) {}
-
- bool operator==(const Bstr& other) const& { return mValue == other.mValue; }
-
- MajorType type() const override { return kMajorType; }
- const Bstr* asBstr() const override { return this; }
- size_t encodedSize() const override { return headerSize(mValue.size()) + mValue.size(); }
- using Item::encode;
- uint8_t* encode(uint8_t* pos, const uint8_t* end) const override;
- void encode(EncodeCallback encodeCallback) const override {
- encodeHeader(mValue.size(), encodeCallback);
- encodeValue(encodeCallback);
- }
-
- const std::vector<uint8_t>& value() const { return mValue; }
-
- virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Bstr>(mValue); }
-
- private:
- void encodeValue(EncodeCallback encodeCallback) const;
-
- std::vector<uint8_t> mValue;
-};
-
-/**
- * Bstr is a concrete Item that implements major type 3.
- */
-class Tstr : public Item {
- public:
- static constexpr MajorType kMajorType = TSTR;
-
- // Construct from a string
- explicit Tstr(std::string v) : mValue(std::move(v)) {}
-
- // Construct from a string_view
- explicit Tstr(const std::string_view& v) : mValue(v) {}
-
- // Construct from a C string
- explicit Tstr(const char* v) : mValue(std::string(v)) {}
-
- // Construct from a pair of iterators
- template <typename I1, typename I2,
- typename = typename std::iterator_traits<I1>::iterator_category,
- typename = typename std::iterator_traits<I2>::iterator_category>
- explicit Tstr(const std::pair<I1, I2>& pair) : mValue(pair.first, pair.second) {}
-
- // Construct from an iterator range
- template <typename I1, typename I2,
- typename = typename std::iterator_traits<I1>::iterator_category,
- typename = typename std::iterator_traits<I2>::iterator_category>
- Tstr(I1 begin, I2 end) : mValue(begin, end) {}
-
- bool operator==(const Tstr& other) const& { return mValue == other.mValue; }
-
- MajorType type() const override { return kMajorType; }
- const Tstr* asTstr() const override { return this; }
- size_t encodedSize() const override { return headerSize(mValue.size()) + mValue.size(); }
- using Item::encode;
- uint8_t* encode(uint8_t* pos, const uint8_t* end) const override;
- void encode(EncodeCallback encodeCallback) const override {
- encodeHeader(mValue.size(), encodeCallback);
- encodeValue(encodeCallback);
- }
-
- const std::string& value() const { return mValue; }
-
- virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Tstr>(mValue); }
-
- private:
- void encodeValue(EncodeCallback encodeCallback) const;
-
- std::string mValue;
-};
-
-/**
- * CompoundItem is an abstract Item that provides common functionality for Items that contain other
- * items, i.e. Arrays (CBOR type 4) and Maps (CBOR type 5).
- */
-class CompoundItem : public Item {
- public:
- bool operator==(const CompoundItem& other) const&;
-
- virtual size_t size() const { return mEntries.size(); }
-
- bool isCompound() const override { return true; }
-
- size_t encodedSize() const override {
- return std::accumulate(mEntries.begin(), mEntries.end(), headerSize(size()),
- [](size_t sum, auto& entry) { return sum + entry->encodedSize(); });
- }
-
- using Item::encode; // Make base versions visible.
- uint8_t* encode(uint8_t* pos, const uint8_t* end) const override;
- void encode(EncodeCallback encodeCallback) const override;
-
- virtual uint64_t addlInfo() const = 0;
-
- protected:
- std::vector<std::unique_ptr<Item>> mEntries;
-};
-
-/*
- * Array is a concrete Item that implements CBOR major type 4.
- *
- * Note that Arrays are not copyable. This is because copying them is expensive and making them
- * move-only ensures that they're never copied accidentally. If you actually want to copy an Array,
- * use the clone() method.
- */
-class Array : public CompoundItem {
- public:
- static constexpr MajorType kMajorType = ARRAY;
-
- Array() = default;
- Array(const Array& other) = delete;
- Array(Array&&) = default;
- Array& operator=(const Array&) = delete;
- Array& operator=(Array&&) = default;
-
- /**
- * Construct an Array from a variable number of arguments of different types. See
- * details::makeItem below for details on what types may be provided. In general, this accepts
- * all of the types you'd expect and doest the things you'd expect (integral values are addes as
- * Uint or Nint, std::string and char* are added as Tstr, bools are added as Bool, etc.).
- */
- template <typename... Args, typename Enable>
- Array(Args&&... args);
-
- /**
- * Append a single element to the Array, of any compatible type.
- */
- template <typename T>
- Array& add(T&& v) &;
- template <typename T>
- Array&& add(T&& v) &&;
-
- const std::unique_ptr<Item>& operator[](size_t index) const { return mEntries[index]; }
- std::unique_ptr<Item>& operator[](size_t index) { return mEntries[index]; }
-
- MajorType type() const override { return kMajorType; }
- const Array* asArray() const override { return this; }
-
- virtual std::unique_ptr<Item> clone() const override;
-
- uint64_t addlInfo() const override { return size(); }
-};
-
-/*
- * Map is a concrete Item that implements CBOR major type 5.
- *
- * Note that Maps are not copyable. This is because copying them is expensive and making them
- * move-only ensures that they're never copied accidentally. If you actually want to copy a
- * Map, use the clone() method.
- */
-class Map : public CompoundItem {
- public:
- static constexpr MajorType kMajorType = MAP;
-
- Map() = default;
- Map(const Map& other) = delete;
- Map(Map&&) = default;
- Map& operator=(const Map& other) = delete;
- Map& operator=(Map&&) = default;
-
- /**
- * Construct a Map from a variable number of arguments of different types. An even number of
- * arguments must be provided (this is verified statically). See details::makeItem below for
- * details on what types may be provided. In general, this accepts all of the types you'd
- * expect and doest the things you'd expect (integral values are addes as Uint or Nint,
- * std::string and char* are added as Tstr, bools are added as Bool, etc.).
- */
- template <typename... Args, typename Enable>
- Map(Args&&... args);
-
- /**
- * Append a key/value pair to the Map, of any compatible types.
- */
- template <typename Key, typename Value>
- Map& add(Key&& key, Value&& value) &;
- template <typename Key, typename Value>
- Map&& add(Key&& key, Value&& value) &&;
-
- size_t size() const override {
- assertInvariant();
- return mEntries.size() / 2;
- }
-
- template <typename Key, typename Enable>
- std::pair<std::unique_ptr<Item>&, bool> get(Key key);
-
- std::pair<const std::unique_ptr<Item>&, const std::unique_ptr<Item>&> operator[](
- size_t index) const {
- assertInvariant();
- return {mEntries[index * 2], mEntries[index * 2 + 1]};
- }
-
- std::pair<std::unique_ptr<Item>&, std::unique_ptr<Item>&> operator[](size_t index) {
- assertInvariant();
- return {mEntries[index * 2], mEntries[index * 2 + 1]};
- }
-
- MajorType type() const override { return kMajorType; }
- const Map* asMap() const override { return this; }
-
- virtual std::unique_ptr<Item> clone() const override;
-
- uint64_t addlInfo() const override { return size(); }
-
- private:
- void assertInvariant() const;
-};
-
-class Semantic : public CompoundItem {
- public:
- static constexpr MajorType kMajorType = SEMANTIC;
-
- template <typename T>
- explicit Semantic(uint64_t value, T&& child);
-
- Semantic(const Semantic& other) = delete;
- Semantic(Semantic&&) = default;
- Semantic& operator=(const Semantic& other) = delete;
- Semantic& operator=(Semantic&&) = default;
-
- size_t size() const override {
- assertInvariant();
- return 1;
- }
-
- size_t encodedSize() const override {
- return std::accumulate(mEntries.begin(), mEntries.end(), headerSize(mValue),
- [](size_t sum, auto& entry) { return sum + entry->encodedSize(); });
- }
-
- MajorType type() const override { return kMajorType; }
- const Semantic* asSemantic() const override { return this; }
-
- const std::unique_ptr<Item>& child() const {
- assertInvariant();
- return mEntries[0];
- }
-
- std::unique_ptr<Item>& child() {
- assertInvariant();
- return mEntries[0];
- }
-
- uint64_t value() const { return mValue; }
-
- uint64_t addlInfo() const override { return value(); }
-
- virtual std::unique_ptr<Item> clone() const override {
- assertInvariant();
- return std::make_unique<Semantic>(mValue, mEntries[0]->clone());
- }
-
- protected:
- Semantic() = default;
- Semantic(uint64_t value) : mValue(value) {}
- uint64_t mValue;
-
- private:
- void assertInvariant() const;
-};
-
-/**
- * Simple is abstract Item that implements CBOR major type 7. It is intended to be subclassed to
- * create concrete Simple types. At present only Bool is provided.
- */
-class Simple : public Item {
- public:
- static constexpr MajorType kMajorType = SIMPLE;
-
- bool operator==(const Simple& other) const&;
-
- virtual SimpleType simpleType() const = 0;
- MajorType type() const override { return kMajorType; }
-
- const Simple* asSimple() const override { return this; }
-
- virtual const Bool* asBool() const { return nullptr; };
- virtual const Null* asNull() const { return nullptr; };
-};
-
-/**
- * Bool is a concrete type that implements CBOR major type 7, with additional item values for TRUE
- * and FALSE.
- */
-class Bool : public Simple {
- public:
- static constexpr SimpleType kSimpleType = BOOLEAN;
-
- explicit Bool(bool v) : mValue(v) {}
-
- bool operator==(const Bool& other) const& { return mValue == other.mValue; }
-
- SimpleType simpleType() const override { return kSimpleType; }
- const Bool* asBool() const override { return this; }
-
- size_t encodedSize() const override { return 1; }
-
- using Item::encode;
- uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
- return encodeHeader(mValue ? TRUE : FALSE, pos, end);
- }
- void encode(EncodeCallback encodeCallback) const override {
- encodeHeader(mValue ? TRUE : FALSE, encodeCallback);
- }
-
- bool value() const { return mValue; }
-
- virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Bool>(mValue); }
-
- private:
- bool mValue;
-};
-
-/**
- * Null is a concrete type that implements CBOR major type 7, with additional item value for NULL
- */
-class Null : public Simple {
- public:
- static constexpr SimpleType kSimpleType = NULL_T;
-
- explicit Null() {}
-
- SimpleType simpleType() const override { return kSimpleType; }
- const Null* asNull() const override { return this; }
-
- size_t encodedSize() const override { return 1; }
-
- using Item::encode;
- uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
- return encodeHeader(NULL_V, pos, end);
- }
- void encode(EncodeCallback encodeCallback) const override {
- encodeHeader(NULL_V, encodeCallback);
- }
-
- virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Null>(); }
-};
-
-template <typename T>
-std::unique_ptr<T> downcastItem(std::unique_ptr<Item>&& v) {
- static_assert(std::is_base_of_v<Item, T> && !std::is_abstract_v<T>,
- "returned type is not an Item or is an abstract class");
- if (v && T::kMajorType == v->type()) {
- if constexpr (std::is_base_of_v<Simple, T>) {
- if (T::kSimpleType != v->asSimple()->simpleType()) {
- return nullptr;
- }
- }
- return std::unique_ptr<T>(static_cast<T*>(v.release()));
- } else {
- return nullptr;
- }
-}
-
-/**
- * Details. Mostly you shouldn't have to look below, except perhaps at the docstring for makeItem.
- */
-namespace details {
-
-template <typename T, typename V, typename Enable = void>
-struct is_iterator_pair_over : public std::false_type {};
-
-template <typename I1, typename I2, typename V>
-struct is_iterator_pair_over<
- std::pair<I1, I2>, V,
- typename std::enable_if_t<std::is_same_v<V, typename std::iterator_traits<I1>::value_type>>>
- : public std::true_type {};
-
-template <typename T, typename V, typename Enable = void>
-struct is_unique_ptr_of_subclass_of_v : public std::false_type {};
-
-template <typename T, typename P>
-struct is_unique_ptr_of_subclass_of_v<T, std::unique_ptr<P>,
- typename std::enable_if_t<std::is_base_of_v<T, P>>>
- : public std::true_type {};
-
-/* check if type is one of std::string (1), std::string_view (2), null-terminated char* (3) or pair
- * of iterators (4)*/
-template <typename T, typename Enable = void>
-struct is_text_type_v : public std::false_type {};
-
-template <typename T>
-struct is_text_type_v<
- T, typename std::enable_if_t<
- /* case 1 */ //
- std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, std::string>
- /* case 2 */ //
- || std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, std::string_view>
- /* case 3 */ //
- || std::is_same_v<std::remove_cv_t<std::decay_t<T>>, char*> //
- || std::is_same_v<std::remove_cv_t<std::decay_t<T>>, const char*>
- /* case 4 */
- || details::is_iterator_pair_over<T, char>::value>> : public std::true_type {};
-
-/**
- * Construct a unique_ptr<Item> from many argument types. Accepts:
- *
- * (a) booleans;
- * (b) integers, all sizes and signs;
- * (c) text strings, as defined by is_text_type_v above;
- * (d) byte strings, as std::vector<uint8_t>(d1), pair of iterators (d2) or pair<uint8_t*, size_T>
- * (d3); and
- * (e) Item subclass instances, including Array and Map. Items may be provided by naked pointer
- * (e1), unique_ptr (e2), reference (e3) or value (e3). If provided by reference or value, will
- * be moved if possible. If provided by pointer, ownership is taken.
- * (f) null pointer;
- */
-template <typename T>
-std::unique_ptr<Item> makeItem(T v) {
- Item* p = nullptr;
- if constexpr (/* case a */ std::is_same_v<T, bool>) {
- p = new Bool(v);
- } else if constexpr (/* case b */ std::is_integral_v<T>) { // b
- if (v < 0) {
- p = new Nint(v);
- } else {
- p = new Uint(static_cast<uint64_t>(v));
- }
- } else if constexpr (/* case c */ //
- details::is_text_type_v<T>::value) {
- p = new Tstr(v);
- } else if constexpr (/* case d1 */ //
- std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>,
- std::vector<uint8_t>>
- /* case d2 */ //
- || details::is_iterator_pair_over<T, uint8_t>::value
- /* case d3 */ //
- || std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>,
- std::pair<uint8_t*, size_t>>) {
- p = new Bstr(v);
- } else if constexpr (/* case e1 */ //
- std::is_pointer_v<T> &&
- std::is_base_of_v<Item, std::remove_pointer_t<T>>) {
- p = v;
- } else if constexpr (/* case e2 */ //
- details::is_unique_ptr_of_subclass_of_v<Item, T>::value) {
- p = v.release();
- } else if constexpr (/* case e3 */ //
- std::is_base_of_v<Item, T>) {
- p = new T(std::move(v));
- } else if constexpr (/* case f */ std::is_null_pointer_v<T>) {
- p = new Null();
- } else {
- // It's odd that this can't be static_assert(false), since it shouldn't be evaluated if one
- // of the above ifs matches. But static_assert(false) always triggers.
- static_assert(std::is_same_v<T, bool>, "makeItem called with unsupported type");
- }
- return std::unique_ptr<Item>(p);
-}
-
-} // namespace details
-
-template <typename... Args,
- /* Prevent use as copy ctor */ typename = std::enable_if_t<
- (sizeof...(Args)) != 1 ||
- !(std::is_same_v<Array, std::remove_cv_t<std::remove_reference_t<Args>>> || ...)>>
-Array::Array(Args&&... args) {
- mEntries.reserve(sizeof...(args));
- (mEntries.push_back(details::makeItem(std::forward<Args>(args))), ...);
-}
-
-template <typename T>
-Array& Array::add(T&& v) & {
- mEntries.push_back(details::makeItem(std::forward<T>(v)));
- return *this;
-}
-
-template <typename T>
-Array&& Array::add(T&& v) && {
- mEntries.push_back(details::makeItem(std::forward<T>(v)));
- return std::move(*this);
-}
-
-template <typename... Args,
- /* Prevent use as copy ctor */ typename = std::enable_if_t<(sizeof...(Args)) != 1>>
-Map::Map(Args&&... args) {
- static_assert((sizeof...(Args)) % 2 == 0, "Map must have an even number of entries");
- mEntries.reserve(sizeof...(args));
- (mEntries.push_back(details::makeItem(std::forward<Args>(args))), ...);
-}
-
-template <typename Key, typename Value>
-Map& Map::add(Key&& key, Value&& value) & {
- mEntries.push_back(details::makeItem(std::forward<Key>(key)));
- mEntries.push_back(details::makeItem(std::forward<Value>(value)));
- return *this;
-}
-
-template <typename Key, typename Value>
-Map&& Map::add(Key&& key, Value&& value) && {
- this->add(std::forward<Key>(key), std::forward<Value>(value));
- return std::move(*this);
-}
-
-template <typename Key, typename = std::enable_if_t<std::is_integral_v<Key> ||
- details::is_text_type_v<Key>::value>>
-std::pair<std::unique_ptr<Item>&, bool> Map::get(Key key) {
- assertInvariant();
- auto keyItem = details::makeItem(key);
- for (size_t i = 0; i < mEntries.size(); i += 2) {
- if (*keyItem == *mEntries[i]) {
- return {mEntries[i + 1], true};
- }
- }
- return {keyItem, false};
-}
-
-template <typename T>
-Semantic::Semantic(uint64_t value, T&& child) : mValue(value) {
- mEntries.reserve(1);
- mEntries.push_back(details::makeItem(std::forward<T>(child)));
-}
-
-} // namespace cppbor
diff --git a/identity/support/include/cppbor/cppbor_parse.h b/identity/support/include/cppbor/cppbor_parse.h
deleted file mode 100644
index 66cd5a3..0000000
--- a/identity/support/include/cppbor/cppbor_parse.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2019, 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 "cppbor.h"
-
-namespace cppbor {
-
-using ParseResult = std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
- std::string /* errMsg */>;
-
-/**
- * Parse the first CBOR data item (possibly compound) from the range [begin, end).
- *
- * Returns a tuple of Item pointer, buffer pointer and error message. If parsing is successful, the
- * Item pointer is non-null, the buffer pointer points to the first byte after the
- * successfully-parsed item and the error message string is empty. If parsing fails, the Item
- * pointer is null, the buffer pointer points to the first byte that was unparseable (the first byte
- * of a data item header that is malformed in some way, e.g. an invalid value, or a length that is
- * too large for the remining buffer, etc.) and the string contains an error message describing the
- * problem encountered.
- */
-ParseResult parse(const uint8_t* begin, const uint8_t* end);
-
-/**
- * Parse the first CBOR data item (possibly compound) from the byte vector.
- *
- * Returns a tuple of Item pointer, buffer pointer and error message. If parsing is successful, the
- * Item pointer is non-null, the buffer pointer points to the first byte after the
- * successfully-parsed item and the error message string is empty. If parsing fails, the Item
- * pointer is null, the buffer pointer points to the first byte that was unparseable (the first byte
- * of a data item header that is malformed in some way, e.g. an invalid value, or a length that is
- * too large for the remining buffer, etc.) and the string contains an error message describing the
- * problem encountered.
- */
-inline ParseResult parse(const std::vector<uint8_t>& encoding) {
- return parse(encoding.data(), encoding.data() + encoding.size());
-}
-
-/**
- * Parse the first CBOR data item (possibly compound) from the range [begin, begin + size).
- *
- * Returns a tuple of Item pointer, buffer pointer and error message. If parsing is successful, the
- * Item pointer is non-null, the buffer pointer points to the first byte after the
- * successfully-parsed item and the error message string is empty. If parsing fails, the Item
- * pointer is null, the buffer pointer points to the first byte that was unparseable (the first byte
- * of a data item header that is malformed in some way, e.g. an invalid value, or a length that is
- * too large for the remining buffer, etc.) and the string contains an error message describing the
- * problem encountered.
- */
-inline ParseResult parse(const uint8_t* begin, size_t size) {
- return parse(begin, begin + size);
-}
-
-class ParseClient;
-
-/**
- * Parse the CBOR data in the range [begin, end) in streaming fashion, calling methods on the
- * provided ParseClient when elements are found.
- */
-void parse(const uint8_t* begin, const uint8_t* end, ParseClient* parseClient);
-
-/**
- * Parse the CBOR data in the vector in streaming fashion, calling methods on the
- * provided ParseClient when elements are found.
- */
-inline void parse(const std::vector<uint8_t>& encoding, ParseClient* parseClient) {
- return parse(encoding.data(), encoding.data() + encoding.size(), parseClient);
-}
-
-/**
- * A pure interface that callers of the streaming parse functions must implement.
- */
-class ParseClient {
- public:
- virtual ~ParseClient() {}
-
- /**
- * Called when an item is found. The Item pointer points to the found item; use type() and
- * the appropriate as*() method to examine the value. hdrBegin points to the first byte of the
- * header, valueBegin points to the first byte of the value and end points one past the end of
- * the item. In the case of header-only items, such as integers, and compound items (ARRAY,
- * MAP or SEMANTIC) whose end has not yet been found, valueBegin and end are equal and point to
- * the byte past the header.
- *
- * Note that for compound types (ARRAY, MAP, and SEMANTIC), the Item will have no content. For
- * Map and Array items, the size() method will return a correct value, but the index operators
- * are unsafe, and the object cannot be safely compared with another Array/Map.
- *
- * The method returns a ParseClient*. In most cases "return this;" will be the right answer,
- * but a different ParseClient may be returned, which the parser will begin using. If the method
- * returns nullptr, parsing will be aborted immediately.
- */
- virtual ParseClient* item(std::unique_ptr<Item>& item, const uint8_t* hdrBegin,
- const uint8_t* valueBegin, const uint8_t* end) = 0;
-
- /**
- * Called when the end of a compound item (MAP or ARRAY) is found. The item argument will be
- * the same one passed to the item() call -- and may be empty if item() moved its value out.
- * hdrBegin, valueBegin and end point to the beginning of the item header, the beginning of the
- * first contained value, and one past the end of the last contained value, respectively.
- *
- * Note that the Item will have no content.
- *
- * As with item(), itemEnd() can change the ParseClient by returning a different one, or end the
- * parsing by returning nullptr;
- */
- virtual ParseClient* itemEnd(std::unique_ptr<Item>& item, const uint8_t* hdrBegin,
- const uint8_t* valueBegin, const uint8_t* end) = 0;
-
- /**
- * Called when parsing encounters an error. position is set to the first unparsed byte (one
- * past the last successfully-parsed byte) and errorMessage contains an message explaining what
- * sort of error occurred.
- */
- virtual void error(const uint8_t* position, const std::string& errorMessage) = 0;
-};
-
-} // namespace cppbor
diff --git a/identity/support/src/cppbor.cpp b/identity/support/src/cppbor.cpp
deleted file mode 100644
index d289985..0000000
--- a/identity/support/src/cppbor.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (c) 2019, 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 "cppbor.h"
-#include "cppbor_parse.h"
-
-#define LOG_TAG "CppBor"
-#include <android-base/logging.h>
-
-namespace cppbor {
-
-namespace {
-
-template <typename T, typename Iterator, typename = std::enable_if<std::is_unsigned<T>::value>>
-Iterator writeBigEndian(T value, Iterator pos) {
- for (unsigned i = 0; i < sizeof(value); ++i) {
- *pos++ = static_cast<uint8_t>(value >> (8 * (sizeof(value) - 1)));
- value = static_cast<T>(value << 8);
- }
- return pos;
-}
-
-template <typename T, typename = std::enable_if<std::is_unsigned<T>::value>>
-void writeBigEndian(T value, std::function<void(uint8_t)>& cb) {
- for (unsigned i = 0; i < sizeof(value); ++i) {
- cb(static_cast<uint8_t>(value >> (8 * (sizeof(value) - 1))));
- value = static_cast<T>(value << 8);
- }
-}
-
-} // namespace
-
-size_t headerSize(uint64_t addlInfo) {
- if (addlInfo < ONE_BYTE_LENGTH) return 1;
- if (addlInfo <= std::numeric_limits<uint8_t>::max()) return 2;
- if (addlInfo <= std::numeric_limits<uint16_t>::max()) return 3;
- if (addlInfo <= std::numeric_limits<uint32_t>::max()) return 5;
- return 9;
-}
-
-uint8_t* encodeHeader(MajorType type, uint64_t addlInfo, uint8_t* pos, const uint8_t* end) {
- size_t sz = headerSize(addlInfo);
- if (end - pos < static_cast<ssize_t>(sz)) return nullptr;
- switch (sz) {
- case 1:
- *pos++ = type | static_cast<uint8_t>(addlInfo);
- return pos;
- case 2:
- *pos++ = type | ONE_BYTE_LENGTH;
- *pos++ = static_cast<uint8_t>(addlInfo);
- return pos;
- case 3:
- *pos++ = type | TWO_BYTE_LENGTH;
- return writeBigEndian(static_cast<uint16_t>(addlInfo), pos);
- case 5:
- *pos++ = type | FOUR_BYTE_LENGTH;
- return writeBigEndian(static_cast<uint32_t>(addlInfo), pos);
- case 9:
- *pos++ = type | EIGHT_BYTE_LENGTH;
- return writeBigEndian(addlInfo, pos);
- default:
- CHECK(false); // Impossible to get here.
- return nullptr;
- }
-}
-
-void encodeHeader(MajorType type, uint64_t addlInfo, EncodeCallback encodeCallback) {
- size_t sz = headerSize(addlInfo);
- switch (sz) {
- case 1:
- encodeCallback(type | static_cast<uint8_t>(addlInfo));
- break;
- case 2:
- encodeCallback(type | ONE_BYTE_LENGTH);
- encodeCallback(static_cast<uint8_t>(addlInfo));
- break;
- case 3:
- encodeCallback(type | TWO_BYTE_LENGTH);
- writeBigEndian(static_cast<uint16_t>(addlInfo), encodeCallback);
- break;
- case 5:
- encodeCallback(type | FOUR_BYTE_LENGTH);
- writeBigEndian(static_cast<uint32_t>(addlInfo), encodeCallback);
- break;
- case 9:
- encodeCallback(type | EIGHT_BYTE_LENGTH);
- writeBigEndian(addlInfo, encodeCallback);
- break;
- default:
- CHECK(false); // Impossible to get here.
- }
-}
-
-bool Item::operator==(const Item& other) const& {
- if (type() != other.type()) return false;
- switch (type()) {
- case UINT:
- return *asUint() == *(other.asUint());
- case NINT:
- return *asNint() == *(other.asNint());
- case BSTR:
- return *asBstr() == *(other.asBstr());
- case TSTR:
- return *asTstr() == *(other.asTstr());
- case ARRAY:
- return *asArray() == *(other.asArray());
- case MAP:
- return *asMap() == *(other.asMap());
- case SIMPLE:
- return *asSimple() == *(other.asSimple());
- case SEMANTIC:
- return *asSemantic() == *(other.asSemantic());
- default:
- CHECK(false); // Impossible to get here.
- return false;
- }
-}
-
-Nint::Nint(int64_t v) : mValue(v) {
- CHECK(v < 0) << "Only negative values allowed";
-}
-
-bool Simple::operator==(const Simple& other) const& {
- if (simpleType() != other.simpleType()) return false;
-
- switch (simpleType()) {
- case BOOLEAN:
- return *asBool() == *(other.asBool());
- case NULL_T:
- return true;
- default:
- CHECK(false); // Impossible to get here.
- return false;
- }
-}
-
-uint8_t* Bstr::encode(uint8_t* pos, const uint8_t* end) const {
- pos = encodeHeader(mValue.size(), pos, end);
- if (!pos || end - pos < static_cast<ptrdiff_t>(mValue.size())) return nullptr;
- return std::copy(mValue.begin(), mValue.end(), pos);
-}
-
-void Bstr::encodeValue(EncodeCallback encodeCallback) const {
- for (auto c : mValue) {
- encodeCallback(c);
- }
-}
-
-uint8_t* Tstr::encode(uint8_t* pos, const uint8_t* end) const {
- pos = encodeHeader(mValue.size(), pos, end);
- if (!pos || end - pos < static_cast<ptrdiff_t>(mValue.size())) return nullptr;
- return std::copy(mValue.begin(), mValue.end(), pos);
-}
-
-void Tstr::encodeValue(EncodeCallback encodeCallback) const {
- for (auto c : mValue) {
- encodeCallback(static_cast<uint8_t>(c));
- }
-}
-
-bool CompoundItem::operator==(const CompoundItem& other) const& {
- return type() == other.type() //
- && addlInfo() == other.addlInfo() //
- // Can't use vector::operator== because the contents are pointers. std::equal lets us
- // provide a predicate that does the dereferencing.
- && std::equal(mEntries.begin(), mEntries.end(), other.mEntries.begin(),
- [](auto& a, auto& b) -> bool { return *a == *b; });
-}
-
-uint8_t* CompoundItem::encode(uint8_t* pos, const uint8_t* end) const {
- pos = encodeHeader(addlInfo(), pos, end);
- if (!pos) return nullptr;
- for (auto& entry : mEntries) {
- pos = entry->encode(pos, end);
- if (!pos) return nullptr;
- }
- return pos;
-}
-
-void CompoundItem::encode(EncodeCallback encodeCallback) const {
- encodeHeader(addlInfo(), encodeCallback);
- for (auto& entry : mEntries) {
- entry->encode(encodeCallback);
- }
-}
-
-void Map::assertInvariant() const {
- CHECK(mEntries.size() % 2 == 0);
-}
-
-std::unique_ptr<Item> Map::clone() const {
- assertInvariant();
- auto res = std::make_unique<Map>();
- for (size_t i = 0; i < mEntries.size(); i += 2) {
- res->add(mEntries[i]->clone(), mEntries[i + 1]->clone());
- }
- return res;
-}
-
-std::unique_ptr<Item> Array::clone() const {
- auto res = std::make_unique<Array>();
- for (size_t i = 0; i < mEntries.size(); i++) {
- res->add(mEntries[i]->clone());
- }
- return res;
-}
-
-void Semantic::assertInvariant() const {
- CHECK(mEntries.size() == 1);
-}
-
-} // namespace cppbor
diff --git a/identity/support/src/cppbor_parse.cpp b/identity/support/src/cppbor_parse.cpp
deleted file mode 100644
index c9ebb8a..0000000
--- a/identity/support/src/cppbor_parse.cpp
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright (c) 2019, 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 "cppbor_parse.h"
-
-#include <sstream>
-#include <stack>
-
-#define LOG_TAG "CppBor"
-#include <android-base/logging.h>
-
-namespace cppbor {
-
-namespace {
-
-std::string insufficientLengthString(size_t bytesNeeded, size_t bytesAvail,
- const std::string& type) {
- std::stringstream errStream;
- errStream << "Need " << bytesNeeded << " byte(s) for " << type << ", have " << bytesAvail
- << ".";
- return errStream.str();
-}
-
-template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
-std::tuple<bool, uint64_t, const uint8_t*> parseLength(const uint8_t* pos, const uint8_t* end,
- ParseClient* parseClient) {
- if (pos + sizeof(T) > end) {
- parseClient->error(pos - 1, insufficientLengthString(sizeof(T), end - pos, "length field"));
- return {false, 0, pos};
- }
-
- const uint8_t* intEnd = pos + sizeof(T);
- T result = 0;
- do {
- result = static_cast<T>((result << 8) | *pos++);
- } while (pos < intEnd);
- return {true, result, pos};
-}
-
-std::tuple<const uint8_t*, ParseClient*> parseRecursively(const uint8_t* begin, const uint8_t* end,
- ParseClient* parseClient);
-
-std::tuple<const uint8_t*, ParseClient*> handleUint(uint64_t value, const uint8_t* hdrBegin,
- const uint8_t* hdrEnd,
- ParseClient* parseClient) {
- std::unique_ptr<Item> item = std::make_unique<Uint>(value);
- return {hdrEnd,
- parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
-}
-
-std::tuple<const uint8_t*, ParseClient*> handleNint(uint64_t value, const uint8_t* hdrBegin,
- const uint8_t* hdrEnd,
- ParseClient* parseClient) {
- if (value > std::numeric_limits<int64_t>::max()) {
- parseClient->error(hdrBegin, "NINT values that don't fit in int64_t are not supported.");
- return {hdrBegin, nullptr /* end parsing */};
- }
- std::unique_ptr<Item> item = std::make_unique<Nint>(-1 - static_cast<uint64_t>(value));
- return {hdrEnd,
- parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
-}
-
-std::tuple<const uint8_t*, ParseClient*> handleBool(uint64_t value, const uint8_t* hdrBegin,
- const uint8_t* hdrEnd,
- ParseClient* parseClient) {
- std::unique_ptr<Item> item = std::make_unique<Bool>(value == TRUE);
- return {hdrEnd,
- parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
-}
-
-std::tuple<const uint8_t*, ParseClient*> handleNull(const uint8_t* hdrBegin, const uint8_t* hdrEnd,
- ParseClient* parseClient) {
- std::unique_ptr<Item> item = std::make_unique<Null>();
- return {hdrEnd,
- parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
-}
-
-template <typename T>
-std::tuple<const uint8_t*, ParseClient*> handleString(uint64_t length, const uint8_t* hdrBegin,
- const uint8_t* valueBegin, const uint8_t* end,
- const std::string& errLabel,
- ParseClient* parseClient) {
- if (end - valueBegin < static_cast<ssize_t>(length)) {
- parseClient->error(hdrBegin, insufficientLengthString(length, end - valueBegin, errLabel));
- return {hdrBegin, nullptr /* end parsing */};
- }
-
- std::unique_ptr<Item> item = std::make_unique<T>(valueBegin, valueBegin + length);
- return {valueBegin + length,
- parseClient->item(item, hdrBegin, valueBegin, valueBegin + length)};
-}
-
-class IncompleteItem {
- public:
- virtual ~IncompleteItem() {}
- virtual void add(std::unique_ptr<Item> item) = 0;
-};
-
-class IncompleteArray : public Array, public IncompleteItem {
- public:
- IncompleteArray(size_t size) : mSize(size) {}
-
- // We return the "complete" size, rather than the actual size.
- size_t size() const override { return mSize; }
-
- void add(std::unique_ptr<Item> item) override {
- mEntries.reserve(mSize);
- mEntries.push_back(std::move(item));
- }
-
- private:
- size_t mSize;
-};
-
-class IncompleteMap : public Map, public IncompleteItem {
- public:
- IncompleteMap(size_t size) : mSize(size) {}
-
- // We return the "complete" size, rather than the actual size.
- size_t size() const override { return mSize; }
-
- void add(std::unique_ptr<Item> item) override {
- mEntries.reserve(mSize * 2);
- mEntries.push_back(std::move(item));
- }
-
- private:
- size_t mSize;
-};
-
-class IncompleteSemantic : public Semantic, public IncompleteItem {
- public:
- IncompleteSemantic(uint64_t value) : Semantic(value) {}
-
- // We return the "complete" size, rather than the actual size.
- size_t size() const override { return 1; }
-
- void add(std::unique_ptr<Item> item) override {
- mEntries.reserve(1);
- mEntries.push_back(std::move(item));
- }
-};
-
-std::tuple<const uint8_t*, ParseClient*> handleEntries(size_t entryCount, const uint8_t* hdrBegin,
- const uint8_t* pos, const uint8_t* end,
- const std::string& typeName,
- ParseClient* parseClient) {
- while (entryCount > 0) {
- --entryCount;
- if (pos == end) {
- parseClient->error(hdrBegin, "Not enough entries for " + typeName + ".");
- return {hdrBegin, nullptr /* end parsing */};
- }
- std::tie(pos, parseClient) = parseRecursively(pos, end, parseClient);
- if (!parseClient) return {hdrBegin, nullptr};
- }
- return {pos, parseClient};
-}
-
-std::tuple<const uint8_t*, ParseClient*> handleCompound(
- std::unique_ptr<Item> item, uint64_t entryCount, const uint8_t* hdrBegin,
- const uint8_t* valueBegin, const uint8_t* end, const std::string& typeName,
- ParseClient* parseClient) {
- parseClient =
- parseClient->item(item, hdrBegin, valueBegin, valueBegin /* don't know the end yet */);
- if (!parseClient) return {hdrBegin, nullptr};
-
- const uint8_t* pos;
- std::tie(pos, parseClient) =
- handleEntries(entryCount, hdrBegin, valueBegin, end, typeName, parseClient);
- if (!parseClient) return {hdrBegin, nullptr};
-
- return {pos, parseClient->itemEnd(item, hdrBegin, valueBegin, pos)};
-}
-
-std::tuple<const uint8_t*, ParseClient*> parseRecursively(const uint8_t* begin, const uint8_t* end,
- ParseClient* parseClient) {
- const uint8_t* pos = begin;
-
- MajorType type = static_cast<MajorType>(*pos & 0xE0);
- uint8_t tagInt = *pos & 0x1F;
- ++pos;
-
- bool success = true;
- uint64_t addlData;
- if (tagInt < ONE_BYTE_LENGTH || tagInt > EIGHT_BYTE_LENGTH) {
- addlData = tagInt;
- } else {
- switch (tagInt) {
- case ONE_BYTE_LENGTH:
- std::tie(success, addlData, pos) = parseLength<uint8_t>(pos, end, parseClient);
- break;
-
- case TWO_BYTE_LENGTH:
- std::tie(success, addlData, pos) = parseLength<uint16_t>(pos, end, parseClient);
- break;
-
- case FOUR_BYTE_LENGTH:
- std::tie(success, addlData, pos) = parseLength<uint32_t>(pos, end, parseClient);
- break;
-
- case EIGHT_BYTE_LENGTH:
- std::tie(success, addlData, pos) = parseLength<uint64_t>(pos, end, parseClient);
- break;
-
- default:
- CHECK(false); // It's impossible to get here
- break;
- }
- }
-
- if (!success) return {begin, nullptr};
-
- switch (type) {
- case UINT:
- return handleUint(addlData, begin, pos, parseClient);
-
- case NINT:
- return handleNint(addlData, begin, pos, parseClient);
-
- case BSTR:
- return handleString<Bstr>(addlData, begin, pos, end, "byte string", parseClient);
-
- case TSTR:
- return handleString<Tstr>(addlData, begin, pos, end, "text string", parseClient);
-
- case ARRAY:
- return handleCompound(std::make_unique<IncompleteArray>(addlData), addlData, begin, pos,
- end, "array", parseClient);
-
- case MAP:
- return handleCompound(std::make_unique<IncompleteMap>(addlData), addlData * 2, begin,
- pos, end, "map", parseClient);
-
- case SEMANTIC:
- return handleCompound(std::make_unique<IncompleteSemantic>(addlData), 1, begin, pos,
- end, "semantic", parseClient);
-
- case SIMPLE:
- switch (addlData) {
- case TRUE:
- case FALSE:
- return handleBool(addlData, begin, pos, parseClient);
- case NULL_V:
- return handleNull(begin, pos, parseClient);
- }
- }
- CHECK(false); // Impossible to get here.
- return {};
-}
-
-class FullParseClient : public ParseClient {
- public:
- virtual ParseClient* item(std::unique_ptr<Item>& item, const uint8_t*, const uint8_t*,
- const uint8_t* end) override {
- if (mParentStack.empty() && !item->isCompound()) {
- // This is the first and only item.
- mTheItem = std::move(item);
- mPosition = end;
- return nullptr; // We're done.
- }
-
- if (item->isCompound()) {
- // Starting a new compound data item, i.e. a new parent. Save it on the parent stack.
- // It's safe to save a raw pointer because the unique_ptr is guaranteed to stay in
- // existence until the corresponding itemEnd() call.
- assert(dynamic_cast<CompoundItem*>(item.get()));
- mParentStack.push(static_cast<CompoundItem*>(item.get()));
- return this;
- } else {
- appendToLastParent(std::move(item));
- return this;
- }
- }
-
- virtual ParseClient* itemEnd(std::unique_ptr<Item>& item, const uint8_t*, const uint8_t*,
- const uint8_t* end) override {
- CHECK(item->isCompound() && item.get() == mParentStack.top());
- mParentStack.pop();
-
- if (mParentStack.empty()) {
- mTheItem = std::move(item);
- mPosition = end;
- return nullptr; // We're done
- } else {
- appendToLastParent(std::move(item));
- return this;
- }
- }
-
- virtual void error(const uint8_t* position, const std::string& errorMessage) override {
- mPosition = position;
- mErrorMessage = errorMessage;
- }
-
- std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
- std::string /* errMsg */>
- parseResult() {
- std::unique_ptr<Item> p = std::move(mTheItem);
- return {std::move(p), mPosition, std::move(mErrorMessage)};
- }
-
- private:
- void appendToLastParent(std::unique_ptr<Item> item) {
- auto parent = mParentStack.top();
- assert(dynamic_cast<IncompleteItem*>(parent));
- if (parent->type() == ARRAY) {
- static_cast<IncompleteArray*>(parent)->add(std::move(item));
- } else if (parent->type() == MAP) {
- static_cast<IncompleteMap*>(parent)->add(std::move(item));
- } else if (parent->type() == SEMANTIC) {
- static_cast<IncompleteSemantic*>(parent)->add(std::move(item));
- } else {
- CHECK(false); // Impossible to get here.
- }
- }
-
- std::unique_ptr<Item> mTheItem;
- std::stack<CompoundItem*> mParentStack;
- const uint8_t* mPosition = nullptr;
- std::string mErrorMessage;
-};
-
-} // anonymous namespace
-
-void parse(const uint8_t* begin, const uint8_t* end, ParseClient* parseClient) {
- parseRecursively(begin, end, parseClient);
-}
-
-std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
- std::string /* errMsg */>
-parse(const uint8_t* begin, const uint8_t* end) {
- FullParseClient parseClient;
- parse(begin, end, &parseClient);
- return parseClient.parseResult();
-}
-
-} // namespace cppbor
diff --git a/identity/support/tests/cppbor_test.cpp b/identity/support/tests/cppbor_test.cpp
deleted file mode 100644
index 3eb5598..0000000
--- a/identity/support/tests/cppbor_test.cpp
+++ /dev/null
@@ -1,1013 +0,0 @@
-/*
- * Copyright (c) 2019, 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 <iomanip>
-#include <sstream>
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "cppbor.h"
-#include "cppbor_parse.h"
-
-using namespace cppbor;
-using namespace std;
-
-using ::testing::_;
-using ::testing::AllOf;
-using ::testing::ByRef;
-using ::testing::InSequence;
-using ::testing::IsNull;
-using ::testing::NotNull;
-using ::testing::Return;
-using ::testing::Truly;
-using ::testing::Unused;
-
-string hexDump(const string& str) {
- stringstream s;
- for (auto c : str) {
- s << setfill('0') << setw(2) << hex << (static_cast<unsigned>(c) & 0xff);
- }
- return s.str();
-}
-
-TEST(SimpleValueTest, UnsignedValueSizes) {
- // Check that unsigned integers encode to correct lengths, and that encodedSize() is correct.
- vector<pair<uint64_t /* value */, size_t /* expected encoded size */>> testCases{
- {0, 1},
- {1, 1},
- {23, 1},
- {24, 2},
- {255, 2},
- {256, 3},
- {65535, 3},
- {65536, 5},
- {4294967295, 5},
- {4294967296, 9},
- {std::numeric_limits<uint64_t>::max(), 9},
- };
- for (auto& testCase : testCases) {
- Uint val(testCase.first);
- EXPECT_EQ(testCase.second, val.encodedSize()) << "Wrong size for value " << testCase.first;
- EXPECT_EQ(val.encodedSize(), val.toString().size())
- << "encodedSize and encoding disagree for value " << testCase.first;
- }
-}
-
-TEST(SimpleValueTest, UnsignedValueEncodings) {
- EXPECT_EQ("\x00"s, Uint(0u).toString());
- EXPECT_EQ("\x01"s, Uint(1u).toString());
- EXPECT_EQ("\x0a"s, Uint(10u).toString());
- EXPECT_EQ("\x17"s, Uint(23u).toString());
- EXPECT_EQ("\x18\x18"s, Uint(24u).toString());
- EXPECT_EQ("\x18\x19"s, Uint(25u).toString());
- EXPECT_EQ("\x18\x64"s, Uint(100u).toString());
- EXPECT_EQ("\x19\x03\xe8"s, Uint(1000u).toString());
- EXPECT_EQ("\x1a\x00\x0f\x42\x40"s, Uint(1000000u).toString());
- EXPECT_EQ("\x1b\x00\x00\x00\xe8\xd4\xa5\x10\x00"s, Uint(1000000000000u).toString());
- EXPECT_EQ("\x1B\x7f\xff\xff\xff\xff\xff\xff\xff"s,
- Uint(std::numeric_limits<int64_t>::max()).toString());
-}
-
-TEST(SimpleValueTest, NegativeValueEncodings) {
- EXPECT_EQ("\x20"s, Nint(-1).toString());
- EXPECT_EQ("\x28"s, Nint(-9).toString());
- EXPECT_EQ("\x29"s, Nint(-10).toString());
- EXPECT_EQ("\x36"s, Nint(-23).toString());
- EXPECT_EQ("\x37"s, Nint(-24).toString());
- EXPECT_EQ("\x38\x18"s, Nint(-25).toString());
- EXPECT_EQ("\x38\x62"s, Nint(-99).toString());
- EXPECT_EQ("\x38\x63"s, Nint(-100).toString());
- EXPECT_EQ("\x39\x03\xe6"s, Nint(-999).toString());
- EXPECT_EQ("\x39\x03\xe7"s, Nint(-1000).toString());
- EXPECT_EQ("\x3a\x00\x0f\x42\x3F"s, Nint(-1000000).toString());
- EXPECT_EQ("\x3b\x00\x00\x00\xe8\xd4\xa5\x0f\xff"s, Nint(-1000000000000).toString());
- EXPECT_EQ("\x3B\x7f\xff\xff\xff\xff\xff\xff\xff"s,
- Nint(std::numeric_limits<int64_t>::min()).toString());
-}
-
-TEST(SimpleValueDeathTest, NegativeValueEncodings) {
- EXPECT_DEATH(Nint(0), "");
- EXPECT_DEATH(Nint(1), "");
-}
-
-TEST(SimpleValueTest, BooleanEncodings) {
- EXPECT_EQ("\xf4"s, Bool(false).toString());
- EXPECT_EQ("\xf5"s, Bool(true).toString());
-}
-
-TEST(SimpleValueTest, ByteStringEncodings) {
- EXPECT_EQ("\x40", Bstr("").toString());
- EXPECT_EQ("\x41\x61", Bstr("a").toString());
- EXPECT_EQ("\x41\x41", Bstr("A").toString());
- EXPECT_EQ("\x44\x49\x45\x54\x46", Bstr("IETF").toString());
- EXPECT_EQ("\x42\x22\x5c", Bstr("\"\\").toString());
- EXPECT_EQ("\x42\xc3\xbc", Bstr("\xc3\xbc").toString());
- EXPECT_EQ("\x43\xe6\xb0\xb4", Bstr("\xe6\xb0\xb4").toString());
- EXPECT_EQ("\x44\xf0\x90\x85\x91", Bstr("\xf0\x90\x85\x91").toString());
- EXPECT_EQ("\x44\x01\x02\x03\x04", Bstr("\x01\x02\x03\x04").toString());
- EXPECT_EQ("\x44\x40\x40\x40\x40", Bstr("@@@@").toString());
-}
-
-TEST(SimpleValueTest, TextStringEncodings) {
- EXPECT_EQ("\x60"s, Tstr("").toString());
- EXPECT_EQ("\x61\x61"s, Tstr("a").toString());
- EXPECT_EQ("\x61\x41"s, Tstr("A").toString());
- EXPECT_EQ("\x64\x49\x45\x54\x46"s, Tstr("IETF").toString());
- EXPECT_EQ("\x62\x22\x5c"s, Tstr("\"\\").toString());
- EXPECT_EQ("\x62\xc3\xbc"s, Tstr("\xc3\xbc").toString());
- EXPECT_EQ("\x63\xe6\xb0\xb4"s, Tstr("\xe6\xb0\xb4").toString());
- EXPECT_EQ("\x64\xf0\x90\x85\x91"s, Tstr("\xf0\x90\x85\x91").toString());
- EXPECT_EQ("\x64\x01\x02\x03\x04"s, Tstr("\x01\x02\x03\x04").toString());
-}
-
-TEST(IsIteratorPairOverTest, All) {
- EXPECT_TRUE((
- details::is_iterator_pair_over<pair<string::iterator, string::iterator>, char>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<pair<string::const_iterator, string::iterator>,
- char>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<pair<string::iterator, string::const_iterator>,
- char>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<pair<char*, char*>, char>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<pair<const char*, char*>, char>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<pair<char*, const char*>, char>::value));
- EXPECT_FALSE((details::is_iterator_pair_over<pair<string::iterator, string::iterator>,
- uint8_t>::value));
- EXPECT_FALSE((details::is_iterator_pair_over<pair<char*, char*>, uint8_t>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<
- pair<vector<uint8_t>::iterator, vector<uint8_t>::iterator>, uint8_t>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<
- pair<vector<uint8_t>::const_iterator, vector<uint8_t>::iterator>,
- uint8_t>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<
- pair<vector<uint8_t>::iterator, vector<uint8_t>::const_iterator>,
- uint8_t>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<pair<uint8_t*, uint8_t*>, uint8_t>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<pair<const uint8_t*, uint8_t*>, uint8_t>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<pair<uint8_t*, const uint8_t*>, uint8_t>::value));
- EXPECT_FALSE((details::is_iterator_pair_over<
- pair<vector<uint8_t>::iterator, vector<uint8_t>::iterator>, char>::value));
- EXPECT_FALSE((details::is_iterator_pair_over<pair<uint8_t*, const uint8_t*>, char>::value));
-}
-
-TEST(MakeEntryTest, Boolean) {
- EXPECT_EQ("\xf4"s, details::makeItem(false)->toString());
-}
-
-TEST(MakeEntryTest, Integers) {
- EXPECT_EQ("\x00"s, details::makeItem(static_cast<uint8_t>(0))->toString());
- EXPECT_EQ("\x00"s, details::makeItem(static_cast<uint16_t>(0))->toString());
- EXPECT_EQ("\x00"s, details::makeItem(static_cast<uint32_t>(0))->toString());
- EXPECT_EQ("\x00"s, details::makeItem(static_cast<uint64_t>(0))->toString());
- EXPECT_EQ("\x00"s, details::makeItem(static_cast<int8_t>(0))->toString());
- EXPECT_EQ("\x00"s, details::makeItem(static_cast<int16_t>(0))->toString());
- EXPECT_EQ("\x00"s, details::makeItem(static_cast<int32_t>(0))->toString());
- EXPECT_EQ("\x00"s, details::makeItem(static_cast<int64_t>(0))->toString());
- EXPECT_EQ("\x20"s, details::makeItem(static_cast<int8_t>(-1))->toString());
- EXPECT_EQ("\x20"s, details::makeItem(static_cast<int16_t>(-1))->toString());
- EXPECT_EQ("\x20"s, details::makeItem(static_cast<int32_t>(-1))->toString());
- EXPECT_EQ("\x20"s, details::makeItem(static_cast<int64_t>(-1))->toString());
-
- EXPECT_EQ("\x1b\xff\xff\xff\xff\xff\xff\xff\xff"s,
- details::makeItem(static_cast<uint64_t>(std::numeric_limits<uint64_t>::max()))
- ->toString());
-}
-
-TEST(MakeEntryTest, StdStrings) {
- string s1("hello");
- const string s2("hello");
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s1)->toString()); // copy of string
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s,
- details::makeItem(s2)->toString()); // copy of const string
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s,
- details::makeItem(std::move(s1))->toString()); // move string
- EXPECT_EQ(0U, s1.size()); // Prove string was moved, not copied.
-}
-
-TEST(MakeEntryTest, StdStringViews) {
- string_view s1("hello");
- const string_view s2("hello");
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s1)->toString());
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s2)->toString());
-}
-
-TEST(MakeEntryTest, CStrings) {
- char s1[] = "hello";
- const char s2[] = "hello";
- const char* s3 = "hello";
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s1)->toString());
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s2)->toString());
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s3)->toString());
-}
-
-TEST(MakeEntryTest, StringIteratorPairs) {
- // Use iterators from string to prove that "real" iterators work
- string s1 = "hello"s;
- pair<string::iterator, string::iterator> p1 = make_pair(s1.begin(), s1.end());
-
- const pair<string::iterator, string::iterator> p2 = p1;
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(p1)->toString());
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(p2)->toString());
-
- // Use char*s as iterators
- const char* s2 = "hello";
- pair p3 = make_pair(s2, s2 + 5);
- const pair p4 = p3;
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(p3)->toString());
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(p4)->toString());
-}
-
-TEST(MakeEntryTest, ByteStrings) {
- vector<uint8_t> v1 = {0x00, 0x01, 0x02};
- const vector<uint8_t> v2 = {0x00, 0x01, 0x02};
- EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(v1)->toString()); // copy of vector
- EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(v2)->toString()); // copy of const vector
- EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(std::move(v1))->toString()); // move vector
- EXPECT_EQ(0U, v1.size()); // Prove vector was moved, not copied.
-}
-
-TEST(MakeEntryTest, ByteStringIteratorPairs) {
- using vec = vector<uint8_t>;
- using iter = vec::iterator;
- vec v1 = {0x00, 0x01, 0x02};
- pair<iter, iter> p1 = make_pair(v1.begin(), v1.end());
- const pair<iter, iter> p2 = make_pair(v1.begin(), v1.end());
- EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p1)->toString());
- EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p2)->toString());
-
- // Use uint8_t*s as iterators
- uint8_t v2[] = {0x00, 0x01, 0x02};
- uint8_t* v3 = v2;
- pair<uint8_t*, uint8_t*> p3 = make_pair(v2, v2 + 3);
- const pair<uint8_t*, uint8_t*> p4 = make_pair(v2, v2 + 3);
- pair<uint8_t*, uint8_t*> p5 = make_pair(v3, v3 + 3);
- const pair<uint8_t*, uint8_t*> p6 = make_pair(v3, v3 + 3);
- EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p3)->toString());
- EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p4)->toString());
- EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p5)->toString());
- EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p6)->toString());
-}
-
-TEST(MakeEntryTest, ByteStringBuffers) {
- uint8_t v1[] = {0x00, 0x01, 0x02};
- EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(make_pair(v1, 3))->toString());
-}
-
-TEST(MakeEntryTest, ItemPointer) {
- Uint* p1 = new Uint(0);
- EXPECT_EQ("\x00"s, details::makeItem(p1)->toString());
- EXPECT_EQ("\x60"s, details::makeItem(new Tstr(string()))->toString());
-}
-
-TEST(MakeEntryTest, ItemReference) {
- Tstr str("hello"s);
- Tstr& strRef = str;
- const Tstr& strConstRef = str;
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(str)->toString());
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(strRef)->toString());
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(strConstRef)->toString());
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(std::move(str))->toString());
- EXPECT_EQ("\x60"s, details::makeItem(str)->toString()); // Prove that it moved
-
- EXPECT_EQ("\x00"s, details::makeItem(Uint(0))->toString());
-
- EXPECT_EQ("\x43\x00\x01\x02"s,
- details::makeItem(Bstr(vector<uint8_t>{0x00, 0x01, 0x02}))->toString());
-
- EXPECT_EQ("\x80"s, details::makeItem(Array())->toString());
- EXPECT_EQ("\xa0"s, details::makeItem(Map())->toString());
-}
-
-TEST(CompoundValueTest, ArrayOfInts) {
- EXPECT_EQ("\x80"s, Array().toString());
- Array(Uint(0)).toString();
-
- EXPECT_EQ("\x81\x00"s, Array(Uint(0U)).toString());
- EXPECT_EQ("\x82\x00\x01"s, Array(Uint(0), Uint(1)).toString());
- EXPECT_EQ("\x83\x00\x01\x38\x62"s, Array(Uint(0), Uint(1), Nint(-99)).toString());
-
- EXPECT_EQ("\x81\x00"s, Array(0).toString());
- EXPECT_EQ("\x82\x00\x01"s, Array(0, 1).toString());
- EXPECT_EQ("\x83\x00\x01\x38\x62"s, Array(0, 1, -99).toString());
-}
-
-TEST(CompoundValueTest, MapOfInts) {
- EXPECT_EQ("\xA0"s, Map().toString());
- EXPECT_EQ("\xA1\x00\x01"s, Map(Uint(0), Uint(1)).toString());
- // Maps with an odd number of arguments will fail to compile. Uncomment the next lines to test.
- // EXPECT_EQ("\xA1\x00"s, Map(Int(0)).toString());
- // EXPECT_EQ("\xA1\x00\x01\x02"s, Map(Int(0), Int(1), Int(2)).toString());
-}
-
-TEST(CompoundValueTest, MixedArray) {
- vector<uint8_t> vec = {3, 2, 1};
- EXPECT_EQ("\x84\x01\x20\x43\x03\x02\x01\x65\x68\x65\x6C\x6C\x6F"s,
- Array(Uint(1), Nint(-1), Bstr(vec), Tstr("hello")).toString());
-
- EXPECT_EQ("\x84\x01\x20\x43\x03\x02\x01\x65\x68\x65\x6C\x6C\x6F"s,
- Array(1, -1, vec, "hello").toString());
-}
-
-TEST(CompoundValueTest, MixedMap) {
- vector<uint8_t> vec = {3, 2, 1};
- EXPECT_EQ("\xA2\x01\x20\x43\x03\x02\x01\x65\x68\x65\x6C\x6C\x6F"s,
- Map(Uint(1), Nint(-1), Bstr(vec), Tstr("hello")).toString());
-
- EXPECT_EQ("\xA2\x01\x20\x43\x03\x02\x01\x65\x68\x65\x6C\x6C\x6F"s,
- Map(1, -1, vec, "hello").toString());
-}
-
-TEST(CompoundValueTest, NestedStructures) {
- vector<uint8_t> vec = {3, 2, 1};
-
- string expectedEncoding =
- "\xA2\x66\x4F\x75\x74\x65\x72\x31\x82\xA2\x66\x49\x6E\x6E\x65\x72\x31\x18\x63\x66\x49"
- "\x6E"
- "\x6E\x65\x72\x32\x43\x03\x02\x01\x63\x66\x6F\x6F\x66\x4F\x75\x74\x65\x72\x32\x0A"s;
-
- // Do it with explicitly-created Items
- EXPECT_EQ(expectedEncoding,
- Map(Tstr("Outer1"),
- Array( //
- Map(Tstr("Inner1"), Uint(99), Tstr("Inner2"), Bstr(vec)), Tstr("foo")),
- Tstr("Outer2"), //
- Uint(10))
- .toString());
- EXPECT_EQ(3U, vec.size());
-
- // Now just use convertible types
- EXPECT_EQ(expectedEncoding, Map("Outer1",
- Array(Map("Inner1", 99, //
- "Inner2", vec),
- "foo"),
- "Outer2", 10)
- .toString());
- EXPECT_EQ(3U, vec.size());
-
- // Finally, do it with the .add() method. This is slightly less efficient, but has the
- // advantage you can build a structure up incrementally, or somewhat fluently if you like.
- // First, fluently.
- EXPECT_EQ(expectedEncoding, Map().add("Outer1", Array().add(Map() //
- .add("Inner1", 99)
- .add("Inner2", vec))
- .add("foo"))
- .add("Outer2", 10)
- .toString());
- EXPECT_EQ(3U, vec.size());
-
- // Next, more incrementally
- Array arr;
- arr.add(Map() //
- .add("Inner1", 99)
- .add("Inner2", vec))
- .add("foo");
- EXPECT_EQ(3U, vec.size());
-
- Map m;
- m.add("Outer1", std::move(arr)); // Moving is necessary; Map and Array cannot be copied.
- m.add("Outer2", 10);
- auto s = m.toString();
- EXPECT_EQ(expectedEncoding, s);
-}
-
-TEST(EncodingMethodsTest, AllVariants) {
- Map map;
- map.add("key1", Array().add(Map() //
- .add("key_a", 9999999)
- .add("key_b", std::vector<uint8_t>{0x01, 0x02, 0x03})
- .add("key_c", std::numeric_limits<uint64_t>::max())
- .add("key_d", std::numeric_limits<int16_t>::min()))
- .add("foo"))
- .add("key2", true);
-
- std::vector<uint8_t> buf;
- buf.resize(map.encodedSize());
-
- EXPECT_EQ(buf.data() + buf.size(), map.encode(buf.data(), buf.data() + buf.size()));
-
- EXPECT_EQ(buf, map.encode());
-
- std::vector<uint8_t> buf2;
- map.encode(std::back_inserter(buf2));
- EXPECT_EQ(buf, buf2);
-
- auto iter = buf.begin();
- map.encode([&](uint8_t c) { EXPECT_EQ(c, *iter++); });
-}
-
-TEST(EncodingMethodsTest, UintWithTooShortBuf) {
- Uint val(100000);
- vector<uint8_t> buf(val.encodedSize() - 1);
- EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-}
-
-TEST(EncodingMethodsTest, TstrWithTooShortBuf) {
- Tstr val("01234567890123456789012345"s);
- vector<uint8_t> buf(1);
- EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-
- buf.resize(val.encodedSize() - 1);
- EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-}
-
-TEST(EncodingMethodsTest, BstrWithTooShortBuf) {
- Bstr val("01234567890123456789012345"s);
- vector<uint8_t> buf(1);
- EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-
- buf.resize(val.encodedSize() - 1);
- EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-}
-
-TEST(EncodingMethodsTest, ArrayWithTooShortBuf) {
- Array val("a", 5, -100);
-
- std::vector<uint8_t> buf(val.encodedSize() - 1);
- EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-}
-
-TEST(EncodingMethodsTest, MapWithTooShortBuf) {
- Map map;
- map.add("key1", Array().add(Map() //
- .add("key_a", 99)
- .add("key_b", std::vector<uint8_t>{0x01, 0x02, 0x03}))
- .add("foo"))
- .add("key2", true);
-
- std::vector<uint8_t> buf(map.encodedSize() - 1);
- EXPECT_EQ(nullptr, map.encode(buf.data(), buf.data() + buf.size()));
-}
-
-TEST(EqualityTest, Uint) {
- Uint val(99);
- EXPECT_EQ(val, Uint(99));
-
- EXPECT_NE(val, Uint(98));
- EXPECT_NE(val, Nint(-1));
- EXPECT_NE(val, Tstr("99"));
- EXPECT_NE(val, Bstr("99"));
- EXPECT_NE(val, Bool(false));
- EXPECT_NE(val, Array(99, 1));
- EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Nint) {
- Nint val(-1);
- EXPECT_EQ(val, Nint(-1));
-
- EXPECT_NE(val, Uint(99));
- EXPECT_NE(val, Nint(-4));
- EXPECT_NE(val, Tstr("99"));
- EXPECT_NE(val, Bstr("99"));
- EXPECT_NE(val, Bool(false));
- EXPECT_NE(val, Array(99));
- EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Tstr) {
- Tstr val("99");
- EXPECT_EQ(val, Tstr("99"));
-
- EXPECT_NE(val, Uint(99));
- EXPECT_NE(val, Nint(-1));
- EXPECT_NE(val, Nint(-4));
- EXPECT_NE(val, Tstr("98"));
- EXPECT_NE(val, Bstr("99"));
- EXPECT_NE(val, Bool(false));
- EXPECT_NE(val, Array(99, 1));
- EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Bstr) {
- Bstr val("99");
- EXPECT_EQ(val, Bstr("99"));
-
- EXPECT_NE(val, Uint(99));
- EXPECT_NE(val, Nint(-1));
- EXPECT_NE(val, Nint(-4));
- EXPECT_NE(val, Tstr("99"));
- EXPECT_NE(val, Bstr("98"));
- EXPECT_NE(val, Bool(false));
- EXPECT_NE(val, Array(99, 1));
- EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Bool) {
- Bool val(false);
- EXPECT_EQ(val, Bool(false));
-
- EXPECT_NE(val, Uint(99));
- EXPECT_NE(val, Nint(-1));
- EXPECT_NE(val, Nint(-4));
- EXPECT_NE(val, Tstr("99"));
- EXPECT_NE(val, Bstr("98"));
- EXPECT_NE(val, Bool(true));
- EXPECT_NE(val, Array(99, 1));
- EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Array) {
- Array val(99, 1);
- EXPECT_EQ(val, Array(99, 1));
-
- EXPECT_NE(val, Uint(99));
- EXPECT_NE(val, Nint(-1));
- EXPECT_NE(val, Nint(-4));
- EXPECT_NE(val, Tstr("99"));
- EXPECT_NE(val, Bstr("98"));
- EXPECT_NE(val, Bool(true));
- EXPECT_NE(val, Array(99, 2));
- EXPECT_NE(val, Array(98, 1));
- EXPECT_NE(val, Array(99, 1, 2));
- EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Map) {
- Map val(99, 1);
- EXPECT_EQ(val, Map(99, 1));
-
- EXPECT_NE(val, Uint(99));
- EXPECT_NE(val, Nint(-1));
- EXPECT_NE(val, Nint(-4));
- EXPECT_NE(val, Tstr("99"));
- EXPECT_NE(val, Bstr("98"));
- EXPECT_NE(val, Bool(true));
- EXPECT_NE(val, Array(99, 1));
- EXPECT_NE(val, Map(99, 2));
- EXPECT_NE(val, Map(99, 1, 99, 2));
-}
-
-TEST(ConvertTest, Uint) {
- unique_ptr<Item> item = details::makeItem(10);
-
- EXPECT_EQ(UINT, item->type());
- EXPECT_NE(nullptr, item->asInt());
- EXPECT_NE(nullptr, item->asUint());
- EXPECT_EQ(nullptr, item->asNint());
- EXPECT_EQ(nullptr, item->asTstr());
- EXPECT_EQ(nullptr, item->asBstr());
- EXPECT_EQ(nullptr, item->asSimple());
- EXPECT_EQ(nullptr, item->asMap());
- EXPECT_EQ(nullptr, item->asArray());
-
- EXPECT_EQ(10, item->asInt()->value());
- EXPECT_EQ(10, item->asUint()->value());
-}
-
-TEST(ConvertTest, Nint) {
- unique_ptr<Item> item = details::makeItem(-10);
-
- EXPECT_EQ(NINT, item->type());
- EXPECT_NE(nullptr, item->asInt());
- EXPECT_EQ(nullptr, item->asUint());
- EXPECT_NE(nullptr, item->asNint());
- EXPECT_EQ(nullptr, item->asTstr());
- EXPECT_EQ(nullptr, item->asBstr());
- EXPECT_EQ(nullptr, item->asSimple());
- EXPECT_EQ(nullptr, item->asMap());
- EXPECT_EQ(nullptr, item->asArray());
-
- EXPECT_EQ(-10, item->asInt()->value());
- EXPECT_EQ(-10, item->asNint()->value());
-}
-
-TEST(ConvertTest, Tstr) {
- unique_ptr<Item> item = details::makeItem("hello");
-
- EXPECT_EQ(TSTR, item->type());
- EXPECT_EQ(nullptr, item->asInt());
- EXPECT_EQ(nullptr, item->asUint());
- EXPECT_EQ(nullptr, item->asNint());
- EXPECT_NE(nullptr, item->asTstr());
- EXPECT_EQ(nullptr, item->asBstr());
- EXPECT_EQ(nullptr, item->asSimple());
- EXPECT_EQ(nullptr, item->asMap());
- EXPECT_EQ(nullptr, item->asArray());
-
- EXPECT_EQ("hello"s, item->asTstr()->value());
-}
-
-TEST(ConvertTest, Bstr) {
- vector<uint8_t> vec{0x23, 0x24, 0x22};
- unique_ptr<Item> item = details::makeItem(vec);
-
- EXPECT_EQ(BSTR, item->type());
- EXPECT_EQ(nullptr, item->asInt());
- EXPECT_EQ(nullptr, item->asUint());
- EXPECT_EQ(nullptr, item->asNint());
- EXPECT_EQ(nullptr, item->asTstr());
- EXPECT_NE(nullptr, item->asBstr());
- EXPECT_EQ(nullptr, item->asSimple());
- EXPECT_EQ(nullptr, item->asMap());
- EXPECT_EQ(nullptr, item->asArray());
-
- EXPECT_EQ(vec, item->asBstr()->value());
-}
-
-TEST(ConvertTest, Bool) {
- unique_ptr<Item> item = details::makeItem(false);
-
- EXPECT_EQ(SIMPLE, item->type());
- EXPECT_EQ(nullptr, item->asInt());
- EXPECT_EQ(nullptr, item->asUint());
- EXPECT_EQ(nullptr, item->asNint());
- EXPECT_EQ(nullptr, item->asTstr());
- EXPECT_EQ(nullptr, item->asBstr());
- EXPECT_NE(nullptr, item->asSimple());
- EXPECT_EQ(nullptr, item->asMap());
- EXPECT_EQ(nullptr, item->asArray());
-
- EXPECT_EQ(BOOLEAN, item->asSimple()->simpleType());
- EXPECT_NE(nullptr, item->asSimple()->asBool());
-
- EXPECT_FALSE(item->asSimple()->asBool()->value());
-}
-
-TEST(ConvertTest, Map) {
- unique_ptr<Item> item(new Map);
-
- EXPECT_EQ(MAP, item->type());
- EXPECT_EQ(nullptr, item->asInt());
- EXPECT_EQ(nullptr, item->asUint());
- EXPECT_EQ(nullptr, item->asNint());
- EXPECT_EQ(nullptr, item->asTstr());
- EXPECT_EQ(nullptr, item->asBstr());
- EXPECT_EQ(nullptr, item->asSimple());
- EXPECT_NE(nullptr, item->asMap());
- EXPECT_EQ(nullptr, item->asArray());
-
- EXPECT_EQ(0U, item->asMap()->size());
-}
-
-TEST(ConvertTest, Array) {
- unique_ptr<Item> item(new Array);
-
- EXPECT_EQ(ARRAY, item->type());
- EXPECT_EQ(nullptr, item->asInt());
- EXPECT_EQ(nullptr, item->asUint());
- EXPECT_EQ(nullptr, item->asNint());
- EXPECT_EQ(nullptr, item->asTstr());
- EXPECT_EQ(nullptr, item->asBstr());
- EXPECT_EQ(nullptr, item->asSimple());
- EXPECT_EQ(nullptr, item->asMap());
- EXPECT_NE(nullptr, item->asArray());
-
- EXPECT_EQ(0U, item->asArray()->size());
-}
-
-class MockParseClient : public ParseClient {
- public:
- MOCK_METHOD4(item, ParseClient*(std::unique_ptr<Item>& item, const uint8_t* hdrBegin,
- const uint8_t* valueBegin, const uint8_t* end));
- MOCK_METHOD4(itemEnd, ParseClient*(std::unique_ptr<Item>& item, const uint8_t* hdrBegin,
- const uint8_t* valueBegin, const uint8_t* end));
- MOCK_METHOD2(error, void(const uint8_t* position, const std::string& errorMessage));
-};
-
-MATCHER_P(IsType, value, std::string("Type ") + (negation ? "doesn't match" : "matches")) {
- return arg->type() == value;
-}
-
-MATCHER_P(MatchesItem, value, "") {
- return arg && *arg == value;
-}
-
-MATCHER_P(IsArrayOfSize, value, "") {
- return arg->type() == ARRAY && arg->asArray()->size() == value;
-}
-
-MATCHER_P(IsMapOfSize, value, "") {
- return arg->type() == MAP && arg->asMap()->size() == value;
-}
-
-TEST(StreamParseTest, Uint) {
- MockParseClient mpc;
-
- Uint val(100);
- auto encoded = val.encode();
- uint8_t* encBegin = encoded.data();
- uint8_t* encEnd = encoded.data() + encoded.size();
-
- EXPECT_CALL(mpc, item(MatchesItem(val), encBegin, encEnd, encEnd)).WillOnce(Return(&mpc));
- EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
- EXPECT_CALL(mpc, error(_, _)).Times(0);
-
- parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Nint) {
- MockParseClient mpc;
-
- Nint val(-10);
- auto encoded = val.encode();
- uint8_t* encBegin = encoded.data();
- uint8_t* encEnd = encoded.data() + encoded.size();
-
- EXPECT_CALL(mpc, item(MatchesItem(val), encBegin, encEnd, encEnd)).WillOnce(Return(&mpc));
-
- EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
- EXPECT_CALL(mpc, error(_, _)).Times(0);
-
- parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Bool) {
- MockParseClient mpc;
-
- Bool val(true);
- auto encoded = val.encode();
- uint8_t* encBegin = encoded.data();
- uint8_t* encEnd = encoded.data() + encoded.size();
-
- EXPECT_CALL(mpc, item(MatchesItem(val), encBegin, encEnd, encEnd)).WillOnce(Return(&mpc));
- EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
- EXPECT_CALL(mpc, error(_, _)).Times(0);
-
- parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Tstr) {
- MockParseClient mpc;
-
- Tstr val("Hello");
- auto encoded = val.encode();
- uint8_t* encBegin = encoded.data();
- uint8_t* encEnd = encoded.data() + encoded.size();
-
- EXPECT_CALL(mpc, item(MatchesItem(val), encBegin, encBegin + 1, encEnd)).WillOnce(Return(&mpc));
- EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
- EXPECT_CALL(mpc, error(_, _)).Times(0);
-
- parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Bstr) {
- MockParseClient mpc;
-
- Bstr val("Hello");
- auto encoded = val.encode();
- uint8_t* encBegin = encoded.data();
- uint8_t* encEnd = encoded.data() + encoded.size();
-
- EXPECT_CALL(mpc, item(MatchesItem(val), encBegin, encBegin + 1, encEnd)).WillOnce(Return(&mpc));
- EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
- EXPECT_CALL(mpc, error(_, _)).Times(0);
-
- parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Array) {
- MockParseClient mpc;
-
- Array val("Hello", 4, Array(-9, "Goodbye"), std::numeric_limits<uint64_t>::max());
- ASSERT_NE(val[2]->asArray(), nullptr);
- const Array& interior = *(val[2]->asArray());
- auto encoded = val.encode();
- uint8_t* encBegin = encoded.data();
- uint8_t* encEnd = encoded.data() + encoded.size();
-
- {
- InSequence s;
- const uint8_t* pos = encBegin;
- EXPECT_CALL(mpc, item(IsArrayOfSize(val.size()), pos, pos + 1, pos + 1))
- .WillOnce(Return(&mpc));
- ++pos;
- EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[0])), pos, pos + 1, pos + 6))
- .WillOnce(Return(&mpc));
- pos += 6;
- EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[1])), pos, pos + 1, pos + 1))
- .WillOnce(Return(&mpc));
- ++pos;
- const uint8_t* innerArrayBegin = pos;
- EXPECT_CALL(mpc, item(IsArrayOfSize(interior.size()), pos, pos + 1, pos + 1))
- .WillOnce(Return(&mpc));
- ++pos;
- EXPECT_CALL(mpc, item(MatchesItem(ByRef(*interior[0])), pos, pos + 1, pos + 1))
- .WillOnce(Return(&mpc));
- ++pos;
- EXPECT_CALL(mpc, item(MatchesItem(ByRef(*interior[1])), pos, pos + 1, pos + 8))
- .WillOnce(Return(&mpc));
- pos += 8;
- EXPECT_CALL(mpc, itemEnd(IsArrayOfSize(interior.size()), innerArrayBegin,
- innerArrayBegin + 1, pos))
- .WillOnce(Return(&mpc));
- EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[3])), pos, pos + 9, pos + 9))
- .WillOnce(Return(&mpc));
- EXPECT_CALL(mpc, itemEnd(IsArrayOfSize(val.size()), encBegin, encBegin + 1, encEnd))
- .WillOnce(Return(&mpc));
- }
-
- EXPECT_CALL(mpc, error(_, _)) //
- .Times(0);
-
- parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Map) {
- MockParseClient mpc;
-
- Map val("Hello", 4, Array(-9, "Goodbye"), std::numeric_limits<uint64_t>::max());
- ASSERT_NE(val[1].first->asArray(), nullptr);
- const Array& interior = *(val[1].first->asArray());
- auto encoded = val.encode();
- uint8_t* encBegin = encoded.data();
- uint8_t* encEnd = encoded.data() + encoded.size();
-
- {
- InSequence s;
- const uint8_t* pos = encBegin;
- EXPECT_CALL(mpc, item(_, pos, pos + 1, pos + 1)).WillOnce(Return(&mpc));
- ++pos;
- EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[0].first)), pos, pos + 1, pos + 6))
- .WillOnce(Return(&mpc));
- pos += 6;
- EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[0].second)), pos, pos + 1, pos + 1))
- .WillOnce(Return(&mpc));
- ++pos;
- const uint8_t* innerArrayBegin = pos;
- EXPECT_CALL(mpc, item(IsArrayOfSize(interior.size()), pos, pos + 1, pos + 1))
- .WillOnce(Return(&mpc));
- ++pos;
- EXPECT_CALL(mpc, item(MatchesItem(ByRef(*interior[0])), pos, pos + 1, pos + 1))
- .WillOnce(Return(&mpc));
- ++pos;
- EXPECT_CALL(mpc, item(MatchesItem(ByRef(*interior[1])), pos, pos + 1, pos + 8))
- .WillOnce(Return(&mpc));
- pos += 8;
- EXPECT_CALL(mpc, itemEnd(IsArrayOfSize(interior.size()), innerArrayBegin,
- innerArrayBegin + 1, pos))
- .WillOnce(Return(&mpc));
- EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[1].second)), pos, pos + 9, pos + 9))
- .WillOnce(Return(&mpc));
- EXPECT_CALL(mpc, itemEnd(IsMapOfSize(val.size()), encBegin, encBegin + 1, encEnd))
- .WillOnce(Return(&mpc));
- }
-
- EXPECT_CALL(mpc, error(_, _)) //
- .Times(0);
-
- parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Semantic) {
- MockParseClient mpc;
-
- vector<uint8_t> encoded;
- auto iter = back_inserter(encoded);
- encodeHeader(SEMANTIC, 0, iter);
- Uint(999).encode(iter);
-
- EXPECT_CALL(mpc, item(_, _, _, _)).Times(0);
- EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
- EXPECT_CALL(mpc, error(encoded.data(), "Semantic tags not supported"));
-
- parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(FullParserTest, Uint) {
- Uint val(10);
-
- auto [item, pos, message] = parse(val.encode());
- EXPECT_THAT(item, MatchesItem(val));
-}
-
-TEST(FullParserTest, Nint) {
- Nint val(-10);
-
- auto [item, pos, message] = parse(val.encode());
- EXPECT_THAT(item, MatchesItem(val));
-
- vector<uint8_t> minNint = {0x3B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
-
- std::tie(item, pos, message) = parse(minNint);
- EXPECT_THAT(item, NotNull());
- EXPECT_EQ(item->asNint()->value(), std::numeric_limits<int64_t>::min());
-}
-
-TEST(FullParserTest, NintOutOfRange) {
- vector<uint8_t> outOfRangeNint = {0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
-
- auto [item, pos, message] = parse(outOfRangeNint);
- EXPECT_THAT(item, IsNull());
- EXPECT_EQ(pos, outOfRangeNint.data());
- EXPECT_EQ(message, "NINT values that don't fit in int64_t are not supported.");
-}
-
-TEST(FullParserTest, Tstr) {
- Tstr val("Hello");
-
- auto [item, pos, message] = parse(val.encode());
- EXPECT_THAT(item, MatchesItem(val));
-}
-
-TEST(FullParserTest, Bstr) {
- Bstr val("\x00\x01\0x02"s);
-
- auto [item, pos, message] = parse(val.encode());
- EXPECT_THAT(item, MatchesItem(val));
-}
-
-TEST(FullParserTest, Array) {
- Array val("hello", -4, 3);
-
- auto encoded = val.encode();
- auto [item, pos, message] = parse(encoded);
- EXPECT_THAT(item, MatchesItem(ByRef(val)));
- EXPECT_EQ(pos, encoded.data() + encoded.size());
- EXPECT_EQ("", message);
-
- // We've already checked it all, but walk it just for fun.
- ASSERT_NE(nullptr, item->asArray());
- const Array& arr = *(item->asArray());
- ASSERT_EQ(arr[0]->type(), TSTR);
- EXPECT_EQ(arr[0]->asTstr()->value(), "hello");
-}
-
-TEST(FullParserTest, Map) {
- Map val("hello", -4, 3, Bstr("hi"));
-
- auto [item, pos, message] = parse(val.encode());
- EXPECT_THAT(item, MatchesItem(ByRef(val)));
-}
-
-TEST(FullParserTest, Complex) {
- vector<uint8_t> vec = {0x01, 0x02, 0x08, 0x03};
- Map val("Outer1",
- Array(Map("Inner1", 99, //
- "Inner2", vec),
- "foo"),
- "Outer2", 10);
-
- std::unique_ptr<Item> item;
- const uint8_t* pos;
- std::string message;
- std::tie(item, pos, message) = parse(val.encode());
- EXPECT_THAT(item, MatchesItem(ByRef(val)));
-}
-
-TEST(FullParserTest, IncompleteUint) {
- Uint val(1000);
-
- auto encoding = val.encode();
- auto [item, pos, message] = parse(encoding.data(), encoding.size() - 1);
- EXPECT_EQ(nullptr, item.get());
- EXPECT_EQ(encoding.data(), pos);
- EXPECT_EQ("Need 2 byte(s) for length field, have 1.", message);
-}
-
-TEST(FullParserTest, IncompleteString) {
- Tstr val("hello");
-
- auto encoding = val.encode();
- auto [item, pos, message] = parse(encoding.data(), encoding.size() - 2);
- EXPECT_EQ(nullptr, item.get());
- EXPECT_EQ(encoding.data(), pos);
- EXPECT_EQ("Need 5 byte(s) for text string, have 3.", message);
-}
-
-TEST(FullParserTest, ArrayWithInsufficientEntries) {
- Array val(1, 2, 3, 4);
-
- auto encoding = val.encode();
- auto [item, pos, message] = parse(encoding.data(), encoding.size() - 1);
- EXPECT_EQ(nullptr, item.get());
- EXPECT_EQ(encoding.data(), pos);
- EXPECT_EQ("Not enough entries for array.", message);
-}
-
-TEST(FullParserTest, ArrayWithTruncatedEntry) {
- Array val(1, 2, 3, 400000);
-
- auto encoding = val.encode();
- auto [item, pos, message] = parse(encoding.data(), encoding.size() - 1);
- EXPECT_EQ(nullptr, item.get());
- EXPECT_EQ(encoding.data() + encoding.size() - 5, pos);
- EXPECT_EQ("Need 4 byte(s) for length field, have 3.", message);
-}
-
-TEST(FullParserTest, MapWithTruncatedEntry) {
- Map val(1, 2, 300000, 4);
-
- auto encoding = val.encode();
- auto [item, pos, message] = parse(encoding.data(), encoding.size() - 2);
- EXPECT_EQ(nullptr, item.get());
- EXPECT_EQ(encoding.data() + 3, pos);
- EXPECT_EQ("Need 4 byte(s) for length field, have 3.", message);
-}
-int main(int argc, char** argv) {
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
diff --git a/input/common/aidl/Android.bp b/input/common/aidl/Android.bp
index 95a14b2..5aa820c 100644
--- a/input/common/aidl/Android.bp
+++ b/input/common/aidl/Android.bp
@@ -12,6 +12,7 @@
host_supported: true,
vendor_available: true,
srcs: ["android/hardware/input/common/*.aidl"],
+ frozen: true,
stability: "vintf",
backend: {
cpp: {
diff --git a/media/bufferpool/aidl/Android.bp b/media/bufferpool/aidl/Android.bp
new file mode 100644
index 0000000..68ac489
--- /dev/null
+++ b/media/bufferpool/aidl/Android.bp
@@ -0,0 +1,44 @@
+// 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"],
+}
+
+aidl_interface {
+ name: "android.hardware.media.bufferpool2",
+ vendor_available: true,
+ srcs: ["android/hardware/media/bufferpool2/*.aidl"],
+ imports: [
+ "android.hardware.common-V2",
+ "android.hardware.common.fmq-V1",
+ ],
+ stability: "vintf",
+ backend: {
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ enabled: false,
+ },
+ ndk: {
+ enabled: true,
+ },
+ },
+}
diff --git a/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/Buffer.aidl b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/Buffer.aidl
new file mode 100644
index 0000000..4ea0bba
--- /dev/null
+++ b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/Buffer.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.bufferpool2;
+@VintfStability
+parcelable Buffer {
+ int id;
+ android.hardware.common.NativeHandle buffer;
+}
diff --git a/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/BufferInvalidationMessage.aidl b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/BufferInvalidationMessage.aidl
new file mode 100644
index 0000000..181286c
--- /dev/null
+++ b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/BufferInvalidationMessage.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.media.bufferpool2;
+@FixedSize @VintfStability
+parcelable BufferInvalidationMessage {
+ int messageId;
+ int fromBufferId;
+ int toBufferId;
+}
diff --git a/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/BufferStatus.aidl b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/BufferStatus.aidl
new file mode 100644
index 0000000..13174ff
--- /dev/null
+++ b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/BufferStatus.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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.media.bufferpool2;
+@Backing(type="int") @VintfStability
+enum BufferStatus {
+ NOT_USED = 0,
+ USED = 1,
+ TRANSFER_TO = 2,
+ TRANSFER_FROM = 3,
+ TRANSFER_TIMEOUT = 4,
+ TRANSFER_LOST = 5,
+ TRANSFER_FETCH = 6,
+ TRANSFER_OK = 7,
+ TRANSFER_ERROR = 8,
+ INVALIDATION_ACK = 9,
+}
diff --git a/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/BufferStatusMessage.aidl b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/BufferStatusMessage.aidl
new file mode 100644
index 0000000..7e79a36
--- /dev/null
+++ b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/BufferStatusMessage.aidl
@@ -0,0 +1,43 @@
+/*
+ * 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.media.bufferpool2;
+@FixedSize @VintfStability
+parcelable BufferStatusMessage {
+ long transactionId;
+ int bufferId;
+ android.hardware.media.bufferpool2.BufferStatus status;
+ long connectionId;
+ long targetConnectionId;
+ long timestampUs;
+}
diff --git a/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IAccessor.aidl b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IAccessor.aidl
new file mode 100644
index 0000000..4053797
--- /dev/null
+++ b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IAccessor.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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.media.bufferpool2;
+@VintfStability
+interface IAccessor {
+ android.hardware.media.bufferpool2.IAccessor.ConnectionInfo connect(in android.hardware.media.bufferpool2.IObserver observer);
+ @VintfStability
+ parcelable ConnectionInfo {
+ android.hardware.media.bufferpool2.IConnection connection;
+ long connectionId;
+ int msgId;
+ android.hardware.common.fmq.MQDescriptor<android.hardware.media.bufferpool2.BufferStatusMessage,android.hardware.common.fmq.SynchronizedReadWrite> toFmqDesc;
+ android.hardware.common.fmq.MQDescriptor<android.hardware.media.bufferpool2.BufferInvalidationMessage,android.hardware.common.fmq.UnsynchronizedWrite> fromFmqDesc;
+ }
+}
diff --git a/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IClientManager.aidl b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IClientManager.aidl
new file mode 100644
index 0000000..54896d4
--- /dev/null
+++ b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IClientManager.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <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.media.bufferpool2;
+@VintfStability
+interface IClientManager {
+ long registerSender(in android.hardware.media.bufferpool2.IAccessor bufferPool);
+}
diff --git a/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IConnection.aidl b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IConnection.aidl
new file mode 100644
index 0000000..300fcba
--- /dev/null
+++ b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IConnection.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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.media.bufferpool2;
+@VintfStability
+interface IConnection {
+ android.hardware.media.bufferpool2.IConnection.FetchResult[] fetch(in android.hardware.media.bufferpool2.IConnection.FetchInfo[] fetchInfos);
+ parcelable FetchInfo {
+ long transactionId;
+ int bufferId;
+ }
+ union FetchResult {
+ android.hardware.media.bufferpool2.Buffer buffer;
+ android.hardware.media.bufferpool2.ResultStatus failure;
+ }
+}
diff --git a/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IObserver.aidl b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IObserver.aidl
new file mode 100644
index 0000000..2d8cffe
--- /dev/null
+++ b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IObserver.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <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.media.bufferpool2;
+@VintfStability
+interface IObserver {
+ oneway void onMessage(in long connectionId, in int msgId);
+}
diff --git a/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/ResultStatus.aidl b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/ResultStatus.aidl
new file mode 100644
index 0000000..7370998
--- /dev/null
+++ b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/ResultStatus.aidl
@@ -0,0 +1,43 @@
+/*
+ * 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.media.bufferpool2;
+@VintfStability
+parcelable ResultStatus {
+ int resultStatus;
+ const int OK = 0;
+ const int NO_MEMORY = 1;
+ const int ALREADY_EXISTS = 2;
+ const int NOT_FOUND = 3;
+ const int CRITICAL_ERROR = 4;
+}
diff --git a/media/bufferpool/aidl/android/hardware/media/bufferpool2/Buffer.aidl b/media/bufferpool/aidl/android/hardware/media/bufferpool2/Buffer.aidl
new file mode 100644
index 0000000..976f674
--- /dev/null
+++ b/media/bufferpool/aidl/android/hardware/media/bufferpool2/Buffer.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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.media.bufferpool2;
+
+import android.hardware.common.NativeHandle;
+
+/**
+ * Generic buffer for fast recycling for media/stagefright.
+ *
+ * During media pipeline buffer references are created, shared and
+ * destroyed frequently. The underlying buffers are allocated on demand
+ * by a buffer pool, and are recycled to the buffer pool when they are
+ * no longer referenced by the clients.
+ *
+ * E.g. ion or gralloc buffer
+ */
+@VintfStability
+parcelable Buffer {
+ int id;
+ NativeHandle buffer;
+}
diff --git a/media/bufferpool/aidl/android/hardware/media/bufferpool2/BufferInvalidationMessage.aidl b/media/bufferpool/aidl/android/hardware/media/bufferpool2/BufferInvalidationMessage.aidl
new file mode 100644
index 0000000..ad03cd5
--- /dev/null
+++ b/media/bufferpool/aidl/android/hardware/media/bufferpool2/BufferInvalidationMessage.aidl
@@ -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 android.hardware.media.bufferpool2;
+
+/*
+ * Buffer pool sends a buffer invalidation message to clients in order to
+ * ensure fast reclamation of the buffers. Buffer pool implementation on
+ * clients must release the invalidated buffers right away after finishing
+ * the use of buffers upon receiving a buffer invalidation message.
+ * Users cannot delay or control timing of the handling/reception of
+ * invalidation messages. Buffer pool implementation must guarantee timely
+ * handling of invalidation messages.
+ */
+@VintfStability
+@FixedSize
+parcelable BufferInvalidationMessage {
+ int messageId;
+ /**
+ * Buffers from fromBufferId to toBufferId must be invalidated.
+ * fromBufferId is inclusive, but toBufferId is not inclusive.
+ * If fromBufferId > toBufferID, wrap happens. In that case
+ * the wrap is based on UINT32_MAX.
+ */
+ int fromBufferId;
+ int toBufferId;
+}
diff --git a/media/bufferpool/aidl/android/hardware/media/bufferpool2/BufferStatus.aidl b/media/bufferpool/aidl/android/hardware/media/bufferpool2/BufferStatus.aidl
new file mode 100644
index 0000000..b63aee2
--- /dev/null
+++ b/media/bufferpool/aidl/android/hardware/media/bufferpool2/BufferStatus.aidl
@@ -0,0 +1,68 @@
+/*
+ * 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.media.bufferpool2;
+
+/**
+ * Buffer ownership status for the specified client.
+ * Buffer transfer status for the specified buffer transafer transaction.
+ * BufferStatus is posted along with BufferStatusMessage from a client to
+ * the buffer pool for synchronization after status change.
+ */
+@VintfStability
+@Backing(type="int")
+enum BufferStatus {
+ /**
+ * No longer used by the specified client.
+ */
+ NOT_USED = 0,
+ /**
+ * Buffer is acquired by the specified client.
+ */
+ USED = 1,
+ /**
+ * Buffer is sent by the specified client.
+ */
+ TRANSFER_TO = 2,
+ /**
+ * Buffer transfer is acked by the receiver client.
+ */
+ TRANSFER_FROM = 3,
+ /**
+ * Buffer transfer is timed out by receiver client.
+ */
+ TRANSFER_TIMEOUT = 4,
+ /**
+ * Buffer transfer is not acked by the receiver.
+ */
+ TRANSFER_LOST = 5,
+ /**
+ * Buffer fetch request from the client.
+ */
+ TRANSFER_FETCH = 6,
+ /**
+ * Buffer transaction succeeded.
+ */
+ TRANSFER_OK = 7,
+ /**
+ * Buffer transaction failure.
+ */
+ TRANSFER_ERROR = 8,
+ /**
+ * Buffer invalidation ack.
+ */
+ INVALIDATION_ACK = 9,
+}
diff --git a/media/bufferpool/aidl/android/hardware/media/bufferpool2/BufferStatusMessage.aidl b/media/bufferpool/aidl/android/hardware/media/bufferpool2/BufferStatusMessage.aidl
new file mode 100644
index 0000000..e3fd8f0
--- /dev/null
+++ b/media/bufferpool/aidl/android/hardware/media/bufferpool2/BufferStatusMessage.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.media.bufferpool2;
+
+import android.hardware.media.bufferpool2.BufferStatus;
+
+/**
+ * Buffer ownership status change message. This message is
+ * sent via fmq to the buffer pool from client processes.
+ */
+@VintfStability
+@FixedSize
+parcelable BufferStatusMessage {
+ /**
+ * Transaction Id = (SenderId : sender local transaction Id)
+ * Transaction Id is created from sender and posted via fmq within
+ * TRANSFER_TO message.
+ */
+ long transactionId;
+ int bufferId;
+ BufferStatus status;
+ /**
+ * Used by the buffer pool, not by client.
+ */
+ long connectionId;
+ /**
+ * Valid only when TRANSFER_TO is posted.
+ */
+ long targetConnectionId;
+ /**
+ * Used by the buffer pool, not by client.
+ * Monotonic timestamp in Us since fixed point in time as decided
+ * by the sender of the message
+ */
+ long timestampUs;
+}
diff --git a/media/bufferpool/aidl/android/hardware/media/bufferpool2/IAccessor.aidl b/media/bufferpool/aidl/android/hardware/media/bufferpool2/IAccessor.aidl
new file mode 100644
index 0000000..0fa5961
--- /dev/null
+++ b/media/bufferpool/aidl/android/hardware/media/bufferpool2/IAccessor.aidl
@@ -0,0 +1,106 @@
+/*
+ * 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.media.bufferpool2;
+
+import android.hardware.common.fmq.MQDescriptor;
+import android.hardware.common.fmq.SynchronizedReadWrite;
+import android.hardware.common.fmq.UnsynchronizedWrite;
+
+
+import android.hardware.media.bufferpool2.BufferInvalidationMessage;
+import android.hardware.media.bufferpool2.BufferStatusMessage;
+import android.hardware.media.bufferpool2.IConnection;
+import android.hardware.media.bufferpool2.IObserver;
+
+/**
+ * IAccessor creates IConnection which is used from IClientManager in order to
+ * use functionality of the specified buffer pool.
+ */
+@VintfStability
+interface IAccessor {
+ @VintfStability
+ /**
+ * Connection information between the bufferpool process and the receiver
+ * process. The information is used from the receiver process in order to
+ * receive buffers from the bufferpool process.
+ */
+ parcelable ConnectionInfo {
+ /**
+ * The interface to get shared buffers from the bufferpool.
+ */
+ IConnection connection;
+ /**
+ * The identifier for a (sender/receiver) pair during buffer transfer.
+ * This is system wide unique.
+ */
+ long connectionId;
+ /**
+ * Id of the most recent message from bufferpool. This is monotonic.
+ */
+ int msgId;
+ /**
+ * The FMQ descriptor for sending buffer status messages back to bufferpool
+ */
+ MQDescriptor<BufferStatusMessage, SynchronizedReadWrite> toFmqDesc;
+ /**
+ * The FMQ descriptor for receiving buffer invalidation messages from bufferpool
+ */
+ MQDescriptor<BufferInvalidationMessage, UnsynchronizedWrite> fromFmqDesc;
+ }
+
+ /**
+ * Registers a new client and creates IConnection to the buffer pool for
+ * the client. IConnection and FMQ are used by IClientManager in order to
+ * communicate with the buffer pool. Via FMQ IClientManager sends
+ * BufferStatusMessage(s) to the buffer pool.
+ *
+ * FMQ is used to send buffer ownership status changes to a buffer pool
+ * from a buffer pool client. A buffer pool synchronizes FMQ messages when
+ * there is an aidl request from the clients. Every client has its own
+ * connection and FMQ to communicate with the buffer pool. So sending an
+ * FMQ message on behalf of other clients is not possible.
+ *
+ * FMQ messages are sent when a buffer is acquired or released. Also, FMQ
+ * messages are sent when a buffer is transferred from a client to another
+ * client. FMQ has its own ID from a buffer pool. A client is specified
+ * with the ID.
+ *
+ * To transfer a buffer, a sender must send an FMQ message. The message
+ * must include a receiver's ID and a transaction ID. A receiver must send
+ * the transaction ID to fetch a buffer from a buffer pool. Since the
+ * sender already registered the receiver via an FMQ message, The buffer
+ * pool must verify the receiver with the transaction ID. In order to
+ * prevent faking a receiver, a connection to a buffer pool from client is
+ * made and kept private. Also part of transaction ID is a sender ID in
+ * order to prevent fake transactions from other clients. This must be
+ * verified with an FMQ message from a buffer pool.
+ *
+ * @param observer The buffer pool event observer from the client.
+ * Observer is provided to ensure FMQ messages are processed even when
+ * client processes are idle. Buffer invalidation caused by
+ * reconfiguration does not call observer. Buffer invalidation caused
+ * by termination of pipeline call observer in order to ensure
+ * invalidation is done after pipeline completion.
+ * @return ConnectionInfo The information regarding the established
+ * connection
+ * @@throws ServiceSpecificException with one of the following values:
+ * ResultStatus::NO_MEMORY - Memory allocation failure occurred.
+ * ResultStatus::ALREADY_EXISTS - A connection was already made.
+ * ResultStatus::CRITICAL_ERROR - Other errors.
+ */
+ ConnectionInfo connect(in IObserver observer);
+}
diff --git a/media/bufferpool/aidl/android/hardware/media/bufferpool2/IClientManager.aidl b/media/bufferpool/aidl/android/hardware/media/bufferpool2/IClientManager.aidl
new file mode 100644
index 0000000..bf36e25
--- /dev/null
+++ b/media/bufferpool/aidl/android/hardware/media/bufferpool2/IClientManager.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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.media.bufferpool2;
+
+import android.hardware.media.bufferpool2.IAccessor;
+
+/**
+ * IClientManager manages IConnection(s) inside a process. A locally
+ * created IConnection represents a communication node(receiver) with the
+ * specified buffer pool(IAccessor).
+ * IConnection(s) are not exposed to other processes(IClientManager).
+ * IClientManager instance must be unique within a process.
+ */
+@VintfStability
+interface IClientManager {
+ /**
+ * Sets up a buffer receiving communication node for the specified
+ * buffer pool. A manager must create a IConnection to the buffer
+ * pool if it does not already have a connection.
+ *
+ * @param bufferPool a buffer pool which is specified with the IAccessor.
+ * The specified buffer pool is the owner of received buffers.
+ * @return the Id of the communication node to the buffer pool.
+ * This id is used in FMQ to notify IAccessor that a buffer has been
+ * sent to that connection during transfers.
+ * @throws ServiceSpecificException with one of the following values:
+ * ResultStatus::NO_MEMORY - Memory allocation failure occurred.
+ * ResultStatus::ALREADY_EXISTS - A sender was registered already.
+ * ResultStatus::CRITICAL_ERROR - Other errors.
+ */
+ long registerSender(in IAccessor bufferPool);
+}
diff --git a/media/bufferpool/aidl/android/hardware/media/bufferpool2/IConnection.aidl b/media/bufferpool/aidl/android/hardware/media/bufferpool2/IConnection.aidl
new file mode 100644
index 0000000..d869f47
--- /dev/null
+++ b/media/bufferpool/aidl/android/hardware/media/bufferpool2/IConnection.aidl
@@ -0,0 +1,73 @@
+/*
+ * 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.media.bufferpool2;
+
+import android.hardware.media.bufferpool2.Buffer;
+import android.hardware.media.bufferpool2.ResultStatus;
+
+/**
+ * A connection to a buffer pool which handles requests from a buffer pool
+ * client. The connection must be made in order to receive buffers from
+ * other buffer pool clients.
+ */
+@VintfStability
+interface IConnection {
+
+ parcelable FetchInfo {
+ /**
+ * Unique transaction id for buffer transferring.
+ */
+ long transactionId;
+ /**
+ * Id of the buffer to be fetched.
+ */
+ int bufferId;
+ }
+
+ union FetchResult {
+ /**
+ * The fetched buffer on successful fetch.
+ */
+ Buffer buffer;
+ /**
+ * The reason of the request failure. Possible values are below.
+ *
+ * ResultStatus::NOT_FOUND - A buffer was not found due to invalidation.
+ * ResultStatus::CRITICAL_ERROR - Other errors.
+ */
+ ResultStatus failure;
+ }
+
+ /**
+ * Retrieves buffers using an array of FetchInfo.
+ * Each element of FetchInfo array contains a bufferId and a transactionId
+ * for each buffer to fetch. The method must be called from receiving side of buffers
+ * during transferring only when the specified buffer is neither cached nor used.
+ *
+ * The method could have partial failures, in the case other successfully fetched buffers
+ * will be in returned result along with the failures. The order of the returned result
+ * will be the same with the fetchInfos.
+ *
+ * @param fetchInfos information of buffers to fetch
+ * @return Requested buffers.
+ * If there are failures, reasons of failures are also included.
+ * @throws ServiceSpecificException with one of the following values:
+ * ResultStatus::NO_MEMORY - Memory allocation failure occurred.
+ * ResultStatus::CRITICAL_ERROR - Other errors.
+ */
+ FetchResult[] fetch(in FetchInfo[] fetchInfos);
+}
diff --git a/media/bufferpool/aidl/android/hardware/media/bufferpool2/IObserver.aidl b/media/bufferpool/aidl/android/hardware/media/bufferpool2/IObserver.aidl
new file mode 100644
index 0000000..07d1c3e
--- /dev/null
+++ b/media/bufferpool/aidl/android/hardware/media/bufferpool2/IObserver.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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.media.bufferpool2;
+
+/**
+ * IObserver listens on notifications from the buffer pool. On receiving
+ * notifications, FMQ messages from the specific buffer pool which are already
+ * in the FMQ are processed.
+ */
+@VintfStability
+interface IObserver {
+ /**
+ * The specific buffer pool sent a message to the client. Calling this
+ * method from the buffer pool enforces a buffer pool client process the
+ * message.
+ *
+ * @param connectionId the connection Id of the specific buffer pool client
+ * @param msgId Id of the most recent message
+ */
+ oneway void onMessage(in long connectionId, in int msgId);
+}
diff --git a/media/bufferpool/aidl/android/hardware/media/bufferpool2/ResultStatus.aidl b/media/bufferpool/aidl/android/hardware/media/bufferpool2/ResultStatus.aidl
new file mode 100644
index 0000000..162f9a7
--- /dev/null
+++ b/media/bufferpool/aidl/android/hardware/media/bufferpool2/ResultStatus.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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.media.bufferpool2;
+
+@VintfStability
+parcelable ResultStatus {
+ const int OK = 0;
+ const int NO_MEMORY = 1;
+ const int ALREADY_EXISTS = 2;
+ const int NOT_FOUND = 3;
+ const int CRITICAL_ERROR = 4;
+
+ int resultStatus;
+}
diff --git a/media/c2/aidl/Android.bp b/media/c2/aidl/Android.bp
new file mode 100644
index 0000000..3393ede
--- /dev/null
+++ b/media/c2/aidl/Android.bp
@@ -0,0 +1,38 @@
+// This is the expected build file, but it may not be right in all cases
+
+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"],
+}
+
+aidl_interface {
+ name: "android.hardware.media.c2",
+ vendor_available: true,
+ srcs: ["android/hardware/media/c2/*.aidl"],
+ include_dirs: [
+ "frameworks/native/aidl/gui",
+ ],
+ imports: [
+ "android.hardware.common-V2",
+ "android.hardware.media.bufferpool2-V1",
+ ],
+ stability: "vintf",
+ backend: {
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ enabled: false,
+ },
+ ndk: {
+ enabled: true,
+ additional_shared_libraries: [
+ "libnativewindow",
+ ],
+ },
+ },
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/BaseBlock.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/BaseBlock.aidl
new file mode 100644
index 0000000..460ff97
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/BaseBlock.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+union BaseBlock {
+ android.hardware.common.NativeHandle nativeBlock;
+ android.hardware.media.bufferpool2.BufferStatusMessage pooledBlock;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Block.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Block.aidl
new file mode 100644
index 0000000..7b3005e
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Block.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.media.c2;
+@VintfStability
+parcelable Block {
+ int index;
+ android.hardware.media.c2.Params meta;
+ android.hardware.common.NativeHandle fence;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Buffer.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Buffer.aidl
new file mode 100644
index 0000000..b632932
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Buffer.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable Buffer {
+ android.hardware.media.c2.Params info;
+ android.hardware.media.c2.Block[] blocks;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldDescriptor.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldDescriptor.aidl
new file mode 100644
index 0000000..d0e4cbf
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldDescriptor.aidl
@@ -0,0 +1,62 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable FieldDescriptor {
+ android.hardware.media.c2.FieldId fieldId;
+ android.hardware.media.c2.FieldDescriptor.Type type;
+ int structIndex;
+ int extent;
+ String name;
+ android.hardware.media.c2.FieldDescriptor.NamedValue[] namedValues;
+ @Backing(type="int") @VintfStability
+ enum Type {
+ NO_INIT = 0,
+ INT32 = 1,
+ UINT32 = 2,
+ CNTR32 = 3,
+ INT64 = 4,
+ UINT64 = 5,
+ CNTR64 = 6,
+ FLOAT = 7,
+ STRING = 256,
+ BLOB = 257,
+ STRUCT = 131072,
+ }
+ @VintfStability
+ parcelable NamedValue {
+ String name;
+ long value;
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldId.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldId.aidl
new file mode 100644
index 0000000..935b85d
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldId.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable FieldId {
+ int offset;
+ int sizeBytes;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValues.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValues.aidl
new file mode 100644
index 0000000..69060be
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValues.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.media.c2;
+@VintfStability
+union FieldSupportedValues {
+ boolean empty;
+ android.hardware.media.c2.ValueRange range;
+ long[] values;
+ long[] flags;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQuery.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQuery.aidl
new file mode 100644
index 0000000..22f7c84
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQuery.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable FieldSupportedValuesQuery {
+ android.hardware.media.c2.ParamField field;
+ android.hardware.media.c2.FieldSupportedValuesQuery.Type type;
+ @Backing(type="int") @VintfStability
+ enum Type {
+ POSSIBLE = 0,
+ CURRENT = 1,
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
new file mode 100644
index 0000000..187e3eb
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable FieldSupportedValuesQueryResult {
+ android.hardware.media.c2.Status status;
+ android.hardware.media.c2.FieldSupportedValues values;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FrameData.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FrameData.aidl
new file mode 100644
index 0000000..e73b05e
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FrameData.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable FrameData {
+ int flags;
+ android.hardware.media.c2.WorkOrdinal ordinal;
+ android.hardware.media.c2.Buffer[] buffers;
+ android.hardware.media.c2.Params configUpdate;
+ android.hardware.media.c2.InfoBuffer[] infoBuffers;
+ const int DROP_FRAME = 1;
+ const int END_OF_STREAM = 2;
+ const int DISCARD_FRAME = 4;
+ const int FLAG_INCOMPLETE = 8;
+ const int CODEC_CONFIG = -2147483648;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponent.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponent.aidl
new file mode 100644
index 0000000..7ed09af
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponent.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <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.media.c2;
+@VintfStability
+interface IComponent {
+ android.hardware.common.NativeHandle configureVideoTunnel(in int avSyncHwId);
+ android.hardware.media.c2.IComponent.BlockPool createBlockPool(in int allocatorId);
+ void destroyBlockPool(in long blockPoolId);
+ void drain(in boolean withEos);
+ android.hardware.media.c2.WorkBundle flush();
+ android.hardware.media.c2.IComponentInterface getInterface();
+ void queue(in android.hardware.media.c2.WorkBundle workBundle);
+ void release();
+ void reset();
+ void setOutputSurface(in long blockPoolId, in android.view.Surface surface, in android.hardware.media.c2.SurfaceSyncObj syncObject);
+ void start();
+ void stop();
+ parcelable BlockPool {
+ long blockPoolId;
+ android.hardware.media.c2.IConfigurable configurable;
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentInterface.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentInterface.aidl
new file mode 100644
index 0000000..2350dae
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentInterface.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <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.media.c2;
+@VintfStability
+interface IComponentInterface {
+ android.hardware.media.c2.IConfigurable getConfigurable();
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentListener.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentListener.aidl
new file mode 100644
index 0000000..f6f2a63
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentListener.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <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.media.c2;
+@VintfStability
+interface IComponentListener {
+ oneway void onError(in android.hardware.media.c2.Status status, in int errorCode);
+ oneway void onFramesRendered(in android.hardware.media.c2.IComponentListener.RenderedFrame[] renderedFrames);
+ oneway void onInputBuffersReleased(in android.hardware.media.c2.IComponentListener.InputBuffer[] inputBuffers);
+ oneway void onTripped(in android.hardware.media.c2.SettingResult[] settingResults);
+ oneway void onWorkDone(in android.hardware.media.c2.WorkBundle workBundle);
+ @VintfStability
+ parcelable InputBuffer {
+ long frameIndex;
+ int arrayIndex;
+ }
+ @VintfStability
+ parcelable RenderedFrame {
+ long bufferQueueId;
+ int slotId;
+ long timestampNs;
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentStore.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentStore.aidl
new file mode 100644
index 0000000..35532be
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentStore.aidl
@@ -0,0 +1,66 @@
+/*
+ * 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.media.c2;
+@VintfStability
+interface IComponentStore {
+ void copyBuffer(in android.hardware.media.c2.Buffer src, in android.hardware.media.c2.Buffer dst);
+ android.hardware.media.c2.IComponent createComponent(in String name, in android.hardware.media.c2.IComponentListener listener, in android.hardware.media.bufferpool2.IClientManager pool);
+ android.hardware.media.c2.IComponentInterface createInterface(in String name);
+ android.hardware.media.c2.IConfigurable getConfigurable();
+ android.hardware.media.bufferpool2.IClientManager getPoolClientManager();
+ android.hardware.media.c2.StructDescriptor[] getStructDescriptors(in int[] indices);
+ android.hardware.media.c2.IComponentStore.ComponentTraits[] listComponents();
+ @VintfStability
+ parcelable ComponentTraits {
+ String name;
+ android.hardware.media.c2.IComponentStore.ComponentTraits.Domain domain;
+ android.hardware.media.c2.IComponentStore.ComponentTraits.Kind kind;
+ int rank;
+ String mediaType;
+ String[] aliases;
+ @Backing(type="int") @VintfStability
+ enum Kind {
+ OTHER = 0,
+ DECODER = 1,
+ ENCODER = 2,
+ }
+ @Backing(type="int") @VintfStability
+ enum Domain {
+ OTHER = 0,
+ VIDEO = 1,
+ AUDIO = 2,
+ IMAGE = 3,
+ }
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IConfigurable.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IConfigurable.aidl
new file mode 100644
index 0000000..32f5abd
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IConfigurable.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <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.media.c2;
+@VintfStability
+interface IConfigurable {
+ android.hardware.media.c2.IConfigurable.ConfigResult config(in android.hardware.media.c2.Params inParams, in boolean mayBlock);
+ int getId();
+ String getName();
+ android.hardware.media.c2.Params query(in int[] indices, in boolean mayBlock);
+ android.hardware.media.c2.ParamDescriptor[] querySupportedParams(in int start, in int count);
+ android.hardware.media.c2.FieldSupportedValuesQueryResult[] querySupportedValues(in android.hardware.media.c2.FieldSupportedValuesQuery[] inFields, in boolean mayBlock);
+ @VintfStability
+ parcelable ConfigResult {
+ android.hardware.media.c2.Params params;
+ android.hardware.media.c2.SettingResult[] failures;
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/InfoBuffer.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/InfoBuffer.aidl
new file mode 100644
index 0000000..94cd77d
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/InfoBuffer.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable InfoBuffer {
+ int index;
+ android.hardware.media.c2.Buffer buffer;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamDescriptor.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamDescriptor.aidl
new file mode 100644
index 0000000..04c869c
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamDescriptor.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <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.media.c2;
+@VintfStability
+parcelable ParamDescriptor {
+ int index;
+ int attrib;
+ String name;
+ int[] dependencies;
+ const int ATTRIBUTE_REQUIRED = 1;
+ const int ATTRIBUTE_PERSISTENT = 2;
+ const int ATTRIBUTE_STRICT = 4;
+ const int ATTRIBUTE_READ_ONLY = 8;
+ const int ATTRIBUTE_HIDDEN = 16;
+ const int ATTRIBUTE_INTERNAL = 32;
+ const int ATTRIBUTE_CONST = 64;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamField.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamField.aidl
new file mode 100644
index 0000000..13d2522
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamField.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable ParamField {
+ int index;
+ android.hardware.media.c2.FieldId fieldId;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamFieldValues.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamFieldValues.aidl
new file mode 100644
index 0000000..5a2821c
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamFieldValues.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable ParamFieldValues {
+ android.hardware.media.c2.ParamField paramOrField;
+ android.hardware.media.c2.FieldSupportedValues[] values;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Params.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Params.aidl
new file mode 100644
index 0000000..7d363c0
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Params.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <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.media.c2;
+@VintfStability
+parcelable Params {
+ byte[] params;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/SettingResult.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/SettingResult.aidl
new file mode 100644
index 0000000..f9e6a93
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/SettingResult.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <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.media.c2;
+@VintfStability
+parcelable SettingResult {
+ android.hardware.media.c2.SettingResult.Failure failure;
+ android.hardware.media.c2.ParamFieldValues field;
+ android.hardware.media.c2.ParamFieldValues[] conflicts;
+ @Backing(type="int") @VintfStability
+ enum Failure {
+ BAD_TYPE = 0,
+ BAD_PORT = 1,
+ BAD_INDEX = 2,
+ READ_ONLY = 3,
+ MISMATCH = 4,
+ BAD_VALUE = 5,
+ CONFLICT = 6,
+ UNSUPPORTED = 7,
+ INFO_BAD_VALUE = 8,
+ INFO_CONFLICT = 9,
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Status.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Status.aidl
new file mode 100644
index 0000000..ad07677
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Status.aidl
@@ -0,0 +1,52 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable Status {
+ int status;
+ const int OK = 0;
+ const int BAD_VALUE = -22;
+ const int BAD_INDEX = -75;
+ const int CANNOT_DO = -2147483646;
+ const int DUPLICATE = -17;
+ const int NOT_FOUND = -2;
+ const int BAD_STATE = -38;
+ const int BLOCKING = -9930;
+ const int NO_MEMORY = -12;
+ const int REFUSED = -1;
+ const int TIMED_OUT = -110;
+ const int OMITTED = -74;
+ const int CORRUPTED = -2147483648;
+ const int NO_INIT = -19;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/StructDescriptor.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/StructDescriptor.aidl
new file mode 100644
index 0000000..58268e0
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/StructDescriptor.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable StructDescriptor {
+ int type;
+ android.hardware.media.c2.FieldDescriptor[] fields;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/SurfaceSyncObj.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/SurfaceSyncObj.aidl
new file mode 100644
index 0000000..1c9bf8d
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/SurfaceSyncObj.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable SurfaceSyncObj {
+ android.hardware.common.NativeHandle syncMemory;
+ long bqId;
+ int generationId;
+ long consumerUsage;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ValueRange.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ValueRange.aidl
new file mode 100644
index 0000000..db71ce0
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ValueRange.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable ValueRange {
+ long min;
+ long max;
+ long step;
+ long num;
+ long denom;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Work.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Work.aidl
new file mode 100644
index 0000000..a534348
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Work.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable Work {
+ byte[] chainInfo;
+ android.hardware.media.c2.FrameData input;
+ android.hardware.media.c2.Worklet[] worklets;
+ int workletsProcessed;
+ android.hardware.media.c2.Status result;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkBundle.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkBundle.aidl
new file mode 100644
index 0000000..84708a8
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkBundle.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable WorkBundle {
+ android.hardware.media.c2.Work[] works;
+ android.hardware.media.c2.BaseBlock[] baseBlocks;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkOrdinal.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkOrdinal.aidl
new file mode 100644
index 0000000..2833df3
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkOrdinal.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.media.c2;
+@VintfStability
+parcelable WorkOrdinal {
+ long timestampUs;
+ long frameIndex;
+ long customOrdinal;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Worklet.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Worklet.aidl
new file mode 100644
index 0000000..a79abf2
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Worklet.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable Worklet {
+ int componentId;
+ byte[] tunings;
+ android.hardware.media.c2.SettingResult[] failures;
+ android.hardware.media.c2.FrameData output;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/BaseBlock.aidl b/media/c2/aidl/android/hardware/media/c2/BaseBlock.aidl
new file mode 100644
index 0000000..8b8b8e0
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/BaseBlock.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.media.c2;
+
+import android.hardware.common.NativeHandle;
+
+/**
+ * Storage type for `BaseBlock`.
+ *
+ * A `BaseBlock` is a representation of a codec memory block. Coded data,
+ * decoded data, codec-specific data, and other codec-related data are all sent
+ * in the form of BaseBlocks.
+ */
+@VintfStability
+union BaseBlock {
+ /**
+ * #nativeBlock is the opaque representation of a buffer.
+ */
+ NativeHandle nativeBlock;
+ /**
+ * #pooledBlock is a reference to a buffer handled by a BufferPool.
+ */
+ android.hardware.media.bufferpool2.BufferStatusMessage pooledBlock;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/Block.aidl b/media/c2/aidl/android/hardware/media/c2/Block.aidl
new file mode 100644
index 0000000..34aa7b1
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/Block.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.common.NativeHandle;
+import android.hardware.media.c2.Params;
+
+/**
+ * Reference to a @ref BaseBlock within a @ref WorkBundle.
+ *
+ * `Block` contains additional attributes that `BaseBlock` does not. These
+ * attributes may differ among `Block` objects that refer to the same
+ * `BaseBlock` in the same `WorkBundle`.
+ */
+@VintfStability
+parcelable Block {
+ /**
+ * Identity of a `BaseBlock` within a `WorkBundle`. This is an index into
+ * #WorkBundle.baseBlocks.
+ */
+ int index;
+ /**
+ * Metadata associated with this `Block`.
+ */
+ Params meta;
+ /**
+ * Fence for synchronizing `Block` access.
+ */
+ NativeHandle fence;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/Buffer.aidl b/media/c2/aidl/android/hardware/media/c2/Buffer.aidl
new file mode 100644
index 0000000..d2dcf2d
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/Buffer.aidl
@@ -0,0 +1,37 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.Block;
+import android.hardware.media.c2.Params;
+
+/**
+ * A codec buffer, which is a collection of @ref Block objects and metadata.
+ *
+ * This is a part of @ref FrameData.
+ */
+@VintfStability
+parcelable Buffer {
+ /**
+ * Metadata associated with the buffer.
+ */
+ Params info;
+ /**
+ * Blocks contained in the buffer.
+ */
+ Block[] blocks;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/FieldDescriptor.aidl b/media/c2/aidl/android/hardware/media/c2/FieldDescriptor.aidl
new file mode 100644
index 0000000..a2774ec
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/FieldDescriptor.aidl
@@ -0,0 +1,103 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.FieldId;
+
+/**
+ * Description of a field inside a C2Param structure.
+ */
+@VintfStability
+parcelable FieldDescriptor {
+ /**
+ * Possible types of the field.
+ */
+ @VintfStability
+ @Backing(type="int")
+ enum Type {
+ NO_INIT = 0,
+ INT32,
+ UINT32,
+ CNTR32,
+ INT64,
+ UINT64,
+ CNTR64,
+ FLOAT,
+ /**
+ * Fixed-size string (POD).
+ */
+ STRING = 0x100,
+ /**
+ * A blob has no sub-elements and can be thought of as an array of
+ * bytes. However, bytes cannot be individually addressed by clients.
+ */
+ BLOB,
+ /**
+ * The field is a structure that may contain other fields.
+ */
+ STRUCT = 0x20000,
+ }
+ /**
+ * Named value type. This is used for defining an enum value for a numeric
+ * type.
+ */
+ @VintfStability
+ parcelable NamedValue {
+ /**
+ * Name of the enum value. This must be unique for each enum value in
+ * the same field.
+ */
+ String name;
+ /**
+ * Underlying value of the enum value. Multiple enum names may have the
+ * same underlying value.
+ */
+ long value;
+ }
+ /**
+ * Location of the field in the C2Param structure
+ */
+ FieldId fieldId;
+ /**
+ * Type of the field.
+ */
+ Type type;
+ /**
+ * If #type is #Type.STRUCT, #structIndex is the C2Param structure index;
+ * otherwise, #structIndex is not used.
+ */
+ int structIndex;
+ /**
+ * Extent of the field.
+ * - For a non-array field, #extent is 1.
+ * - For a fixed-length array field, #extent is the length. An array field
+ * of length 1 is indistinguishable from a non-array field.
+ * - For a variable-length array field, #extent is 0. This can only occur as
+ * the last member of a C2Param structure.
+ */
+ int extent;
+ /**
+ * Name of the field. This must be unique for each field in the same
+ * structure.
+ */
+ String name;
+ /**
+ * List of enum values. This is not used when #type is not one of the
+ * numeric types.
+ */
+ NamedValue[] namedValues;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/FieldId.aidl b/media/c2/aidl/android/hardware/media/c2/FieldId.aidl
new file mode 100644
index 0000000..68bf058
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/FieldId.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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.media.c2;
+
+/**
+ * Identifying information of a field relative to a known C2Param structure.
+ *
+ * Within a given C2Param structure, each field is uniquely identified by @ref
+ * FieldId.
+ */
+@VintfStability
+parcelable FieldId {
+ /**
+ * Offset of the field in bytes.
+ */
+ int offset;
+ /**
+ * Size of the field in bytes.
+ */
+ int sizeBytes;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/FieldSupportedValues.aidl b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValues.aidl
new file mode 100644
index 0000000..6c2033b
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValues.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.
+ */
+
+package android.hardware.media.c2;
+
+import android.hardware.media.c2.ValueRange;
+
+/*
+ * Description of supported values for a field of C2Param.
+ *
+ * This can be a continuous range or a discrete set of values.
+ *
+ * The intended type of values must be made clear in the context where
+ * `FieldSupportedValues` is used.
+ */
+@VintfStability
+union FieldSupportedValues {
+ /**
+ * No supported values
+ */
+ boolean empty;
+ /**
+ * Numeric range, described in a #ValueRange structure
+ */
+ ValueRange range;
+ /**
+ * List of values
+ */
+ long[] values;
+ /**
+ * List of flags that can be OR-ed.
+ *
+ * The list contains { min-mask, flag1, flag2... }. Basically, the first
+ * value is the required set of flags to be set, and the rest of the values are flags that can
+ * be set independently. FLAGS is only supported for integral types. Supported flags should
+ * not overlap, as it can make validation non-deterministic. The standard validation method
+ * is that starting from the original value, if each flag is removed when fully present (the
+ * min-mask must be fully present), we shall arrive at 0.
+ */
+ long[] flags;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQuery.aidl b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQuery.aidl
new file mode 100644
index 0000000..bdaaef6
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQuery.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.ParamField;
+
+/**
+ * Query information for supported values of a field. This is used as input to
+ * IConfigurable::querySupportedValues().
+ */
+@VintfStability
+parcelable FieldSupportedValuesQuery {
+ @VintfStability
+ @Backing(type="int")
+ enum Type {
+ /**
+ * Query all possible values regardless of other settings.
+ */
+ POSSIBLE = 0,
+ /**
+ * Query currently possible values given dependent settings.
+ */
+ CURRENT,
+ }
+ /**
+ * Identity of the field to query.
+ */
+ ParamField field;
+ /**
+ * Type of the query. See #Type for more information.
+ */
+ Type type;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
new file mode 100644
index 0000000..b5c28c6
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.FieldSupportedValues;
+import android.hardware.media.c2.Status;
+
+/**
+ * This structure is used to hold the result from
+ * IConfigurable::querySupportedValues().
+ */
+@VintfStability
+parcelable FieldSupportedValuesQueryResult {
+ /**
+ * Result of the query. Possible values are
+ * - `Status::OK`: The query was successful.
+ * - `Status::BAD_STATE`: The query was requested when the `IConfigurable` instance
+ * was in a bad state.
+ * - `Status::BAD_INDEX`: The requested field was not recognized.
+ * - `Status::TIMED_OUT`: The query could not be completed in a timely manner.
+ * - `Status::BLOCKING`: The query must block, but the parameter `mayBlock` in the
+ * call to `querySupportedValues()` was `false`.
+ * - `Status::CORRUPTED`: Some unknown error occurred.
+ */
+ Status status;
+ /**
+ * Supported values. This is meaningful only when #status is `OK`.
+ */
+ FieldSupportedValues values;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/FrameData.aidl b/media/c2/aidl/android/hardware/media/c2/FrameData.aidl
new file mode 100644
index 0000000..15c1b6d
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/FrameData.aidl
@@ -0,0 +1,97 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.Buffer;
+import android.hardware.media.c2.InfoBuffer;
+import android.hardware.media.c2.Params;
+import android.hardware.media.c2.WorkOrdinal;
+
+/**
+ * Data for an input frame or an output frame.
+ *
+ * This structure represents a @e frame with its metadata. A @e frame consists
+ * of an ordered set of buffers, configuration changes, and info buffers along
+ * with some non-configuration metadata.
+ *
+ * @note `FrameData` is the HIDL counterpart of `C2FrameData` in the Codec 2.0
+ * standard.
+ */
+@VintfStability
+parcelable FrameData {
+ /** List of frame flags */
+ /**
+ * For input frames: no output frame shall be generated when processing
+ * this frame, but metadata must still be processed.
+ *
+ * For output frames: this frame must be discarded but metadata is still
+ * valid.
+ */
+ const int DROP_FRAME = (1 << 0);
+ /**
+ * This frame is the last frame of the current stream. Further frames
+ * are part of a new stream.
+ */
+ const int END_OF_STREAM = (1 << 1);
+ /**
+ * This frame must be discarded with its metadata.
+ *
+ * This flag is only set by components, e.g. as a response to the flush
+ * command.
+ */
+ const int DISCARD_FRAME = (1 << 2);
+ /**
+ * This frame is not the last frame produced for the input.
+ *
+ * This flag is normally set by the component - e.g. when an input frame
+ * results in multiple output frames, this flag is set on all but the
+ * last output frame.
+ *
+ * Also, when components are chained, this flag should be propagated
+ * down the work chain. That is, if set on an earlier frame of a
+ * work-chain, it should be propagated to all later frames in that
+ * chain. Additionally, components down the chain could set this flag
+ * even if not set earlier, e.g. if multiple output frames are generated
+ * at that component for the input frame.
+ */
+ const int FLAG_INCOMPLETE = (1 << 3);
+ /**
+ * This frame contains only codec-specific configuration data, and no
+ * actual access unit.
+ */
+ const int CODEC_CONFIG = (1 << 31);
+ /**
+ * Frame flags, as described above.
+ */
+ int flags;
+ /**
+ * @ref WorkOrdinal of the frame.
+ */
+ WorkOrdinal ordinal;
+ /**
+ * List of frame buffers.
+ */
+ Buffer[] buffers;
+ /**
+ * List of configuration updates.
+ */
+ Params configUpdate;
+ /**
+ * List of info buffers.
+ */
+ InfoBuffer[] infoBuffers;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/IComponent.aidl b/media/c2/aidl/android/hardware/media/c2/IComponent.aidl
new file mode 100644
index 0000000..b3390c3
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/IComponent.aidl
@@ -0,0 +1,304 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.common.NativeHandle;
+import android.view.Surface;
+
+import android.hardware.media.c2.IComponentInterface;
+import android.hardware.media.c2.IConfigurable;
+import android.hardware.media.c2.WorkBundle;
+import android.hardware.media.c2.SurfaceSyncObj;
+
+/**
+ * Interface for an AIDL Codec2 component.
+ * Components have two states: stopped and running. The running state has three
+ * sub-states: executing, tripped and error.
+ *
+ * All methods in `IComponent` must not block. If a method call cannot be
+ * completed in a timely manner, it must throw `Status::TIMED_OUT`.
+ */
+@VintfStability
+interface IComponent {
+ /**
+ * The reference object from framwork to HAL C2BlockPool.
+ *
+ * The object will be returned when C2BlockPool is created by a framework
+ * request. The object also can be destroyed using blockPoolId.
+ * Using configurable framework can query/config the object in HAL(IComponent).
+ */
+ parcelable BlockPool {
+ long blockPoolId;
+ IConfigurable configurable;
+ }
+ /**
+ * Configures a component for a tunneled playback mode.
+ *
+ * A successful call to this method puts the component in the *tunneled*
+ * mode. In this mode, the output `Worklet`s returned in
+ * IComponentListener::onWorkDone() may not contain any buffers. The output
+ * buffers are passed directly to the consumer end of a buffer queue whose
+ * producer side is configured with the returned @p sidebandStream passed
+ * to IGraphicBufferProducer::setSidebandStream().
+ *
+ * The component is initially in the non-tunneled mode by default. The
+ * tunneled mode can be toggled on only before the component starts
+ * processing. Once the component is put into the tunneled mode, it shall
+ * stay in the tunneled mode until and only until reset() is called.
+ *
+ * @param avSyncHwId A resource ID for hardware sync. The generator of sync
+ * IDs must ensure that this number is unique among all services at any
+ * given time. For example, if both the audio HAL and the tuner HAL
+ * support this feature, sync IDs from the audio HAL must not clash
+ * with sync IDs from the tuner HAL.
+ * @return Codec-allocated sideband stream NativeHandle. This can
+ * be passed to IGraphicBufferProducer::setSidebandStream() to
+ * establish a direct channel to the consumer.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::OMITTED` - The component does not support video tunneling.
+ * - `Status::BAD_STATE` - The component is already running.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ NativeHandle configureVideoTunnel(in int avSyncHwId);
+
+ /**
+ * Creates a local `C2BlockPool` backed by the given allocator and returns
+ * its id.
+ *
+ * The returned @p blockPoolId is the only way the client can refer to a
+ * `C2BlockPool` object in the component. The id can be passed to
+ * setOutputSurface() or used in some C2Param objects later.
+ *
+ * The created `C2BlockPool` object can be destroyed by calling
+ * destroyBlockPool(), reset() or release(). reset() and release() must
+ * destroy all `C2BlockPool` objects that have been created.
+ *
+ * @param allocatorId Id of a `C2Allocator`.
+ * @param out configurable Configuration interface for the created pool. This
+ * must not be null.
+ * @return Created block pool information. This could be used to config/query and
+ * also be used in setOutputSurface() if the allocator
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::NO_MEMORY` - Not enough memory to create the pool.
+ * - `Status::BAD_VALUE` - @p allocatorId is not recognized.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ BlockPool createBlockPool(in int allocatorId);
+
+ /**
+ * Destroys a local block pool previously created by createBlockPool().
+ *
+ * @param blockPoolId Id of a `C2BlockPool` that was previously returned by
+ * createBlockPool().
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::NOT_FOUND` - The supplied blockPoolId is not valid.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ void destroyBlockPool(in long blockPoolId);
+
+ /**
+ * Drains the component, and optionally downstream components. This is a
+ * signalling method; as such it does not wait for any work completion.
+ *
+ * The last `Work` item is marked as "drain-till-here", so the component is
+ * notified not to wait for further `Work` before it processes what is
+ * already queued. This method can also be used to set the end-of-stream
+ * flag after `Work` has been queued. Client can continue to queue further
+ * `Work` immediately after this method returns.
+ *
+ * This method must be supported in running (including tripped) states.
+ *
+ * `Work` that is completed must be returned via
+ * IComponentListener::onWorkDone().
+ *
+ * @param withEos Whether to drain the component with marking end-of-stream.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ void drain(in boolean withEos);
+
+ /**
+ * Discards and abandons any pending `Work` items for the component.
+ *
+ * This method must be supported in running (including tripped) states.
+ *
+ * `Work` that could be immediately abandoned/discarded must be returned in
+ * @p flushedWorkBundle. The order in which queued `Work` items are
+ * discarded can be arbitrary.
+ *
+ * `Work` that could not be abandoned or discarded immediately must be
+ * marked to be discarded at the earliest opportunity, and must be returned
+ * via IComponentListener::onWorkDone(). This must be completed within
+ * 500ms.
+ *
+ * @return `WorkBundle` object containing flushed `Work` items.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ WorkBundle flush();
+
+ /**
+ * Returns the @ref IComponentInterface instance associated to this
+ * component.
+ *
+ * An @ref IConfigurable instance for the component can be obtained by calling
+ * IComponentInterface::getConfigurable() on the returned @p intf.
+ *
+ * @return `IComponentInterface` instance. This must not be null.
+ */
+ IComponentInterface getInterface();
+
+ /**
+ * Queues up work for the component.
+ *
+ * This method must be supported in running (including tripped) states.
+ *
+ * It is acceptable for this method to return `OK` and return an error value
+ * using the IComponentListener::onWorkDone() callback.
+ *
+ * @param workBundle `WorkBundle` object containing a list of `Work` objects
+ * to queue to the component.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::BAD_INDEX` - Some component id in some `Worklet` is not valid.
+ * - `Status::CANNOT_DO` - The components are not tunneled but some `Work` object
+ * contains tunneling information.
+ * - `Status::NO_MEMORY` - Not enough memory to queue @p workBundle.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ void queue(in WorkBundle workBundle);
+
+ /**
+ * Releases the component.
+ *
+ * This method must be supported in stopped state.
+ *
+ * This method destroys the component. Upon return, if @p status is `OK` or
+ * `DUPLICATE`, all resources must have been released.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::BAD_STATE` - The component is running.
+ * - `Status::DUPLICATE` - The component is already released.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ void release();
+
+ /**
+ * Resets the component.
+ *
+ * This method must be supported in all (including tripped) states other
+ * than released.
+ *
+ * This method must be supported during any other blocking call.
+ *
+ * This method must return within 500ms.
+ *
+ * When this call returns, if @p status is `OK`, all `Work` items must
+ * have been abandoned, and all resources (including `C2BlockPool` objects
+ * previously created by createBlockPool()) must have been released.
+ *
+ * If the return value is `BAD_STATE` or `DUPLICATE`, no state change is
+ * expected as a response to this call. For all other return values, the
+ * component must be in the stopped state.
+ *
+ * This brings settings back to their default, "guaranteeing" no tripped
+ * state.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::BAD_STATE` - Component is in released state.
+ * - `Status::DUPLICATE` - When called during another reset call from another
+ * thread.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ void reset();
+
+ /**
+ * Starts using a surface for output with a synchronization object
+ *
+ * This method must not block.
+ *
+ * @param blockPoolId Id of the `C2BlockPool` to be associated with the
+ * output surface.
+ * @param surface Output surface.
+ * @param syncObject synchronization object for buffer allocation between
+ * Framework and Component.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::CANNOT_DO` - The component does not support an output surface.
+ * - `Status::REFUSED` - The output surface cannot be accessed.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ void setOutputSurface(in long blockPoolId, in Surface surface,
+ in SurfaceSyncObj syncObject);
+
+ /**
+ * Starts the component.
+ *
+ * This method must be supported in stopped state as well as tripped state.
+ *
+ * If the return value is `OK`, the component must be in the running state.
+ * If the return value is `BAD_STATE` or `DUPLICATE`, no state change is
+ * expected as a response to this call. Otherwise, the component must be in
+ * the stopped state.
+ *
+ * If a component is in the tripped state and start() is called while the
+ * component configuration still results in a trip, start() must succeed and
+ * a new onTripped() callback must be used to communicate the configuration
+ * conflict that results in the new trip.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::BAD_STATE` - Component is not in stopped or tripped state.
+ * - `Status::DUPLICATE` - When called during another start call from another
+ * thread.
+ * - `Status::NO_MEMORY` - Not enough memory to start the component.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ void start();
+
+ /**
+ * Stops the component.
+ *
+ * This method must be supported in running (including tripped) state.
+ *
+ * This method must return within 500ms.
+ *
+ * Upon this call, all pending `Work` must be abandoned.
+ *
+ * If the return value is `BAD_STATE` or `DUPLICATE`, no state change is
+ * expected as a response to this call. For all other return values, the
+ * component must be in the stopped state.
+ *
+ * This does not alter any settings and tunings that may have resulted in a
+ * tripped state.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::BAD_STATE` - Component is not in running state.
+ * - `Status::DUPLICATE` - When called during another stop call from another
+ * thread.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ void stop();
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/IComponentInterface.aidl b/media/c2/aidl/android/hardware/media/c2/IComponentInterface.aidl
new file mode 100644
index 0000000..9db81e6
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/IComponentInterface.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.media.c2;
+
+import android.hardware.media.c2.IConfigurable;
+
+/**
+ * Component interface object. This object contains all of the configurations of
+ * a potential or actual component. It can be created and used independently of
+ * an actual Codec2 component to query supported parameters for various
+ * component settings, and configurations for a potential component.
+ *
+ * An actual component exposes this interface via IComponent::getInterface().
+ */
+@VintfStability
+interface IComponentInterface {
+ /**
+ * Returns the @ref IConfigurable instance associated to this component
+ * interface.
+ *
+ * @return `IConfigurable` instance. This must not be null.
+ */
+ IConfigurable getConfigurable();
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/IComponentListener.aidl b/media/c2/aidl/android/hardware/media/c2/IComponentListener.aidl
new file mode 100644
index 0000000..75500b7
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/IComponentListener.aidl
@@ -0,0 +1,131 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.SettingResult;
+import android.hardware.media.c2.Status;
+import android.hardware.media.c2.WorkBundle;
+
+/**
+ * Callback interface for handling notifications from @ref IComponent.
+ */
+@VintfStability
+oneway interface IComponentListener {
+ /**
+ * Identifying information for an input buffer previously queued to the
+ * component via IComponent::queue().
+ */
+ @VintfStability
+ parcelable InputBuffer {
+ /**
+ * This value comes from `Work::input.ordinal.frameIndex` in a `Work`
+ * object that was previously queued.
+ */
+ long frameIndex;
+ /**
+ * This value is an index into `Work::input.buffers` (which is an array)
+ * in a `Work` object that was previously queued.
+ */
+ int arrayIndex;
+ }
+ /**
+ * Information about rendering of a frame to a `Surface`.
+ */
+ @VintfStability
+ parcelable RenderedFrame {
+ /**
+ * Id of the `BufferQueue` containing the rendered buffer.
+ *
+ * This value must have been obtained by an earlier call to
+ * IGraphicBufferProducer::getUniqueId().
+ */
+ long bufferQueueId;
+ /**
+ * Id of the slot of the rendered buffer.
+ *
+ * This value must have been obtained by an earlier call to
+ * IGraphicBufferProducer::dequeueBuffer() or
+ * IGraphicBufferProducer::attachBuffer().
+ */
+ int slotId;
+ /**
+ * Timestamp the rendering happened.
+ *
+ * The reference point for the timestamp is determined by the
+ * `BufferQueue` that performed the rendering.
+ */
+ long timestampNs;
+ }
+ /**
+ * Notify the listener of an error.
+ *
+ * @param status Error type. @p status may be `OK`, which means that an
+ * error has occurred, but the error type does not fit into the type
+ * `Status`. In this case, additional information is provided by
+ * @p errorCode.
+ * @param errorCode Additional error information. The framework may not
+ * recognize the meaning of this value.
+ */
+ void onError(in Status status, in int errorCode);
+
+ /**
+ * Notify the listener that frames have been rendered.
+ *
+ * @param renderedFrames List of @ref RenderedFrame objects.
+ */
+ void onFramesRendered(in RenderedFrame[] renderedFrames);
+
+ /**
+ * Notify the listener that some input buffers are no longer needed by the
+ * component, and hence can be released or reused by the client.
+ *
+ * Input buffers that are contained in a `Work` object returned by an
+ * earlier onWorkDone() call are assumed released, so they must not appear
+ * in any onInputBuffersReleased() calls. That means
+ * onInputBuffersReleased() must only report input buffers that are released
+ * before the output in the same `Work` item is produced. However, it is
+ * possible for an input buffer to be returned by onWorkDone() after it has
+ * been reported by onInputBuffersReleased().
+ *
+ * @note onWorkDone() and onInputBuffersReleased() both notify the client
+ * that input buffers are no longer needed. However, in order to minimize
+ * IPC calls, onInputBuffersReleased() should be called only when
+ * onWorkDone() cannot be called, e.g., the component needs more input
+ * before an output can be produced.
+ *
+ * @param inputBuffers List of `InputBuffer` objects, identifying input
+ * buffers that are no longer needed by the component.
+ */
+ void onInputBuffersReleased(in InputBuffer[] inputBuffers);
+
+ /**
+ * Notify the listener that the component is tripped.
+ *
+ * @param settingResults List of failures.
+ */
+ void onTripped(in SettingResult[] settingResults);
+
+ /**
+ * Notify the listener that some `Work` items have been completed.
+ *
+ * All the input buffers in the returned `Work` objects must not be used by
+ * the component after onWorkDone() is called.
+ *
+ * @param workBundle List of completed `Work` objects.
+ */
+ void onWorkDone(in WorkBundle workBundle);
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/IComponentStore.aidl b/media/c2/aidl/android/hardware/media/c2/IComponentStore.aidl
new file mode 100644
index 0000000..1435a7e
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/IComponentStore.aidl
@@ -0,0 +1,185 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.Buffer;
+import android.hardware.media.c2.IComponent;
+import android.hardware.media.c2.IComponentInterface;
+import android.hardware.media.c2.IComponentListener;
+import android.hardware.media.c2.IConfigurable;
+import android.hardware.media.c2.StructDescriptor;
+
+/**
+ * Entry point for Codec2 HAL.
+ *
+ * All methods in `IComponentStore` must not block. If a method call cannot be
+ * completed in a timely manner, it must throw `Status::TIMED_OUT`. The only
+ * exceptions are getPoolClientManager() and getConfigurable(), which must
+ * always return immediately.
+ *
+ * @note This is an extension of version 1.1 of `IComponentStore`. The purpose
+ * of the extension is to add support for blocking output buffer allocator.
+ */
+@VintfStability
+interface IComponentStore {
+ /**
+ * Component traits.
+ */
+ @VintfStability
+ parcelable ComponentTraits {
+ @VintfStability
+ @Backing(type="int")
+ enum Kind {
+ OTHER = 0,
+ DECODER,
+ ENCODER,
+ }
+ @VintfStability
+ @Backing(type="int")
+ enum Domain {
+ OTHER = 0,
+ VIDEO,
+ AUDIO,
+ IMAGE,
+ }
+ /**
+ * Name of the component. This must be unique for each component.
+ *
+ * This name is use to identify the component to create in
+ * createComponent() and createComponentInterface().
+ */
+ String name;
+ /**
+ * Component domain.
+ */
+ Domain domain;
+ /**
+ * Component kind.
+ */
+ Kind kind;
+ /**
+ * Rank used by `MediaCodecList` to determine component ordering. Lower
+ * value means higher priority.
+ */
+ int rank;
+ /**
+ * MIME type.
+ */
+ String mediaType;
+ /**
+ * Aliases for component name for backward compatibility.
+ *
+ * Multiple components can have the same alias (but not the same
+ * component name) as long as their media types differ.
+ */
+ String[] aliases;
+ }
+
+ /**
+ * Copies the contents of @p src into @p dst without changing the format of
+ * @p dst.
+ *
+ * @param src Source buffer.
+ * @param dst Destination buffer.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::CANNOT_DO` - @p src and @p dst are not compatible.
+ * - `Status::REFUSED` - No permission to copy.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ void copyBuffer(in Buffer src, in Buffer dst);
+
+ /**
+ * Creates a component by name.
+ *
+ * @param name Name of the component to create. This must match one of the
+ * names returned by listComponents().
+ * @param listener Callback receiver.
+ * @param pool `IClientManager` object of the BufferPool in the client
+ * process. This may be null if the client does not own a BufferPool.
+ * @return The created component.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::NOT_FOUND` - There is no component with the given name.
+ * - `Status::NO_MEMORY` - Not enough memory to create the component.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ *
+ * @sa IComponentListener.
+ */
+ IComponent createComponent(in String name, in IComponentListener listener,
+ in android.hardware.media.bufferpool2.IClientManager pool);
+
+ /**
+ * Creates a component interface by name.
+ *
+ * @param name Name of the component interface to create. This should match
+ * one of the names returned by listComponents().
+ * @return The created component interface.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::NOT_FOUND` - There is no component interface with the given name.
+ * - `Status::NO_MEMORY` - Not enough memory to create the component interface.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ IComponentInterface createInterface(in String name);
+
+ /**
+ * Returns the @ref IConfigurable instance associated to this component
+ * store.
+ *
+ * @return `IConfigurable` instance. This must not be null.
+ */
+ IConfigurable getConfigurable();
+
+ /**
+ * Returns the `IClientManager` object for the component's BufferPool.
+ *
+ * @return If the component store supports receiving buffers via
+ * BufferPool API, @p pool must be a valid `IClientManager` instance.
+ * Otherwise, @p pool must be null.
+ */
+ android.hardware.media.bufferpool2.IClientManager getPoolClientManager();
+
+ /**
+ * Returns a list of `StructDescriptor` objects for a set of requested
+ * C2Param structure indices that this store is aware of.
+ *
+ * This operation must be performed at best effort, e.g. the component
+ * store must simply ignore all struct indices that it is not aware of.
+ *
+ * @param indices Indices of C2Param structures to describe.
+ * @return List of `StructDescriptor` objects.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::NOT_FOUND` - Some indices were not known.
+ * - `Status::NO_MEMORY` - Not enough memory to complete this method.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ StructDescriptor[] getStructDescriptors(in int[] indices);
+
+ /**
+ * Returns the list of components supported by this component store.
+ *
+ * @return traits List of component traits for all components supported by
+ * this store (in no particular order).
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::NO_MEMORY` - Not enough memory to complete this method.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ ComponentTraits[] listComponents();
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/IConfigurable.aidl b/media/c2/aidl/android/hardware/media/c2/IConfigurable.aidl
new file mode 100644
index 0000000..7fdb825
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/IConfigurable.aidl
@@ -0,0 +1,213 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.FieldSupportedValuesQuery;
+import android.hardware.media.c2.FieldSupportedValuesQueryResult;
+import android.hardware.media.c2.ParamDescriptor;
+import android.hardware.media.c2.Params;
+import android.hardware.media.c2.SettingResult;
+
+/**
+ * Generic configuration interface presented by all configurable Codec2 objects.
+ *
+ * This interface must be supported in all states of the owning object, and must
+ * not change the state of the owning object.
+ */
+@VintfStability
+interface IConfigurable {
+ /**
+ * Return parcelable for config() interface.
+ *
+ * This includes the successful config settings along with the failure reasons of
+ * the specified setting.
+ */
+ @VintfStability
+ parcelable ConfigResult {
+ Params params;
+ SettingResult[] failures;
+ }
+
+ /**
+ * Sets a set of parameters for the object.
+ *
+ * Tuning is performed at best effort: the object must update all supported
+ * configurations at best effort and skip unsupported parameters. Any errors
+ * are communicated in the return value along with the failures.
+ *
+ * A non-strict parameter update with an unsupported value shall cause an
+ * update to the closest supported value. A strict parameter update with an
+ * unsupported value shall be skipped and a failure shall be returned.
+ *
+ * If @p mayBlock is false, this method must not block. An update that
+ * requires blocking shall be skipped and a failure shall be returned.
+ *
+ * If @p mayBlock is true, an update may block, but the whole method call
+ * has to complete in a timely manner, or `Status::TIMED_OUT` is thrown.
+ *
+ * The final values for all parameters set are propagated back to the caller
+ * in @p params.
+ *
+ * \par For IComponent
+ *
+ * When the object type is @ref IComponent, this method must be supported in
+ * any state except released.
+ *
+ * The blocking behavior of this method differs among states:
+ * - In the stopped state, this must be non-blocking. @p mayBlock is
+ * ignored. (The method operates as if @p mayBlock was false.)
+ * - In any of the running states, this method may block momentarily if
+ * @p mayBlock is true. However, if the call cannot be completed in a
+ * timely manner, `Status::TIMED_OUT` is thrown.
+ *
+ * @note Parameter tuning @e does depend on the order of the tuning
+ * parameters, e.g., some parameter update may enable some subsequent
+ * parameter update.
+ *
+ * @param inParams Requested parameter updates.
+ * @param mayBlock Whether this call may block or not.
+ * @return result of config. Params in the result should be in same order
+ * with @p inParams.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::NO_MEMORY` - Some supported parameters could not be updated
+ * successfully because they contained unsupported values.
+ * These are returned in @p failures.
+ * - `Status::BLOCKING` - Setting some parameters requires blocking, but
+ * @p mayBlock is false.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ ConfigResult config(in Params inParams, in boolean mayBlock);
+
+ /**
+ * Returns the id of the object. This must be unique among all objects of
+ * the same type hosted by the same store.
+ *
+ * @return Id of the object.
+ */
+ int getId();
+
+ /**
+ * Returns the name of the object.
+ *
+ * This must match the name that was supplied during the creation of the
+ * object.
+ *
+ * @return Name of the object.
+ */
+ String getName();
+
+ /**
+ * Queries a set of parameters from the object.
+ *
+ * Querying is performed at best effort: the object must query all supported
+ * parameters and skip unsupported ones (which may include parameters that
+ * could not be allocated).
+ *
+ * If @p mayBlock is true, a query may block, but the whole method call
+ * has to complete in a timely manner, or `Status::TIMED_OUT` is thrown.
+ *
+ * If @p mayBlock is false, this method must not block(All parameter queries
+ * that require blocking must be skipped). Otherwise, this
+ * method is allowed to block for a certain period of time before completing
+ * the operation. If the operation is not completed in a timely manner,
+ * `Status::TIMED_OUT` is thrown.
+ *
+ * @note Since unsupported parameters will be skipped, the returned results
+ * does not have every settings from @p indices, but the result will preserve
+ * the original order from @p indices though unsupported settings are skipped.
+ *
+ * \par For IComponent
+ *
+ * When the object type is @ref IComponent, this method must be supported in
+ * any state except released. This call must not change the state nor the
+ * internal configuration of the component.
+ *
+ * The blocking behavior of this method differs among states:
+ * - In the stopped state, this must be non-blocking. @p mayBlock is
+ * ignored. (The method operates as if @p mayBlock was false.)
+ * - In any of the running states, this method may block momentarily if
+ * @p mayBlock is true. However, if the call cannot be completed in a
+ * timely manner, `Status::status` is thrown.
+ *
+ * @param indices List of C2Param structure indices to query.
+ * @param mayBlock Whether this call may block or not.
+ * @return Flattened representation of std::vector<C2Param> object.
+ * Unsupported settings are skipped in the results. The order in @p indices
+ * still be preserved except skipped settings.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::NO_MEMORY` - Could not allocate memory for a supported parameter.
+ * - `Status::BLOCKING` - Querying some parameters requires blocking, but
+ * @p mayBlock is false.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ Params query(in int[] indices, in boolean mayBlock);
+
+ /**
+ * Returns a list of supported parameters within a selected range of C2Param
+ * structure indices.
+ *
+ * @param start The first index of the selected range.
+ * @param count The length of the selected range.
+ * @return List of supported parameters in the selected range. This
+ * list may have fewer than @p count elements if some indices in the
+ * range are not supported.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::NO_MEMORY` - Not enough memory to complete this method.
+ *
+ */
+ ParamDescriptor[] querySupportedParams(in int start, in int count);
+
+ /**
+ * Retrieves the supported values for the queried fields.
+ *
+ * The object must process all fields queried even if some queries fail.
+ *
+ * If @p mayBlock is false, this method must not block. Otherwise, this
+ * method is allowed to block for a certain period of time before completing
+ * the operation. If the operation cannot be completed in a timely manner,
+ * `Status::TIMED_OUT` is thrown.
+ *
+ * \par For IComponent
+ *
+ * When the object type is @ref IComponent, this method must be supported in
+ * any state except released.
+ *
+ * The blocking behavior of this method differs among states:
+ * - In the stopped state, this must be non-blocking. @p mayBlock is
+ * ignored. (The method operates as if @p mayBlock was false.)
+ * - In any of the running states, this method may block momentarily if
+ * @p mayBlock is true. However, if the call cannot be completed in a
+ * timely manner, `Status::TIMED_OUT` is thrown.
+ *
+ * @param inFields List of field queries.
+ * @param mayBlock Whether this call may block or not.
+ * @return List of supported values and results for the
+ * supplied queries.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::BLOCKING` - Querying some parameters requires blocking, but
+ * @p mayBlock is false.
+ * - `Status::NO_MEMORY` - Not enough memory to complete this method.
+ * - `Status::BLOCKING` - Querying some fields requires blocking, but @p mayblock
+ * is false.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ FieldSupportedValuesQueryResult[] querySupportedValues(
+ in FieldSupportedValuesQuery[] inFields, in boolean mayBlock);
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/InfoBuffer.aidl b/media/c2/aidl/android/hardware/media/c2/InfoBuffer.aidl
new file mode 100644
index 0000000..207c4d0
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/InfoBuffer.aidl
@@ -0,0 +1,36 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.Buffer;
+
+/**
+ * An extension of @ref Buffer that also contains a C2Param structure index.
+ *
+ * This is a part of @ref FrameData.
+ */
+@VintfStability
+parcelable InfoBuffer {
+ /**
+ * A C2Param structure index.
+ */
+ int index;
+ /**
+ * Associated @ref Buffer object.
+ */
+ Buffer buffer;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/ParamDescriptor.aidl b/media/c2/aidl/android/hardware/media/c2/ParamDescriptor.aidl
new file mode 100644
index 0000000..84c6acc
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/ParamDescriptor.aidl
@@ -0,0 +1,73 @@
+/*
+ * 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.media.c2;
+
+/**
+ * Usage description of a C2Param structure.
+ *
+ * @ref ParamDescriptor is returned by IConfigurable::querySupportedParams().
+ */
+@VintfStability
+parcelable ParamDescriptor {
+ /** The list of bit flags for attrib */
+ /**
+ * The parameter is required to be specified.
+ */
+ const int ATTRIBUTE_REQUIRED = 1 << 0;
+ /**
+ * The parameter retains its value.
+ */
+ const int ATTRIBUTE_PERSISTENT = 1 << 1;
+ /**
+ * The parameter is strict.
+ */
+ const int ATTRIBUTE_STRICT = 1 << 2;
+ /**
+ * The parameter is publicly read-only.
+ */
+ const int ATTRIBUTE_READ_ONLY = 1 << 3;
+ /**
+ * The parameter must not be visible to clients.
+ */
+ const int ATTRIBUTE_HIDDEN = 1 << 4;
+ /**
+ * The parameter must not be used by framework (other than testing).
+ */
+ const int ATTRIBUTE_INTERNAL = 1 << 5;
+ /**
+ * The parameter is publicly constant (hence read-only).
+ */
+ const int ATTRIBUTE_CONST = 1 << 6;
+
+ /**
+ * Index of the C2Param structure being described.
+ */
+ int index;
+ /**
+ * bit flag for attribute defined in the above.
+ */
+ int attrib;
+ /**
+ * Name of the structure. This must be unique for each structure.
+ */
+ String name;
+ /**
+ * Indices of other C2Param structures that this C2Param structure depends
+ * on.
+ */
+ int[] dependencies;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/ParamField.aidl b/media/c2/aidl/android/hardware/media/c2/ParamField.aidl
new file mode 100644
index 0000000..64a46bb
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/ParamField.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.FieldId;
+
+/**
+ * Reference to a field in a C2Param structure.
+ */
+@VintfStability
+parcelable ParamField {
+ /**
+ * Index of the C2Param structure.
+ */
+ int index;
+ /**
+ * Identifier of the field inside the C2Param structure.
+ */
+ FieldId fieldId;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/ParamFieldValues.aidl b/media/c2/aidl/android/hardware/media/c2/ParamFieldValues.aidl
new file mode 100644
index 0000000..7b74c0e
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/ParamFieldValues.aidl
@@ -0,0 +1,43 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.FieldSupportedValues;
+import android.hardware.media.c2.ParamField;
+
+/**
+ * Supported values for a field.
+ *
+ * This is a pair of the field specifier together with an optional supported
+ * values object. This structure is used when reporting parameter configuration
+ * failures and conflicts.
+ */
+@VintfStability
+parcelable ParamFieldValues {
+ /**
+ * Reference to a field or a C2Param structure.
+ */
+ ParamField paramOrField;
+ /**
+ * Optional supported values for the field if #paramOrField specifies an
+ * actual field that is numeric (non struct, blob or string). Supported
+ * values for arrays (including string and blobs) describe the supported
+ * values for each element (character for string, and bytes for blobs). It
+ * is optional for read-only strings and blobs.
+ */
+ FieldSupportedValues[] values;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/Params.aidl b/media/c2/aidl/android/hardware/media/c2/Params.aidl
new file mode 100644
index 0000000..53b512c
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/Params.aidl
@@ -0,0 +1,36 @@
+/*
+ * 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.media.c2;
+
+/**
+ * Flattened representation of std::vector<C2Param> object.
+ *
+ * The `Params` type is an array of bytes made up by concatenating a list of
+ * C2Param objects. The start index (offset into @ref Params) of each C2Param
+ * object in the list is divisible by 8. Up to 7 padding bytes may be added
+ * after each C2Param object to achieve this 64-bit alignment.
+ *
+ * Each C2Param object has the following layout:
+ * - 4 bytes: C2Param structure index (of type @ref ParamIndex) identifying the
+ * type of the C2Param object.
+ * - 4 bytes: size of the C2Param object (unsigned 4-byte integer).
+ * - (size - 8) bytes: data of the C2Param object.
+ */
+@VintfStability
+parcelable Params {
+ byte[] params;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/SettingResult.aidl b/media/c2/aidl/android/hardware/media/c2/SettingResult.aidl
new file mode 100644
index 0000000..c2b9574
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/SettingResult.aidl
@@ -0,0 +1,99 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.ParamFieldValues;
+
+/**
+ * Information describing the reason the parameter settings may fail, or may be
+ * overridden.
+ */
+@VintfStability
+parcelable SettingResult {
+ /**
+ * Failure code
+ */
+ @VintfStability
+ @Backing(type="int")
+ enum Failure {
+ /**
+ * Parameter is not supported.
+ */
+ BAD_TYPE,
+ /**
+ * Parameter is not supported on the specific port.
+ */
+ BAD_PORT,
+ /**
+ * Parameter is not supported on the specific stream.
+ */
+ BAD_INDEX,
+ /**
+ * Parameter is read-only and cannot be set.
+ */
+ READ_ONLY,
+ /**
+ * Parameter mismatches input data.
+ */
+ MISMATCH,
+ /**
+ * Strict parameter does not accept value for the field at all.
+ */
+ BAD_VALUE,
+ /**
+ * Strict parameter field value is in conflict with an/other
+ * setting(s).
+ */
+ CONFLICT,
+ /**
+ * Parameter field is out of range due to other settings. (This failure
+ * mode can only be used for strict calculated parameters.)
+ */
+ UNSUPPORTED,
+ /**
+ * Field does not access the requested parameter value at all. It has
+ * been corrected to the closest supported value. This failure mode is
+ * provided to give guidance as to what are the currently supported
+ * values for this field (which may be a subset of the at-all-potential
+ * values).
+ */
+ INFO_BAD_VALUE,
+ /**
+ * Requested parameter value is in conflict with an/other setting(s)
+ * and has been corrected to the closest supported value. This failure
+ * mode is given to provide guidance as to what are the currently
+ * supported values as well as to optionally provide suggestion to the
+ * client as to how to enable the requested parameter value.
+ */
+ INFO_CONFLICT,
+ }
+ Failure failure;
+ /**
+ * Failing (or corrected) field or parameter and optionally, currently
+ * supported values for the field. Values must only be set for field
+ * failures other than `BAD_VALUE`, and only if they are different from the
+ * globally supported values (e.g. due to restrictions by another parameter
+ * or input data).
+ */
+ ParamFieldValues field;
+ /**
+ * Conflicting parameters or fields with (optional) suggested values for any
+ * conflicting fields to avoid the conflict. Values must only be set for
+ * `CONFLICT`, `UNSUPPORTED` or `INFO_CONFLICT` failure code.
+ */
+ ParamFieldValues[] conflicts;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/Status.aidl b/media/c2/aidl/android/hardware/media/c2/Status.aidl
new file mode 100644
index 0000000..58a2404
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/Status.aidl
@@ -0,0 +1,82 @@
+/*
+ * 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.media.c2;
+
+/**
+ * Common return values for Codec2 operations.
+ */
+@VintfStability
+parcelable Status {
+ /**
+ * Operation completed successfully.
+ */
+ const int OK = 0;
+ /**
+ * Argument has invalid value (user error).
+ */
+ const int BAD_VALUE = -22;
+ /**
+ * Argument uses invalid index (user error).
+ */
+ const int BAD_INDEX = -75;
+ /**
+ * Argument/Index is valid but not possible.
+ */
+ const int CANNOT_DO = -2147483646;
+ /**
+ * Object already exists.
+ */
+ const int DUPLICATE = -17;
+ /**
+ * Object not found.
+ */
+ const int NOT_FOUND = -2;
+ /**
+ * Operation is not permitted in the current state.
+ */
+ const int BAD_STATE = -38;
+ /**
+ * Operation would block but blocking is not permitted.
+ */
+ const int BLOCKING = -9930;
+ /**
+ * Not enough memory to complete operation.
+ */
+ const int NO_MEMORY = -12;
+ /**
+ * Missing permission to complete operation.
+ */
+ const int REFUSED = -1;
+ /**
+ * Operation did not complete within timeout.
+ */
+ const int TIMED_OUT = -110;
+ /**
+ * Operation is not implemented/supported (optional only).
+ */
+ const int OMITTED = -74;
+ /**
+ * Some unexpected error prevented the operation.
+ */
+ const int CORRUPTED = -2147483648;
+ /**
+ * Status has not been initialized.
+ */
+ const int NO_INIT = -19;
+
+ int status;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/StructDescriptor.aidl b/media/c2/aidl/android/hardware/media/c2/StructDescriptor.aidl
new file mode 100644
index 0000000..00359041
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/StructDescriptor.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.media.c2;
+
+import android.hardware.media.c2.FieldDescriptor;
+
+/**
+ * Description of a C2Param structure. It consists of an index and a list of
+ * `FieldDescriptor`s.
+ */
+@VintfStability
+parcelable StructDescriptor {
+ /**
+ * Index of the structure.
+ *
+ * Actually C2Param::CoreIndex
+ * Core index is the underlying parameter type for a parameter. It is used to describe the
+ * layout of the parameter structure regardless of the component or parameter kind/scope.
+ *
+ * It is used to identify and distinguish global parameters, and also parameters on a given
+ * port or stream. They must be unique for the set of global parameters, as well as for the
+ * set of parameters on each port or each stream, but the same core index can be used for
+ * parameters on different streams or ports, as well as for global parameters and port/stream
+ * parameters.
+ */
+ int type;
+ /**
+ * List of fields in the structure.
+ *
+ * Fields are ordered by their offsets. A field that is a structure is
+ * ordered before its members.
+ */
+ FieldDescriptor[] fields;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/SurfaceSyncObj.aidl b/media/c2/aidl/android/hardware/media/c2/SurfaceSyncObj.aidl
new file mode 100644
index 0000000..d20e102
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/SurfaceSyncObj.aidl
@@ -0,0 +1,55 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.common.NativeHandle;
+/**
+ * Surface(BufferQueue/IGBP) synchronization object regarding # of dequeued
+ * output buffers. This keeps # of dequeued buffers from Surface less than
+ * configured max # of dequeued buffers all the time.
+ */
+@VintfStability
+parcelable SurfaceSyncObj {
+ /**
+ * ASharedMemory for synchronization data. Layout is below
+ *
+ * |lock(futex) 4bytes|
+ * |conditional_variable(futex) 4bytes|
+ * |# of max dequeable buffer 4bytes|
+ * |# of dequeued buffer 4bytes|
+ * |Status of the surface 4bytes|
+ * INIT = 0, Configuring surface is not finished.
+ * ACTIVE = 1, Surface is ready to allocate(dequeue).
+ * SWITCHING = 2, Switching to the new surface. It is blocked
+ * to allocate(dequeue) a buffer until switching
+ * completes.
+ */
+ NativeHandle syncMemory;
+ /**
+ * BufferQueue id.
+ */
+ long bqId;
+ /**
+ * Generation id.
+ */
+ int generationId;
+ /**
+ * Consumer usage flags. See +ndk
+ * libnativewindow#AHardwareBuffer_UsageFlags for possible values.
+ */
+ long consumerUsage;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/ValueRange.aidl b/media/c2/aidl/android/hardware/media/c2/ValueRange.aidl
new file mode 100644
index 0000000..9abcb7d
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/ValueRange.aidl
@@ -0,0 +1,63 @@
+/*
+ * 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.media.c2;
+
+/**
+ * Description of a set of values.
+ *
+ * If the `step` member is 0, and `num` and `denom` are both 1, the `Range`
+ * structure represents a closed interval bounded by `min` and `max`.
+ *
+ * Otherwise, the #ValueRange structure represents a finite sequence of numbers
+ * produced from the following recurrence relation:
+ *
+ * @code
+ * v[0] = min
+ * v[i] = v[i - 1] * num / denom + step ; i >= 1
+ * @endcode
+ *
+ * Both the ratio `num / denom` and the value `step` must be positive. The
+ * last number in the sequence described by this #Range structure is the
+ * largest number in the sequence that is smaller than or equal to `max`.
+ *
+ * @note
+ * The division in the formula may truncate the result if the data type of
+ * these values is an integral type.
+ */
+@VintfStability
+parcelable ValueRange {
+ /**
+ * Lower end of the range (inclusive).
+ */
+ long min;
+ /**
+ * Upper end of the range (inclusive).
+ */
+ long max;
+ /**
+ * The non-homogeneous term in the recurrence relation.
+ */
+ long step;
+ /**
+ * The numerator of the scale coefficient in the recurrence relation.
+ */
+ long num;
+ /**
+ * The denominator of the scale coefficient in the recurrence relation.
+ */
+ long denom;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/Work.aidl b/media/c2/aidl/android/hardware/media/c2/Work.aidl
new file mode 100644
index 0000000..4b8d696
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/Work.aidl
@@ -0,0 +1,83 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.FrameData;
+import android.hardware.media.c2.Status;
+import android.hardware.media.c2.Worklet;
+
+/**
+ * A collection of input data to and output data from the component.
+ *
+ * A `Work` object holds information about a single work item. It is created by
+ * the client and passed to the component via IComponent::queue(). The component
+ * has two ways of returning a `Work` object to the client:
+ * 1. If the queued `Work` object has been successfully processed,
+ * IComponentListener::onWorkDone() shall be called to notify the listener,
+ * and the output shall be included in the returned `Work` object.
+ * 2. If the client calls IComponent::flush(), a `Work` object that has not
+ * been processed shall be returned.
+ *
+ * `Work` is a part of @ref WorkBundle.
+ */
+@VintfStability
+parcelable Work {
+ /**
+ * Additional work chain info not part of this work.
+ */
+ byte[] chainInfo;
+ /**
+ * @ref FrameData for the input.
+ */
+ FrameData input;
+ /**
+ * The chain of `Worklet`s.
+ *
+ * The length of #worklets is 1 when tunneling is not enabled.
+ *
+ * If #worklets has more than a single element, the tunnels between
+ * successive components of the work chain must have been successfully
+ * pre-registered at the time that the `Work` is submitted. Allocating the
+ * output buffers in the `Worklet`s is the responsibility of each component
+ * in the chain.
+ *
+ * Upon `Work` submission, #worklets must be an appropriately sized vector
+ * containing `Worklet`s with @ref Worklet.hasOutput set to `false`. After a
+ * successful processing, all but the final `Worklet` in the returned
+ * #worklets must have @ref Worklet.hasOutput set to `false`.
+ */
+ Worklet[] worklets;
+ /**
+ * The number of `Worklet`s successfully processed in this chain.
+ *
+ * This must be initialized to 0 by the client when the `Work` is submitted,
+ * and it must contain the number of `Worklet`s that were successfully
+ * processed when the `Work` is returned to the client.
+ *
+ * #workletsProcessed cannot exceed the length of #worklets. If
+ * #workletsProcessed is smaller than the length of #worklets, #result
+ * cannot be `OK`.
+ */
+ int workletsProcessed;
+ /**
+ * The final outcome of the `Work` (corresponding to #workletsProcessed).
+ *
+ * The value of @ref Status.OK implies that all `Worklet`s have been
+ * successfully processed.
+ */
+ Status result;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/WorkBundle.aidl b/media/c2/aidl/android/hardware/media/c2/WorkBundle.aidl
new file mode 100644
index 0000000..2125fda
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/WorkBundle.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.media.c2;
+
+import android.hardware.media.c2.BaseBlock;
+import android.hardware.media.c2.Work;
+
+/**
+ * List of `Work` objects.
+ *
+ * `WorkBundle` is used in IComponent::queue(), IComponent::flush() and
+ * IComponentListener::onWorkDone(). A `WorkBundle` object consists of a list of
+ * `Work` objects and a list of `BaseBlock` objects. Bundling multiple `Work`
+ * objects together provides two benefits:
+ * 1. Batching of `Work` objects can reduce the number of IPC calls.
+ * 2. If multiple `Work` objects contain `Block`s that refer to the same
+ * `BaseBlock`, the number of `BaseBlock`s that is sent between processes
+ * is also reduced.
+ *
+ * @note `WorkBundle` is the AIDL counterpart of the vector of `C2Work` in the
+ * Codec 2.0 standard. The presence of #baseBlocks helps with minimizing the
+ * data transferred over an IPC.
+ */
+@VintfStability
+parcelable WorkBundle {
+ /**
+ * A list of Work items.
+ */
+ Work[] works;
+ /**
+ * A list of blocks indexed by elements of #works.
+ */
+ BaseBlock[] baseBlocks;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/WorkOrdinal.aidl b/media/c2/aidl/android/hardware/media/c2/WorkOrdinal.aidl
new file mode 100644
index 0000000..5708a90
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/WorkOrdinal.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.media.c2;
+
+/**
+ * Ordering information of @ref FrameData objects. Each member is used for
+ * comparing urgency: a smaller difference from a reference value indicates that
+ * the associated Work object is more urgent. The reference value for each
+ * member is initialized the first time it is communicated between the client
+ * and the codec, and it may be updated to later values that are communicated.
+ *
+ * Each member of `WorkOrdinal` is stored as an unsigned integer, but the actual
+ * order it represents is derived by subtracting the reference value, then
+ * interpreting the result as a signed number with the same storage size (using
+ * two's complement).
+ *
+ * @note `WorkOrdinal` is the HIDL counterpart of `C2WorkOrdinalStruct` in the
+ * Codec 2.0 standard.
+ */
+@VintfStability
+parcelable WorkOrdinal {
+ /**
+ * Timestamp in microseconds.
+ */
+ long timestampUs;
+ /**
+ * Frame index.
+ */
+ long frameIndex;
+ /**
+ * Component specific frame ordinal.
+ */
+ long customOrdinal;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/Worklet.aidl b/media/c2/aidl/android/hardware/media/c2/Worklet.aidl
new file mode 100644
index 0000000..6b3ceac
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/Worklet.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.
+ */
+
+package android.hardware.media.c2;
+
+import android.hardware.media.c2.FrameData;
+import android.hardware.media.c2.SettingResult;
+
+/**
+ * In/out structure containing some instructions for and results from output
+ * processing.
+ *
+ * This is a part of @ref Work. One `Worklet` corresponds to one output
+ * @ref FrameData. The client must construct an original `Worklet` object inside
+ * a @ref Work object for each expected output before calling
+ * IComponent::queue().
+ */
+@VintfStability
+parcelable Worklet {
+ /**
+ * Component id. (Input)
+ *
+ * This is used only when tunneling is enabled.
+ *
+ * When used, this must match the return value from IConfigurable::getId().
+ */
+ int componentId;
+ /**
+ * List of C2Param objects describing tunings to be applied before
+ * processing this `Worklet`. (Input)
+ */
+ byte[] tunings;
+ /**
+ * List of failures. (Output)
+ */
+ SettingResult[] failures;
+ /**
+ * Output frame data. (Output)
+ */
+ FrameData output;
+}
diff --git a/radio/aidl/Android.bp b/radio/aidl/Android.bp
index 98eafc1..0088264 100644
--- a/radio/aidl/Android.bp
+++ b/radio/aidl/Android.bp
@@ -12,6 +12,7 @@
vendor_available: true,
host_supported: true,
srcs: ["android/hardware/radio/*.aidl"],
+ frozen: true,
stability: "vintf",
backend: {
cpp: {
@@ -35,6 +36,7 @@
vendor_available: true,
host_supported: true,
srcs: ["android/hardware/radio/config/*.aidl"],
+ frozen: true,
stability: "vintf",
imports: ["android.hardware.radio"],
backend: {
diff --git a/security/keymint/aidl/vts/functional/Android.bp b/security/keymint/aidl/vts/functional/Android.bp
index 13143bf..e7f5a0f 100644
--- a/security/keymint/aidl/vts/functional/Android.bp
+++ b/security/keymint/aidl/vts/functional/Android.bp
@@ -90,24 +90,3 @@
"libgmock_ndk",
],
}
-
-cc_test {
- name: "VtsHalRemotelyProvisionedComponentTargetTest",
- defaults: [
- "keymint_vts_defaults",
- ],
- srcs: [
- "VtsRemotelyProvisionedComponentTests.cpp",
- ],
- static_libs: [
- "libgmock_ndk",
- "libkeymaster_portable",
- "libkeymint_vts_test_utils",
- "libpuresoftkeymasterdevice",
- ],
- test_config: "VtsRemotelyProvisionedComponentTests.xml",
- test_suites: [
- "general-tests",
- "vts",
- ],
-}
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index b8d0c20..5a86283 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -1027,7 +1027,7 @@
* without providing NOT_BEFORE and NOT_AFTER parameters.
*/
TEST_P(NewKeyGenerationTest, RsaWithMissingValidity) {
- if (AidlVersion() < 2) {
+ if (AidlVersion() < 3) {
/*
* The KeyMint V1 spec required that CERTIFICATE_NOT_{BEFORE,AFTER} be
* specified for asymmetric key generation. However, this was not
@@ -1130,16 +1130,16 @@
}
/*
- * NewKeyGenerationTest.RsaWithRpkAttestation
+ * NewKeyGenerationTest.RsaWithRkpAttestation
*
- * Verifies that keymint can generate all required RSA key sizes, using an attestation key
+ * Verifies that keymint can generate all required RSA key sizes using an attestation key
* that has been generated using an associate IRemotelyProvisionedComponent.
- *
- * This test is disabled because the KeyMint specification does not require that implementations
- * of the first version of KeyMint have to also implement IRemotelyProvisionedComponent.
- * However, the test is kept in the code because KeyMint v2 will impose this requirement.
*/
-TEST_P(NewKeyGenerationTest, DISABLED_RsaWithRpkAttestation) {
+TEST_P(NewKeyGenerationTest, RsaWithRkpAttestation) {
+ if (AidlVersion() < 2) {
+ GTEST_SKIP() << "Only required starting with KeyMint v2";
+ }
+
// There should be an IRemotelyProvisionedComponent instance associated with the KeyMint
// instance.
std::shared_ptr<IRemotelyProvisionedComponent> rp;
@@ -1208,6 +1208,81 @@
}
/*
+ * NewKeyGenerationTest.EcdsaWithRkpAttestation
+ *
+ * Verifies that keymint can generate all required ECDSA key sizes using an attestation key
+ * that has been generated using an associate IRemotelyProvisionedComponent.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaWithRkpAttestation) {
+ if (AidlVersion() < 2) {
+ GTEST_SKIP() << "Only required starting with KeyMint v2";
+ }
+
+ // There should be an IRemotelyProvisionedComponent instance associated with the KeyMint
+ // instance.
+ std::shared_ptr<IRemotelyProvisionedComponent> rp;
+ ASSERT_TRUE(matching_rp_instance(GetParam(), &rp))
+ << "No IRemotelyProvisionedComponent found that matches KeyMint device " << GetParam();
+
+ // Generate a P-256 keypair to use as an attestation key.
+ MacedPublicKey macedPubKey;
+ std::vector<uint8_t> privateKeyBlob;
+ auto status =
+ rp->generateEcdsaP256KeyPair(/* testMode= */ false, &macedPubKey, &privateKeyBlob);
+ ASSERT_TRUE(status.isOk());
+ vector<uint8_t> coseKeyData;
+ check_maced_pubkey(macedPubKey, /* testMode= */ false, &coseKeyData);
+
+ AttestationKey attestation_key;
+ attestation_key.keyBlob = std::move(privateKeyBlob);
+ attestation_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
+
+ for (auto curve : ValidCurves()) {
+ SCOPED_TRACE(testing::Message() << "Curve::" << curve);
+ auto challenge = "hello";
+ auto app_id = "foo";
+
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ ASSERT_EQ(ErrorCode::OK,
+ GenerateKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(curve)
+ .Digest(Digest::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity(),
+ attestation_key, &key_blob, &key_characteristics, &cert_chain_));
+
+ ASSERT_GT(key_blob.size(), 0U);
+ CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
+
+ AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+
+ EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
+ EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, curve)) << "Curve " << curve << "missing";
+
+ // Attestation by itself is not valid (last entry is not self-signed).
+ EXPECT_FALSE(ChainSignaturesAreValid(cert_chain_));
+
+ // The signature over the attested key should correspond to the P256 public key.
+ ASSERT_GT(cert_chain_.size(), 0);
+ X509_Ptr key_cert(parse_cert_blob(cert_chain_[0].encodedCertificate));
+ ASSERT_TRUE(key_cert.get());
+ EVP_PKEY_Ptr signing_pubkey;
+ p256_pub_key(coseKeyData, &signing_pubkey);
+ ASSERT_TRUE(signing_pubkey.get());
+
+ ASSERT_TRUE(X509_verify(key_cert.get(), signing_pubkey.get()))
+ << "Verification of attested certificate failed "
+ << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
+
+ CheckedDeleteKey(&key_blob);
+ }
+}
+
+/*
* NewKeyGenerationTest.RsaEncryptionWithAttestation
*
* Verifies that keymint attestation for RSA encryption keys with challenge and
diff --git a/security/rkp/OWNERS b/security/rkp/OWNERS
new file mode 100644
index 0000000..d25977f
--- /dev/null
+++ b/security/rkp/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 1084908
+
+jbires@google.com
+sethmo@google.com
+trong@google.com
diff --git a/security/rkp/TEST_MAPPING b/security/rkp/TEST_MAPPING
new file mode 100644
index 0000000..9ce5e9b
--- /dev/null
+++ b/security/rkp/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "VtsHalRemotelyProvisionedComponentTargetTest"
+ }
+ ]
+}
diff --git a/security/rkp/aidl/vts/functional/Android.bp b/security/rkp/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..9c2b6e1
--- /dev/null
+++ b/security/rkp/aidl/vts/functional/Android.bp
@@ -0,0 +1,44 @@
+//
+// Copyright (C) 2020 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
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+ name: "VtsHalRemotelyProvisionedComponentTargetTest",
+ defaults: [
+ "keymint_vts_defaults",
+ ],
+ srcs: [
+ "VtsRemotelyProvisionedComponentTests.cpp",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ "libcrypto",
+ ],
+ static_libs: [
+ "libcppbor_external",
+ "libgmock_ndk",
+ "libkeymint_vts_test_utils",
+ ],
+ test_config: "VtsRemotelyProvisionedComponentTests.xml",
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.xml b/security/rkp/aidl/vts/functional/AndroidTest.xml
similarity index 100%
copy from security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.xml
copy to security/rkp/aidl/vts/functional/AndroidTest.xml
diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
similarity index 97%
rename from security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
rename to security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index 6d9c8c9..aebcf67 100644
--- a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -18,7 +18,7 @@
#include <string>
#define LOG_TAG "VtsRemotelyProvisionableComponentTests"
-#include <AndroidRemotelyProvisionedComponentDevice.h>
+#include <aidl/android/hardware/security/keymint/BnRemotelyProvisionedComponent.h>
#include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
#include <aidl/android/hardware/security/keymint/SecurityLevel.h>
#include <android/binder_manager.h>
@@ -783,4 +783,20 @@
INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestV2Test);
+using VsrRequirementTest = VtsRemotelyProvisionedComponentTests;
+
+INSTANTIATE_REM_PROV_AIDL_TEST(VsrRequirementTest);
+
+TEST_P(VsrRequirementTest, VsrEnforcementTest) {
+ RpcHardwareInfo hwInfo;
+ ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
+ int vsr_api_level = get_vsr_api_level();
+ if (vsr_api_level < 34) {
+ GTEST_SKIP() << "Applies only to VSR API level 34 or newer, this device is: "
+ << vsr_api_level;
+ }
+ EXPECT_GE(hwInfo.versionNumber, 3)
+ << "VSR 14+ requires IRemotelyProvisionedComponent v3 or newer.";
+}
+
} // namespace aidl::android::hardware::security::keymint::test
diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.xml b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.xml
similarity index 100%
rename from security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.xml
rename to security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.xml