blob: 999e263439c3eae6988ed1a62ba2ba933beded35 [file] [log] [blame]
François Gaffie112b0af2015-11-19 16:13:25 +01001/*
jiabin3e277cc2019-09-10 14:27:34 -07002 * Copyright (C) 2019 The Android Open Source Project
François Gaffie112b0af2015-11-19 16:13:25 +01003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Mikhail Naganovfa69dc62018-07-27 09:58:58 -070017#include <set>
Mikhail Naganove50f6282018-07-26 16:20:43 -070018
jiabin9bb3a1e2019-08-19 10:10:17 -070019#define LOG_TAG "AudioProfile"
François Gaffie112b0af2015-11-19 16:13:25 +010020//#define LOG_NDEBUG 0
21
jiabin9bb3a1e2019-08-19 10:10:17 -070022#include <android-base/stringprintf.h>
jiabin06e4bab2019-07-29 10:13:34 -070023#include <media/AudioContainers.h>
jiabin9bb3a1e2019-08-19 10:10:17 -070024#include <media/AudioProfile.h>
25#include <media/TypeConverter.h>
Mikhail Naganove50f6282018-07-26 16:20:43 -070026#include <utils/Errors.h>
27
François Gaffie112b0af2015-11-19 16:13:25 +010028namespace android {
29
Mikhail Naganov57bd06f2021-08-10 16:41:54 -070030using media::audio::common::AudioChannelLayout;
31
jiabin9bb3a1e2019-08-19 10:10:17 -070032bool operator == (const AudioProfile &left, const AudioProfile &right)
Mikhail Naganove50f6282018-07-26 16:20:43 -070033{
jiabin9bb3a1e2019-08-19 10:10:17 -070034 return (left.getFormat() == right.getFormat()) &&
35 (left.getChannels() == right.getChannels()) &&
36 (left.getSampleRates() == right.getSampleRates());
Mikhail Naganove50f6282018-07-26 16:20:43 -070037}
38
jiabin9bb3a1e2019-08-19 10:10:17 -070039// static
40sp<AudioProfile> AudioProfile::createFullDynamic(audio_format_t dynamicFormat)
Mikhail Naganov21b43362018-06-04 10:37:09 -070041{
jiabin9bb3a1e2019-08-19 10:10:17 -070042 AudioProfile* dynamicProfile = new AudioProfile(dynamicFormat,
jiabin06e4bab2019-07-29 10:13:34 -070043 ChannelMaskSet(), SampleRateSet());
Mikhail Naganov21b43362018-06-04 10:37:09 -070044 dynamicProfile->setDynamicFormat(true);
45 dynamicProfile->setDynamicChannels(true);
46 dynamicProfile->setDynamicRate(true);
47 return dynamicProfile;
48}
49
Mikhail Naganove50f6282018-07-26 16:20:43 -070050AudioProfile::AudioProfile(audio_format_t format,
51 audio_channel_mask_t channelMasks,
52 uint32_t samplingRate) :
jiabin9bb3a1e2019-08-19 10:10:17 -070053 mName(""),
Mikhail Naganove50f6282018-07-26 16:20:43 -070054 mFormat(format)
55{
jiabin06e4bab2019-07-29 10:13:34 -070056 mChannelMasks.insert(channelMasks);
57 mSamplingRates.insert(samplingRate);
Mikhail Naganove50f6282018-07-26 16:20:43 -070058}
59
60AudioProfile::AudioProfile(audio_format_t format,
jiabin06e4bab2019-07-29 10:13:34 -070061 const ChannelMaskSet &channelMasks,
62 const SampleRateSet &samplingRateCollection) :
jiabin82e56932021-03-05 06:35:19 +000063 AudioProfile(format, channelMasks, samplingRateCollection,
64 AUDIO_ENCAPSULATION_TYPE_NONE) {}
65
66AudioProfile::AudioProfile(audio_format_t format,
67 const ChannelMaskSet &channelMasks,
68 const SampleRateSet &samplingRateCollection,
69 audio_encapsulation_type_t encapsulationType) :
jiabin9bb3a1e2019-08-19 10:10:17 -070070 mName(""),
Mikhail Naganove50f6282018-07-26 16:20:43 -070071 mFormat(format),
72 mChannelMasks(channelMasks),
jiabin82e56932021-03-05 06:35:19 +000073 mSamplingRates(samplingRateCollection),
74 mEncapsulationType(encapsulationType) {}
Mikhail Naganove50f6282018-07-26 16:20:43 -070075
jiabin06e4bab2019-07-29 10:13:34 -070076void AudioProfile::setChannels(const ChannelMaskSet &channelMasks)
Mikhail Naganove50f6282018-07-26 16:20:43 -070077{
78 if (mIsDynamicChannels) {
79 mChannelMasks = channelMasks;
80 }
81}
82
jiabin06e4bab2019-07-29 10:13:34 -070083void AudioProfile::setSampleRates(const SampleRateSet &sampleRates)
Mikhail Naganove50f6282018-07-26 16:20:43 -070084{
85 if (mIsDynamicRate) {
86 mSamplingRates = sampleRates;
87 }
88}
89
90void AudioProfile::clear()
91{
92 if (mIsDynamicChannels) {
93 mChannelMasks.clear();
94 }
95 if (mIsDynamicRate) {
96 mSamplingRates.clear();
97 }
98}
99
jiabin9bb3a1e2019-08-19 10:10:17 -0700100void AudioProfile::dump(std::string *dst, int spaces) const
François Gaffie112b0af2015-11-19 16:13:25 +0100101{
Mikhail Naganov0dbe87b2021-12-01 02:03:31 +0000102 dst->append(base::StringPrintf("\"%s\"; ", mName.c_str()));
103 dst->append(base::StringPrintf("%s%s%s%s", mIsDynamicFormat ? "[dynamic format]" : "",
François Gaffie112b0af2015-11-19 16:13:25 +0100104 mIsDynamicChannels ? "[dynamic channels]" : "",
Mikhail Naganov0dbe87b2021-12-01 02:03:31 +0000105 mIsDynamicRate ? "[dynamic rates]" : "", isDynamic() ? "; " : ""));
106 dst->append(base::StringPrintf("%s (0x%x)\n", audio_format_to_string(mFormat), mFormat));
107
jiabin06e4bab2019-07-29 10:13:34 -0700108 if (!mSamplingRates.empty()) {
Mikhail Naganov0dbe87b2021-12-01 02:03:31 +0000109 dst->append(base::StringPrintf("%*ssampling rates: ", spaces, ""));
jiabin06e4bab2019-07-29 10:13:34 -0700110 for (auto it = mSamplingRates.begin(); it != mSamplingRates.end();) {
jiabin9bb3a1e2019-08-19 10:10:17 -0700111 dst->append(base::StringPrintf("%d", *it));
jiabin06e4bab2019-07-29 10:13:34 -0700112 dst->append(++it == mSamplingRates.end() ? "" : ", ");
François Gaffie112b0af2015-11-19 16:13:25 +0100113 }
Andy Hungbb54e202018-10-05 11:42:02 -0700114 dst->append("\n");
François Gaffie112b0af2015-11-19 16:13:25 +0100115 }
116
jiabin06e4bab2019-07-29 10:13:34 -0700117 if (!mChannelMasks.empty()) {
Mikhail Naganov0dbe87b2021-12-01 02:03:31 +0000118 dst->append(base::StringPrintf("%*schannel masks: ", spaces, ""));
jiabin06e4bab2019-07-29 10:13:34 -0700119 for (auto it = mChannelMasks.begin(); it != mChannelMasks.end();) {
jiabin9bb3a1e2019-08-19 10:10:17 -0700120 dst->append(base::StringPrintf("0x%04x", *it));
jiabin06e4bab2019-07-29 10:13:34 -0700121 dst->append(++it == mChannelMasks.end() ? "" : ", ");
François Gaffie112b0af2015-11-19 16:13:25 +0100122 }
Andy Hungbb54e202018-10-05 11:42:02 -0700123 dst->append("\n");
François Gaffie112b0af2015-11-19 16:13:25 +0100124 }
jiabin82e56932021-03-05 06:35:19 +0000125
126 dst->append(base::StringPrintf(
Mikhail Naganov0dbe87b2021-12-01 02:03:31 +0000127 "%*s%s\n", spaces, "", audio_encapsulation_type_to_string(mEncapsulationType)));
François Gaffie112b0af2015-11-19 16:13:25 +0100128}
129
Dorin Drimus94d94412022-02-02 09:05:02 +0100130bool AudioProfile::equals(const sp<AudioProfile>& other, bool ignoreDynamicFlags) const
jiabin49e69a12019-10-15 16:04:13 -0700131{
132 return other != nullptr &&
133 mName.compare(other->mName) == 0 &&
134 mFormat == other->getFormat() &&
135 mChannelMasks == other->getChannels() &&
136 mSamplingRates == other->getSampleRates() &&
Dorin Drimus94d94412022-02-02 09:05:02 +0100137 (ignoreDynamicFlags ||
138 (mIsDynamicFormat == other->isDynamicFormat() &&
139 mIsDynamicChannels == other->isDynamicChannels() &&
140 mIsDynamicRate == other->isDynamicRate())) &&
jiabin82e56932021-03-05 06:35:19 +0000141 mEncapsulationType == other->getEncapsulationType();
jiabin49e69a12019-10-15 16:04:13 -0700142}
143
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800144AudioProfile& AudioProfile::operator=(const AudioProfile& other) {
145 mName = other.mName;
146 mFormat = other.mFormat;
147 mChannelMasks = other.mChannelMasks;
148 mSamplingRates = other.mSamplingRates;
jiabin82e56932021-03-05 06:35:19 +0000149 mEncapsulationType = other.mEncapsulationType;
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800150 mIsDynamicFormat = other.mIsDynamicFormat;
151 mIsDynamicChannels = other.mIsDynamicChannels;
152 mIsDynamicRate = other.mIsDynamicRate;
153 return *this;
jiabin17058fa2019-10-08 17:33:38 -0700154}
155
Mikhail Naganov89818ba2021-09-21 20:37:13 +0000156ConversionResult<AudioProfile::Aidl>
Mikhail Naganovde3fa182021-07-30 15:06:42 -0700157AudioProfile::toParcelable(bool isInput) const {
Dorin Drimusf2196d82022-01-03 12:11:18 +0100158 media::audio::common::AudioProfile parcelable = VALUE_OR_RETURN(toCommonParcelable(isInput));
159 media::AudioProfileSys parcelableSys;
160 parcelableSys.isDynamicFormat = mIsDynamicFormat;
161 parcelableSys.isDynamicChannels = mIsDynamicChannels;
162 parcelableSys.isDynamicRate = mIsDynamicRate;
163 return std::make_pair(parcelable, parcelableSys);
164}
165
166ConversionResult<sp<AudioProfile>> AudioProfile::fromParcelable(
167 const AudioProfile::Aidl& aidl, bool isInput) {
168 sp<AudioProfile> legacy = VALUE_OR_RETURN(fromCommonParcelable(aidl.first, isInput));
169 const auto& parcelableSys = aidl.second;
170 legacy->mIsDynamicFormat = parcelableSys.isDynamicFormat;
171 legacy->mIsDynamicChannels = parcelableSys.isDynamicChannels;
172 legacy->mIsDynamicRate = parcelableSys.isDynamicRate;
173 return legacy;
174}
175
176ConversionResult<media::audio::common::AudioProfile>
177AudioProfile::toCommonParcelable(bool isInput) const {
Mikhail Naganov89818ba2021-09-21 20:37:13 +0000178 media::audio::common::AudioProfile parcelable;
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800179 parcelable.name = mName;
Mikhail Naganov89818ba2021-09-21 20:37:13 +0000180 parcelable.format = VALUE_OR_RETURN(
181 legacy2aidl_audio_format_t_AudioFormatDescription(mFormat));
182 // Note: legacy 'audio_profile' imposes a limit on the number of
183 // channel masks and sampling rates. That's why it's not used here
184 // and conversions are performed directly on the fields instead
185 // of using 'legacy2aidl_audio_profile_AudioProfile' from AidlConversion.
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800186 parcelable.channelMasks = VALUE_OR_RETURN(
Mikhail Naganov57bd06f2021-08-10 16:41:54 -0700187 convertContainer<std::vector<AudioChannelLayout>>(
Dorin Drimusf2196d82022-01-03 12:11:18 +0100188 mChannelMasks,
189 [isInput](audio_channel_mask_t m) {
190 return legacy2aidl_audio_channel_mask_t_AudioChannelLayout(m, isInput);
191 }));
Mikhail Naganov89818ba2021-09-21 20:37:13 +0000192 parcelable.sampleRates = VALUE_OR_RETURN(
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800193 convertContainer<std::vector<int32_t>>(mSamplingRates,
194 convertIntegral<int32_t, uint32_t>));
jiabin82e56932021-03-05 06:35:19 +0000195 parcelable.encapsulationType = VALUE_OR_RETURN(
196 legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(mEncapsulationType));
Dorin Drimusf2196d82022-01-03 12:11:18 +0100197 return parcelable;
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800198}
199
Dorin Drimusf2196d82022-01-03 12:11:18 +0100200ConversionResult<sp<AudioProfile>> AudioProfile::fromCommonParcelable(
201 const media::audio::common::AudioProfile& aidl, bool isInput) {
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800202 sp<AudioProfile> legacy = new AudioProfile();
Dorin Drimusf2196d82022-01-03 12:11:18 +0100203 legacy->mName = aidl.name;
Mikhail Naganovb60bd1b2021-07-15 17:31:43 -0700204 legacy->mFormat = VALUE_OR_RETURN(
Dorin Drimusf2196d82022-01-03 12:11:18 +0100205 aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800206 legacy->mChannelMasks = VALUE_OR_RETURN(
Dorin Drimusf2196d82022-01-03 12:11:18 +0100207 convertContainer<ChannelMaskSet>(aidl.channelMasks,
208 [isInput](const AudioChannelLayout& l) {
209 return aidl2legacy_AudioChannelLayout_audio_channel_mask_t(l, isInput);
210 }));
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800211 legacy->mSamplingRates = VALUE_OR_RETURN(
Dorin Drimusf2196d82022-01-03 12:11:18 +0100212 convertContainer<SampleRateSet>(aidl.sampleRates,
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800213 convertIntegral<uint32_t, int32_t>));
jiabin82e56932021-03-05 06:35:19 +0000214 legacy->mEncapsulationType = VALUE_OR_RETURN(
215 aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
Dorin Drimusf2196d82022-01-03 12:11:18 +0100216 aidl.encapsulationType));
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800217 return legacy;
218}
219
220ConversionResult<sp<AudioProfile>>
Mikhail Naganov89818ba2021-09-21 20:37:13 +0000221aidl2legacy_AudioProfile(const AudioProfile::Aidl& aidl, bool isInput) {
Mikhail Naganovde3fa182021-07-30 15:06:42 -0700222 return AudioProfile::fromParcelable(aidl, isInput);
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800223}
224
Mikhail Naganov89818ba2021-09-21 20:37:13 +0000225ConversionResult<AudioProfile::Aidl>
Mikhail Naganovde3fa182021-07-30 15:06:42 -0700226legacy2aidl_AudioProfile(const sp<AudioProfile>& legacy, bool isInput) {
227 return legacy->toParcelable(isInput);
jiabin17058fa2019-10-08 17:33:38 -0700228}
229
Dorin Drimusf2196d82022-01-03 12:11:18 +0100230ConversionResult<sp<AudioProfile>>
231aidl2legacy_AudioProfile_common(const media::audio::common::AudioProfile& aidl, bool isInput) {
232 return AudioProfile::fromCommonParcelable(aidl, isInput);
233}
234
235ConversionResult<media::audio::common::AudioProfile>
236legacy2aidl_AudioProfile_common(const sp<AudioProfile>& legacy, bool isInput) {
237 return legacy->toCommonParcelable(isInput);
238}
239
jiabin3e277cc2019-09-10 14:27:34 -0700240ssize_t AudioProfileVector::add(const sp<AudioProfile> &profile)
Mikhail Naganove50f6282018-07-26 16:20:43 -0700241{
jiabin06e4bab2019-07-29 10:13:34 -0700242 ssize_t index = size();
243 push_back(profile);
Mikhail Naganove50f6282018-07-26 16:20:43 -0700244 return index;
245}
246
jiabin3e277cc2019-09-10 14:27:34 -0700247void AudioProfileVector::clearProfiles()
Mikhail Naganove50f6282018-07-26 16:20:43 -0700248{
jiabin06e4bab2019-07-29 10:13:34 -0700249 for (auto it = begin(); it != end();) {
250 if ((*it)->isDynamicFormat() && (*it)->hasValidFormat()) {
251 it = erase(it);
252 } else {
253 (*it)->clear();
254 ++it;
Mikhail Naganove50f6282018-07-26 16:20:43 -0700255 }
Mikhail Naganove50f6282018-07-26 16:20:43 -0700256 }
257}
258
jiabin3e277cc2019-09-10 14:27:34 -0700259sp<AudioProfile> AudioProfileVector::getFirstValidProfile() const
Mikhail Naganove50f6282018-07-26 16:20:43 -0700260{
jiabin06e4bab2019-07-29 10:13:34 -0700261 for (const auto &profile : *this) {
262 if (profile->isValid()) {
263 return profile;
Mikhail Naganove50f6282018-07-26 16:20:43 -0700264 }
265 }
jiabin06e4bab2019-07-29 10:13:34 -0700266 return nullptr;
Mikhail Naganove50f6282018-07-26 16:20:43 -0700267}
268
jiabin3e277cc2019-09-10 14:27:34 -0700269sp<AudioProfile> AudioProfileVector::getFirstValidProfileFor(audio_format_t format) const
Mikhail Naganove50f6282018-07-26 16:20:43 -0700270{
jiabin06e4bab2019-07-29 10:13:34 -0700271 for (const auto &profile : *this) {
272 if (profile->isValid() && profile->getFormat() == format) {
273 return profile;
Mikhail Naganove50f6282018-07-26 16:20:43 -0700274 }
275 }
jiabin06e4bab2019-07-29 10:13:34 -0700276 return nullptr;
Mikhail Naganove50f6282018-07-26 16:20:43 -0700277}
278
jiabin3e277cc2019-09-10 14:27:34 -0700279FormatVector AudioProfileVector::getSupportedFormats() const
Mikhail Naganove50f6282018-07-26 16:20:43 -0700280{
281 FormatVector supportedFormats;
jiabin06e4bab2019-07-29 10:13:34 -0700282 for (const auto &profile : *this) {
283 if (profile->hasValidFormat()) {
284 supportedFormats.push_back(profile->getFormat());
Mikhail Naganove50f6282018-07-26 16:20:43 -0700285 }
286 }
287 return supportedFormats;
288}
289
jiabin3e277cc2019-09-10 14:27:34 -0700290bool AudioProfileVector::hasDynamicChannelsFor(audio_format_t format) const
Mikhail Naganove50f6282018-07-26 16:20:43 -0700291{
jiabin06e4bab2019-07-29 10:13:34 -0700292 for (const auto &profile : *this) {
Mikhail Naganove50f6282018-07-26 16:20:43 -0700293 if (profile->getFormat() == format && profile->isDynamicChannels()) {
294 return true;
295 }
296 }
297 return false;
298}
299
jiabin3e277cc2019-09-10 14:27:34 -0700300bool AudioProfileVector::hasDynamicFormat() const
jiabin9bb3a1e2019-08-19 10:10:17 -0700301{
302 for (const auto &profile : *this) {
303 if (profile->isDynamicFormat()) {
304 return true;
305 }
306 }
307 return false;
308}
309
jiabin3e277cc2019-09-10 14:27:34 -0700310bool AudioProfileVector::hasDynamicProfile() const
Mikhail Naganove50f6282018-07-26 16:20:43 -0700311{
jiabin06e4bab2019-07-29 10:13:34 -0700312 for (const auto &profile : *this) {
313 if (profile->isDynamic()) {
Mikhail Naganove50f6282018-07-26 16:20:43 -0700314 return true;
315 }
316 }
317 return false;
318}
319
jiabin3e277cc2019-09-10 14:27:34 -0700320bool AudioProfileVector::hasDynamicRateFor(audio_format_t format) const
Mikhail Naganove50f6282018-07-26 16:20:43 -0700321{
jiabin06e4bab2019-07-29 10:13:34 -0700322 for (const auto &profile : *this) {
Mikhail Naganove50f6282018-07-26 16:20:43 -0700323 if (profile->getFormat() == format && profile->isDynamicRate()) {
324 return true;
325 }
326 }
327 return false;
328}
329
jiabinf26596b2023-04-12 18:56:39 +0000330const SampleRateSet AudioProfileVector::getSampleRatesFor(audio_format_t format) const {
331 for (const auto& profile : *this) {
332 if (profile->getFormat() == format) {
333 return profile->getSampleRates();
334 }
335 }
336 return {};
337}
338
339const ChannelMaskSet AudioProfileVector::getChannelMasksFor(audio_format_t format) const {
340 for (const auto& profile : *this) {
341 if (profile->getFormat() == format) {
342 return profile->getChannels();
343 }
344 }
345 return {};
346}
347
Dorin Drimus94d94412022-02-02 09:05:02 +0100348bool AudioProfileVector::contains(const sp<AudioProfile>& profile, bool ignoreDynamicFlags) const
jiabinb4fed192020-09-22 14:45:40 -0700349{
350 for (const auto& audioProfile : *this) {
Dorin Drimus94d94412022-02-02 09:05:02 +0100351 if (audioProfile->equals(profile, ignoreDynamicFlags)) {
jiabinb4fed192020-09-22 14:45:40 -0700352 return true;
353 }
354 }
355 return false;
356}
357
jiabin3e277cc2019-09-10 14:27:34 -0700358void AudioProfileVector::dump(std::string *dst, int spaces) const
Mikhail Naganove50f6282018-07-26 16:20:43 -0700359{
Mikhail Naganov0dbe87b2021-12-01 02:03:31 +0000360 dst->append(base::StringPrintf("%*s- Profiles (%zu):\n", spaces - 2, "", size()));
Mikhail Naganove50f6282018-07-26 16:20:43 -0700361 for (size_t i = 0; i < size(); i++) {
Mikhail Naganov0f413b22021-12-02 05:29:27 +0000362 const std::string prefix = base::StringPrintf("%*s %zu. ", spaces, "", i + 1);
Mikhail Naganov0dbe87b2021-12-01 02:03:31 +0000363 dst->append(prefix);
jiabin9bb3a1e2019-08-19 10:10:17 -0700364 std::string profileStr;
Mikhail Naganov0dbe87b2021-12-01 02:03:31 +0000365 at(i)->dump(&profileStr, prefix.size());
jiabin9bb3a1e2019-08-19 10:10:17 -0700366 dst->append(profileStr);
Mikhail Naganove50f6282018-07-26 16:20:43 -0700367 }
368}
369
jiabin49e69a12019-10-15 16:04:13 -0700370bool AudioProfileVector::equals(const AudioProfileVector& other) const
371{
372 return std::equal(begin(), end(), other.begin(), other.end(),
373 [](const sp<AudioProfile>& left, const sp<AudioProfile>& right) {
374 return left->equals(right);
375 });
376}
377
Dorin Drimus94d94412022-02-02 09:05:02 +0100378void AudioProfileVector::addAllValidProfiles(const AudioProfileVector& audioProfiles) {
379 for (const auto& audioProfile : audioProfiles) {
380 if (audioProfile->isValid() && !contains(audioProfile, true /*ignoreDynamicFlags*/)) {
381 add(audioProfile);
382 }
383 }
384}
385
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800386ConversionResult<AudioProfileVector>
Mikhail Naganov89818ba2021-09-21 20:37:13 +0000387aidl2legacy_AudioProfileVector(const AudioProfileVector::Aidl& aidl, bool isInput) {
388 return convertContainers<AudioProfileVector>(aidl.first, aidl.second,
389 [isInput](const media::audio::common::AudioProfile& p,
390 const media::AudioProfileSys& ps) {
391 return aidl2legacy_AudioProfile(std::make_pair(p, ps), isInput);
Mikhail Naganovde3fa182021-07-30 15:06:42 -0700392 });
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800393}
394
Mikhail Naganov89818ba2021-09-21 20:37:13 +0000395ConversionResult<AudioProfileVector::Aidl>
Mikhail Naganovde3fa182021-07-30 15:06:42 -0700396legacy2aidl_AudioProfileVector(const AudioProfileVector& legacy, bool isInput) {
Mikhail Naganov89818ba2021-09-21 20:37:13 +0000397 return convertContainerSplit<
398 std::vector<media::audio::common::AudioProfile>,
399 std::vector<media::AudioProfileSys>>(legacy,
Mikhail Naganovde3fa182021-07-30 15:06:42 -0700400 [isInput](const sp<AudioProfile>& p) {
401 return legacy2aidl_AudioProfile(p, isInput);
402 });
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800403}
404
jiabinbce0c1d2020-10-05 11:20:18 -0700405AudioProfileVector intersectAudioProfiles(const AudioProfileVector& profiles1,
406 const AudioProfileVector& profiles2)
407{
408 std::map<audio_format_t, std::pair<ChannelMaskSet, SampleRateSet>> infos2;
409 for (const auto& profile : profiles2) {
410 infos2.emplace(profile->getFormat(),
411 std::make_pair(profile->getChannels(), profile->getSampleRates()));
412 }
413 AudioProfileVector profiles;
414 for (const auto& profile : profiles1) {
415 const auto it = infos2.find(profile->getFormat());
416 if (it == infos2.end()) {
417 continue;
418 }
419 ChannelMaskSet channelMasks = SetIntersection(profile->getChannels(), it->second.first);
420 if (channelMasks.empty()) {
421 continue;
422 }
423 SampleRateSet sampleRates = SetIntersection(profile->getSampleRates(), it->second.second);
424 if (sampleRates.empty()) {
425 continue;
426 }
427 profiles.push_back(new AudioProfile(profile->getFormat(), channelMasks, sampleRates));
428 }
429 return profiles;
430}
431
Mikhail Naganov1b2a7942017-12-08 10:18:09 -0800432} // namespace android