Split AudioProfile between fwk and android.media.audio.common
a.m.a.c adds a version of AudioProfile struct which
is similar to Audio HIDL HAL V7. It lacks some bits used only
by the framework. These are carried in AudioProfileSys.
AudioProfileSys does not contain AudioProfile. This is done
to simplify further splitting of other types like AudioPort.
Updated to/from AIDL conversions in libaudiofondation.
They encapsulate the fact that there are two AIDL structures
per AudioProfile class instance.
Bug: 198812639
Test: atest audiofoundation_parcelable_test
Change-Id: I6834650f9406c552b6dfa42b120769eb38d6f588
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index eb8c03f..ed92681 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -49,6 +49,7 @@
using media::audio::common::AudioFormatType;
using media::audio::common::AudioMode;
using media::audio::common::AudioOffloadInfo;
+using media::audio::common::AudioProfile;
using media::audio::common::AudioSource;
using media::audio::common::AudioStreamType;
using media::audio::common::AudioUsage;
@@ -2743,17 +2744,17 @@
}
ConversionResult<audio_profile>
-aidl2legacy_AudioProfile_audio_profile(const media::AudioProfile& aidl, bool isInput) {
+aidl2legacy_AudioProfile_audio_profile(const AudioProfile& aidl, bool isInput) {
audio_profile legacy;
legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
- if (aidl.samplingRates.size() > std::size(legacy.sample_rates)) {
+ if (aidl.sampleRates.size() > std::size(legacy.sample_rates)) {
return unexpected(BAD_VALUE);
}
RETURN_IF_ERROR(
- convertRange(aidl.samplingRates.begin(), aidl.samplingRates.end(), legacy.sample_rates,
+ convertRange(aidl.sampleRates.begin(), aidl.sampleRates.end(), legacy.sample_rates,
convertIntegral<int32_t, unsigned int>));
- legacy.num_sample_rates = aidl.samplingRates.size();
+ legacy.num_sample_rates = aidl.sampleRates.size();
if (aidl.channelMasks.size() > std::size(legacy.channel_masks)) {
return unexpected(BAD_VALUE);
@@ -2770,9 +2771,9 @@
return legacy;
}
-ConversionResult<media::AudioProfile>
+ConversionResult<AudioProfile>
legacy2aidl_audio_profile_AudioProfile(const audio_profile& legacy, bool isInput) {
- media::AudioProfile aidl;
+ AudioProfile aidl;
aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
if (legacy.num_sample_rates > std::size(legacy.sample_rates)) {
@@ -2780,7 +2781,7 @@
}
RETURN_IF_ERROR(
convertRange(legacy.sample_rates, legacy.sample_rates + legacy.num_sample_rates,
- std::back_inserter(aidl.samplingRates),
+ std::back_inserter(aidl.sampleRates),
convertIntegral<unsigned int, int32_t>));
if (legacy.num_channel_masks > std::size(legacy.channel_masks)) {
@@ -2843,7 +2844,7 @@
}
const bool isInput = VALUE_OR_RETURN(direction(aidl.role, aidl.type)) == Direction::INPUT;
RETURN_IF_ERROR(convertRange(aidl.profiles.begin(), aidl.profiles.end(), legacy.audio_profiles,
- [isInput](const media::AudioProfile& p) {
+ [isInput](const AudioProfile& p) {
return aidl2legacy_AudioProfile_audio_profile(p, isInput);
}));
legacy.num_audio_profiles = aidl.profiles.size();
@@ -2892,6 +2893,7 @@
if (legacy.num_extra_audio_descriptors > std::size(legacy.extra_audio_descriptors)) {
return unexpected(BAD_VALUE);
}
+ aidl.profilesSys.resize(legacy.num_audio_profiles);
RETURN_IF_ERROR(
convertRange(legacy.extra_audio_descriptors,
legacy.extra_audio_descriptors + legacy.num_extra_audio_descriptors,
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 4cb531a..f150d88 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -339,7 +339,7 @@
"aidl/android/media/AudioPortRole.aidl",
"aidl/android/media/AudioPortSessionExt.aidl",
"aidl/android/media/AudioPortType.aidl",
- "aidl/android/media/AudioProfile.aidl",
+ "aidl/android/media/AudioProfileSys.aidl",
"aidl/android/media/AudioStandard.aidl",
"aidl/android/media/AudioTimestampInternal.aidl",
"aidl/android/media/AudioUniqueIdUse.aidl",
diff --git a/media/libaudioclient/aidl/android/media/AudioPort.aidl b/media/libaudioclient/aidl/android/media/AudioPort.aidl
index bf0e5b7..0f98ea1 100644
--- a/media/libaudioclient/aidl/android/media/AudioPort.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioPort.aidl
@@ -21,8 +21,9 @@
import android.media.AudioPortExt;
import android.media.AudioPortRole;
import android.media.AudioPortType;
-import android.media.AudioProfile;
+import android.media.AudioProfileSys;
import android.media.ExtraAudioDescriptor;
+import android.media.audio.common.AudioProfile;
/**
* {@hide}
@@ -37,6 +38,8 @@
@utf8InCpp String name;
/** AudioProfiles supported by this port (format, Rates, Channels). */
AudioProfile[] profiles;
+ /** System-only parameters for each AudioProfile. */
+ AudioProfileSys[] profilesSys;
/**
* ExtraAudioDescriptors supported by this port. The format is not unrecognized to the
* platform. The audio capability is described by a hardware descriptor.
diff --git a/media/libaudioclient/aidl/android/media/AudioProfile.aidl b/media/libaudioclient/aidl/android/media/AudioProfileSys.aidl
similarity index 62%
rename from media/libaudioclient/aidl/android/media/AudioProfile.aidl
rename to media/libaudioclient/aidl/android/media/AudioProfileSys.aidl
index 9378ab3..329c9d5 100644
--- a/media/libaudioclient/aidl/android/media/AudioProfile.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioProfileSys.aidl
@@ -16,21 +16,15 @@
package android.media;
-import android.media.audio.common.AudioEncapsulationType;
-import android.media.audio.common.AudioFormatDescription;
-import android.media.audio.common.AudioChannelLayout;
-
/**
+ * Provides indication whether the parameters of the AudioProfiles in the
+ * AudioPort are dynamic. Each instance of AudioProfileSys corresponds
+ * to an instance of AudioProfile.
+ *
* {@hide}
*/
-parcelable AudioProfile {
- @utf8InCpp String name;
- /** The format for an audio profile should only be set when initialized. */
- AudioFormatDescription format;
- AudioChannelLayout[] channelMasks;
- int[] samplingRates;
+parcelable AudioProfileSys {
boolean isDynamicFormat;
boolean isDynamicChannels;
boolean isDynamicRate;
- AudioEncapsulationType encapsulationType;
}
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index 3bdd11c..1afb2c5 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -39,7 +39,6 @@
#include <android/media/AudioPortExt.h>
#include <android/media/AudioPortMixExt.h>
#include <android/media/AudioPortSessionExt.h>
-#include <android/media/AudioProfile.h>
#include <android/media/AudioTimestampInternal.h>
#include <android/media/AudioUniqueIdUse.h>
#include <android/media/EffectDescriptor.h>
@@ -56,6 +55,7 @@
#include <android/media/audio/common/AudioFormatDescription.h>
#include <android/media/audio/common/AudioMode.h>
#include <android/media/audio/common/AudioOffloadInfo.h>
+#include <android/media/audio/common/AudioProfile.h>
#include <android/media/audio/common/AudioSource.h>
#include <android/media/audio/common/AudioUsage.h>
#include <android/media/audio/common/AudioUuid.h>
@@ -372,8 +372,9 @@
legacy2aidl_audio_port_session_ext_AudioPortSessionExt(const audio_port_session_ext& legacy);
ConversionResult<audio_profile>
-aidl2legacy_AudioProfile_audio_profile(const media::AudioProfile& aidl, bool isInput);
-ConversionResult<media::AudioProfile>
+aidl2legacy_AudioProfile_audio_profile(
+ const media::audio::common::AudioProfile& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioProfile>
legacy2aidl_audio_profile_AudioProfile(const audio_profile& legacy, bool isInput);
ConversionResult<audio_gain>
diff --git a/media/libaudioclient/include/media/AidlConversionUtil.h b/media/libaudioclient/include/media/AidlConversionUtil.h
index c1a2be3..f9446ad 100644
--- a/media/libaudioclient/include/media/AidlConversionUtil.h
+++ b/media/libaudioclient/include/media/AidlConversionUtil.h
@@ -119,6 +119,47 @@
return output;
}
+/**
+ * A generic template that helps to "zip" two input containers of the same size
+ * into a single vector of converted types. The conversion function must
+ * thus accept two arguments.
+ */
+template<typename OutputContainer, typename InputContainer1,
+ typename InputContainer2, typename Func>
+ConversionResult<OutputContainer>
+convertContainers(const InputContainer1& input1, const InputContainer2& input2,
+ const Func& itemConversion) {
+ auto iter2 = input2.begin();
+ OutputContainer output;
+ auto ins = std::inserter(output, output.begin());
+ for (const auto& item1 : input1) {
+ RETURN_IF_ERROR(iter2 != input2.end() ? OK : BAD_VALUE);
+ *ins = VALUE_OR_RETURN(itemConversion(item1, *iter2++));
+ }
+ return output;
+}
+
+/**
+ * A generic template that helps to "unzip" a per-element conversion into
+ * a pair of elements into a pair of containers. The conversion function
+ * must emit a pair of elements.
+ */
+template<typename OutputContainer1, typename OutputContainer2,
+ typename InputContainer, typename Func>
+ConversionResult<std::pair<OutputContainer1, OutputContainer2>>
+convertContainerSplit(const InputContainer& input, const Func& itemConversion) {
+ OutputContainer1 output1;
+ OutputContainer2 output2;
+ auto ins1 = std::inserter(output1, output1.begin());
+ auto ins2 = std::inserter(output2, output2.begin());
+ for (const auto& item : input) {
+ auto out_pair = VALUE_OR_RETURN(itemConversion(item));
+ *ins1 = out_pair.first;
+ *ins2 = out_pair.second;
+ }
+ return std::make_pair(output1, output2);
+}
+
////////////////////////////////////////////////////////////////////////////////////////////////////
// The code below establishes:
// IntegralTypeOf<T>, which works for either integral types (in which case it evaluates to T), or
diff --git a/media/libaudiofoundation/AudioPort.cpp b/media/libaudiofoundation/AudioPort.cpp
index c70a6c2..74c9b10 100644
--- a/media/libaudiofoundation/AudioPort.cpp
+++ b/media/libaudiofoundation/AudioPort.cpp
@@ -210,8 +210,10 @@
parcelable->name = mName;
parcelable->type = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_type_t_AudioPortType(mType));
parcelable->role = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_role_t_AudioPortRole(mRole));
- parcelable->profiles = VALUE_OR_RETURN_STATUS(
+ auto aidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_AudioProfileVector(mProfiles, useInputChannelMask()));
+ parcelable->profiles = aidl.first;
+ parcelable->profilesSys = aidl.second;
parcelable->extraAudioDescriptors = mExtraAudioDescriptors;
parcelable->gains = VALUE_OR_RETURN_STATUS(legacy2aidl_AudioGains(mGains));
return OK;
@@ -228,7 +230,9 @@
mType = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioPortType_audio_port_type_t(parcelable.type));
mRole = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioPortRole_audio_port_role_t(parcelable.role));
mProfiles = VALUE_OR_RETURN_STATUS(
- aidl2legacy_AudioProfileVector(parcelable.profiles, useInputChannelMask()));
+ aidl2legacy_AudioProfileVector(
+ std::make_pair(parcelable.profiles, parcelable.profilesSys),
+ useInputChannelMask()));
mExtraAudioDescriptors = parcelable.extraAudioDescriptors;
mGains = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioGains(parcelable.gains));
return OK;
diff --git a/media/libaudiofoundation/AudioProfile.cpp b/media/libaudiofoundation/AudioProfile.cpp
index 2d44f4a..15f2d68 100644
--- a/media/libaudiofoundation/AudioProfile.cpp
+++ b/media/libaudiofoundation/AudioProfile.cpp
@@ -156,31 +156,38 @@
return *this;
}
-ConversionResult<media::AudioProfile>
+ConversionResult<AudioProfile::Aidl>
AudioProfile::toParcelable(bool isInput) const {
- media::AudioProfile parcelable;
+ media::audio::common::AudioProfile parcelable;
parcelable.name = mName;
- parcelable.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(mFormat));
+ parcelable.format = VALUE_OR_RETURN(
+ legacy2aidl_audio_format_t_AudioFormatDescription(mFormat));
+ // Note: legacy 'audio_profile' imposes a limit on the number of
+ // channel masks and sampling rates. That's why it's not used here
+ // and conversions are performed directly on the fields instead
+ // of using 'legacy2aidl_audio_profile_AudioProfile' from AidlConversion.
parcelable.channelMasks = VALUE_OR_RETURN(
convertContainer<std::vector<AudioChannelLayout>>(
mChannelMasks,
[isInput](audio_channel_mask_t m) {
return legacy2aidl_audio_channel_mask_t_AudioChannelLayout(m, isInput);
}));
- parcelable.samplingRates = VALUE_OR_RETURN(
+ parcelable.sampleRates = VALUE_OR_RETURN(
convertContainer<std::vector<int32_t>>(mSamplingRates,
convertIntegral<int32_t, uint32_t>));
- parcelable.isDynamicFormat = mIsDynamicFormat;
- parcelable.isDynamicChannels = mIsDynamicChannels;
- parcelable.isDynamicRate = mIsDynamicRate;
parcelable.encapsulationType = VALUE_OR_RETURN(
legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(mEncapsulationType));
- return parcelable;
+ media::AudioProfileSys parcelableSys;
+ parcelableSys.isDynamicFormat = mIsDynamicFormat;
+ parcelableSys.isDynamicChannels = mIsDynamicChannels;
+ parcelableSys.isDynamicRate = mIsDynamicRate;
+ return std::make_pair(parcelable, parcelableSys);
}
-ConversionResult<sp<AudioProfile>>
-AudioProfile::fromParcelable(const media::AudioProfile& parcelable, bool isInput) {
+ConversionResult<sp<AudioProfile>> AudioProfile::fromParcelable(
+ const AudioProfile::Aidl& aidl, bool isInput) {
sp<AudioProfile> legacy = new AudioProfile();
+ const auto& parcelable = aidl.first;
legacy->mName = parcelable.name;
legacy->mFormat = VALUE_OR_RETURN(
aidl2legacy_AudioFormatDescription_audio_format_t(parcelable.format));
@@ -190,23 +197,24 @@
return aidl2legacy_AudioChannelLayout_audio_channel_mask_t(l, isInput);
}));
legacy->mSamplingRates = VALUE_OR_RETURN(
- convertContainer<SampleRateSet>(parcelable.samplingRates,
+ convertContainer<SampleRateSet>(parcelable.sampleRates,
convertIntegral<uint32_t, int32_t>));
- legacy->mIsDynamicFormat = parcelable.isDynamicFormat;
- legacy->mIsDynamicChannels = parcelable.isDynamicChannels;
- legacy->mIsDynamicRate = parcelable.isDynamicRate;
legacy->mEncapsulationType = VALUE_OR_RETURN(
aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
parcelable.encapsulationType));
+ const auto& parcelableSys = aidl.second;
+ legacy->mIsDynamicFormat = parcelableSys.isDynamicFormat;
+ legacy->mIsDynamicChannels = parcelableSys.isDynamicChannels;
+ legacy->mIsDynamicRate = parcelableSys.isDynamicRate;
return legacy;
}
ConversionResult<sp<AudioProfile>>
-aidl2legacy_AudioProfile(const media::AudioProfile& aidl, bool isInput) {
+aidl2legacy_AudioProfile(const AudioProfile::Aidl& aidl, bool isInput) {
return AudioProfile::fromParcelable(aidl, isInput);
}
-ConversionResult<media::AudioProfile>
+ConversionResult<AudioProfile::Aidl>
legacy2aidl_AudioProfile(const sp<AudioProfile>& legacy, bool isInput) {
return legacy->toParcelable(isInput);
}
@@ -331,16 +339,19 @@
}
ConversionResult<AudioProfileVector>
-aidl2legacy_AudioProfileVector(const std::vector<media::AudioProfile>& aidl, bool isInput) {
- return convertContainer<AudioProfileVector>(aidl,
- [isInput](const media::AudioProfile& p) {
- return aidl2legacy_AudioProfile(p, isInput);
+aidl2legacy_AudioProfileVector(const AudioProfileVector::Aidl& aidl, bool isInput) {
+ return convertContainers<AudioProfileVector>(aidl.first, aidl.second,
+ [isInput](const media::audio::common::AudioProfile& p,
+ const media::AudioProfileSys& ps) {
+ return aidl2legacy_AudioProfile(std::make_pair(p, ps), isInput);
});
}
-ConversionResult<std::vector<media::AudioProfile>>
+ConversionResult<AudioProfileVector::Aidl>
legacy2aidl_AudioProfileVector(const AudioProfileVector& legacy, bool isInput) {
- return convertContainer<std::vector<media::AudioProfile>>(legacy,
+ return convertContainerSplit<
+ std::vector<media::audio::common::AudioProfile>,
+ std::vector<media::AudioProfileSys>>(legacy,
[isInput](const sp<AudioProfile>& p) {
return legacy2aidl_AudioProfile(p, isInput);
});
diff --git a/media/libaudiofoundation/include/media/AudioProfile.h b/media/libaudiofoundation/include/media/AudioProfile.h
index e34a49f..62670e4 100644
--- a/media/libaudiofoundation/include/media/AudioProfile.h
+++ b/media/libaudiofoundation/include/media/AudioProfile.h
@@ -17,11 +17,10 @@
#pragma once
#include <string>
+#include <utility>
#include <vector>
-#include <android/media/AudioProfile.h>
-#include <binder/Parcel.h>
-#include <binder/Parcelable.h>
+#include <android/media/AudioProfileSys.h>
#include <media/AidlConversion.h>
#include <media/AudioContainers.h>
#include <system/audio.h>
@@ -81,9 +80,10 @@
bool equals(const sp<AudioProfile>& other) const;
- ConversionResult<media::AudioProfile> toParcelable(bool isInput) const;
+ using Aidl = std::pair<media::audio::common::AudioProfile, media::AudioProfileSys>;
+ ConversionResult<Aidl> toParcelable(bool isInput) const;
static ConversionResult<sp<AudioProfile>> fromParcelable(
- const media::AudioProfile& parcelable, bool isInput);
+ const Aidl& aidl, bool isInput);
private:
@@ -104,8 +104,8 @@
// Conversion routines, according to AidlConversion.h conventions.
ConversionResult<sp<AudioProfile>>
-aidl2legacy_AudioProfile(const media::AudioProfile& aidl, bool isInput);
-ConversionResult<media::AudioProfile>
+aidl2legacy_AudioProfile(const AudioProfile::Aidl& aidl, bool isInput);
+ConversionResult<AudioProfile::Aidl>
legacy2aidl_AudioProfile(const sp<AudioProfile>& legacy, bool isInput);
class AudioProfileVector : public std::vector<sp<AudioProfile>>
@@ -134,14 +134,18 @@
virtual void dump(std::string *dst, int spaces) const;
bool equals(const AudioProfileVector& other) const;
+
+ using Aidl = std::pair<
+ std::vector<media::audio::common::AudioProfile>,
+ std::vector<media::AudioProfileSys>>;
};
bool operator == (const AudioProfile &left, const AudioProfile &right);
// Conversion routines, according to AidlConversion.h conventions.
ConversionResult<AudioProfileVector>
-aidl2legacy_AudioProfileVector(const std::vector<media::AudioProfile>& aidl, bool isInput);
-ConversionResult<std::vector<media::AudioProfile>>
+aidl2legacy_AudioProfileVector(const AudioProfileVector::Aidl& aidl, bool isInput);
+ConversionResult<AudioProfileVector::Aidl>
legacy2aidl_AudioProfileVector(const AudioProfileVector& legacy, bool isInput);
AudioProfileVector intersectAudioProfiles(const AudioProfileVector& profiles1,
diff --git a/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp b/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp
index 1696980..abafff1 100644
--- a/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp
+++ b/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp
@@ -75,6 +75,24 @@
return audioProfiles;
}
+TEST(AudioFoundationParcelableTest, ParcelingAudioProfile) {
+ sp<AudioProfile> profile = getAudioProfileVectorForTest()[0];
+ auto conv = legacy2aidl_AudioProfile(profile, false /*isInput*/);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = aidl2legacy_AudioProfile(conv.value(), false /*isInput*/);
+ ASSERT_TRUE(convBack.ok());
+ ASSERT_TRUE(profile->equals(convBack.value()));
+}
+
+TEST(AudioFoundationParcelableTest, ParcelingAudioProfileVector) {
+ AudioProfileVector profiles = getAudioProfileVectorForTest();
+ auto conv = legacy2aidl_AudioProfileVector(profiles, false /*isInput*/);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = aidl2legacy_AudioProfileVector(conv.value(), false /*isInput*/);
+ ASSERT_TRUE(convBack.ok());
+ ASSERT_TRUE(profiles.equals(convBack.value()));
+}
+
TEST(AudioFoundationParcelableTest, ParcelingAudioGain) {
Parcel data;
AudioGains audioGains = getAudioGainsForTest();