1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
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
17 #include <set>
18
19 #define LOG_TAG "AudioProfile"
20 //#define LOG_NDEBUG 0
21
22 #include <android-base/stringprintf.h>
23 #include <media/AudioContainers.h>
24 #include <media/AudioProfile.h>
25 #include <media/TypeConverter.h>
26 #include <utils/Errors.h>
27
28 namespace android {
29
operator ==(const AudioProfile & left,const AudioProfile & right)30 bool operator == (const AudioProfile &left, const AudioProfile &right)
31 {
32 return (left.getFormat() == right.getFormat()) &&
33 (left.getChannels() == right.getChannels()) &&
34 (left.getSampleRates() == right.getSampleRates());
35 }
36
37 // static
createFullDynamic(audio_format_t dynamicFormat)38 sp<AudioProfile> AudioProfile::createFullDynamic(audio_format_t dynamicFormat)
39 {
40 AudioProfile* dynamicProfile = new AudioProfile(dynamicFormat,
41 ChannelMaskSet(), SampleRateSet());
42 dynamicProfile->setDynamicFormat(true);
43 dynamicProfile->setDynamicChannels(true);
44 dynamicProfile->setDynamicRate(true);
45 return dynamicProfile;
46 }
47
AudioProfile(audio_format_t format,audio_channel_mask_t channelMasks,uint32_t samplingRate)48 AudioProfile::AudioProfile(audio_format_t format,
49 audio_channel_mask_t channelMasks,
50 uint32_t samplingRate) :
51 mName(""),
52 mFormat(format)
53 {
54 mChannelMasks.insert(channelMasks);
55 mSamplingRates.insert(samplingRate);
56 }
57
AudioProfile(audio_format_t format,const ChannelMaskSet & channelMasks,const SampleRateSet & samplingRateCollection)58 AudioProfile::AudioProfile(audio_format_t format,
59 const ChannelMaskSet &channelMasks,
60 const SampleRateSet &samplingRateCollection) :
61 mName(""),
62 mFormat(format),
63 mChannelMasks(channelMasks),
64 mSamplingRates(samplingRateCollection) {}
65
setChannels(const ChannelMaskSet & channelMasks)66 void AudioProfile::setChannels(const ChannelMaskSet &channelMasks)
67 {
68 if (mIsDynamicChannels) {
69 mChannelMasks = channelMasks;
70 }
71 }
72
setSampleRates(const SampleRateSet & sampleRates)73 void AudioProfile::setSampleRates(const SampleRateSet &sampleRates)
74 {
75 if (mIsDynamicRate) {
76 mSamplingRates = sampleRates;
77 }
78 }
79
clear()80 void AudioProfile::clear()
81 {
82 if (mIsDynamicChannels) {
83 mChannelMasks.clear();
84 }
85 if (mIsDynamicRate) {
86 mSamplingRates.clear();
87 }
88 }
89
dump(std::string * dst,int spaces) const90 void AudioProfile::dump(std::string *dst, int spaces) const
91 {
92 dst->append(base::StringPrintf("%s%s%s\n", mIsDynamicFormat ? "[dynamic format]" : "",
93 mIsDynamicChannels ? "[dynamic channels]" : "",
94 mIsDynamicRate ? "[dynamic rates]" : ""));
95 if (mName.length() != 0) {
96 dst->append(base::StringPrintf("%*s- name: %s\n", spaces, "", mName.c_str()));
97 }
98 std::string formatLiteral;
99 if (FormatConverter::toString(mFormat, formatLiteral)) {
100 dst->append(base::StringPrintf("%*s- format: %s\n", spaces, "", formatLiteral.c_str()));
101 }
102 if (!mSamplingRates.empty()) {
103 dst->append(base::StringPrintf("%*s- sampling rates:", spaces, ""));
104 for (auto it = mSamplingRates.begin(); it != mSamplingRates.end();) {
105 dst->append(base::StringPrintf("%d", *it));
106 dst->append(++it == mSamplingRates.end() ? "" : ", ");
107 }
108 dst->append("\n");
109 }
110
111 if (!mChannelMasks.empty()) {
112 dst->append(base::StringPrintf("%*s- channel masks:", spaces, ""));
113 for (auto it = mChannelMasks.begin(); it != mChannelMasks.end();) {
114 dst->append(base::StringPrintf("0x%04x", *it));
115 dst->append(++it == mChannelMasks.end() ? "" : ", ");
116 }
117 dst->append("\n");
118 }
119 }
120
equals(const sp<AudioProfile> & other) const121 bool AudioProfile::equals(const sp<AudioProfile>& other) const
122 {
123 return other != nullptr &&
124 mName.compare(other->mName) == 0 &&
125 mFormat == other->getFormat() &&
126 mChannelMasks == other->getChannels() &&
127 mSamplingRates == other->getSampleRates() &&
128 mIsDynamicFormat == other->isDynamicFormat() &&
129 mIsDynamicChannels == other->isDynamicChannels() &&
130 mIsDynamicRate == other->isDynamicRate();
131 }
132
writeToParcel(Parcel * parcel) const133 status_t AudioProfile::writeToParcel(Parcel *parcel) const
134 {
135 status_t status = NO_ERROR;
136 if ((status = parcel->writeUtf8AsUtf16(mName)) != NO_ERROR) return status;
137 if ((status = parcel->writeUint32(mFormat)) != NO_ERROR) return status;
138 std::vector<int> values(mChannelMasks.begin(), mChannelMasks.end());
139 if ((status = parcel->writeInt32Vector(values)) != NO_ERROR) return status;
140 values.clear();
141 values.assign(mSamplingRates.begin(), mSamplingRates.end());
142 if ((status = parcel->writeInt32Vector(values)) != NO_ERROR) return status;
143 if ((status = parcel->writeBool(mIsDynamicFormat)) != NO_ERROR) return status;
144 if ((status = parcel->writeBool(mIsDynamicChannels)) != NO_ERROR) return status;
145 if ((status = parcel->writeBool(mIsDynamicRate)) != NO_ERROR) return status;
146 return status;
147 }
148
readFromParcel(const Parcel * parcel)149 status_t AudioProfile::readFromParcel(const Parcel *parcel)
150 {
151 status_t status = NO_ERROR;
152 if ((status = parcel->readUtf8FromUtf16(&mName)) != NO_ERROR) return status;
153 static_assert(sizeof(mFormat) == sizeof(uint32_t));
154 if ((status = parcel->readUint32(reinterpret_cast<uint32_t*>(&mFormat))) != NO_ERROR) {
155 return status;
156 }
157 std::vector<int> values;
158 if ((status = parcel->readInt32Vector(&values)) != NO_ERROR) return status;
159 mChannelMasks.clear();
160 mChannelMasks.insert(values.begin(), values.end());
161 values.clear();
162 if ((status = parcel->readInt32Vector(&values)) != NO_ERROR) return status;
163 mSamplingRates.clear();
164 mSamplingRates.insert(values.begin(), values.end());
165 if ((status = parcel->readBool(&mIsDynamicFormat)) != NO_ERROR) return status;
166 if ((status = parcel->readBool(&mIsDynamicChannels)) != NO_ERROR) return status;
167 if ((status = parcel->readBool(&mIsDynamicRate)) != NO_ERROR) return status;
168 return status;
169 }
170
add(const sp<AudioProfile> & profile)171 ssize_t AudioProfileVector::add(const sp<AudioProfile> &profile)
172 {
173 ssize_t index = size();
174 push_back(profile);
175 return index;
176 }
177
clearProfiles()178 void AudioProfileVector::clearProfiles()
179 {
180 for (auto it = begin(); it != end();) {
181 if ((*it)->isDynamicFormat() && (*it)->hasValidFormat()) {
182 it = erase(it);
183 } else {
184 (*it)->clear();
185 ++it;
186 }
187 }
188 }
189
getFirstValidProfile() const190 sp<AudioProfile> AudioProfileVector::getFirstValidProfile() const
191 {
192 for (const auto &profile : *this) {
193 if (profile->isValid()) {
194 return profile;
195 }
196 }
197 return nullptr;
198 }
199
getFirstValidProfileFor(audio_format_t format) const200 sp<AudioProfile> AudioProfileVector::getFirstValidProfileFor(audio_format_t format) const
201 {
202 for (const auto &profile : *this) {
203 if (profile->isValid() && profile->getFormat() == format) {
204 return profile;
205 }
206 }
207 return nullptr;
208 }
209
getSupportedFormats() const210 FormatVector AudioProfileVector::getSupportedFormats() const
211 {
212 FormatVector supportedFormats;
213 for (const auto &profile : *this) {
214 if (profile->hasValidFormat()) {
215 supportedFormats.push_back(profile->getFormat());
216 }
217 }
218 return supportedFormats;
219 }
220
hasDynamicChannelsFor(audio_format_t format) const221 bool AudioProfileVector::hasDynamicChannelsFor(audio_format_t format) const
222 {
223 for (const auto &profile : *this) {
224 if (profile->getFormat() == format && profile->isDynamicChannels()) {
225 return true;
226 }
227 }
228 return false;
229 }
230
hasDynamicFormat() const231 bool AudioProfileVector::hasDynamicFormat() const
232 {
233 for (const auto &profile : *this) {
234 if (profile->isDynamicFormat()) {
235 return true;
236 }
237 }
238 return false;
239 }
240
hasDynamicProfile() const241 bool AudioProfileVector::hasDynamicProfile() const
242 {
243 for (const auto &profile : *this) {
244 if (profile->isDynamic()) {
245 return true;
246 }
247 }
248 return false;
249 }
250
hasDynamicRateFor(audio_format_t format) const251 bool AudioProfileVector::hasDynamicRateFor(audio_format_t format) const
252 {
253 for (const auto &profile : *this) {
254 if (profile->getFormat() == format && profile->isDynamicRate()) {
255 return true;
256 }
257 }
258 return false;
259 }
260
dump(std::string * dst,int spaces) const261 void AudioProfileVector::dump(std::string *dst, int spaces) const
262 {
263 dst->append(base::StringPrintf("%*s- Profiles:\n", spaces, ""));
264 for (size_t i = 0; i < size(); i++) {
265 dst->append(base::StringPrintf("%*sProfile %zu:", spaces + 4, "", i));
266 std::string profileStr;
267 at(i)->dump(&profileStr, spaces + 8);
268 dst->append(profileStr);
269 }
270 }
271
writeToParcel(Parcel * parcel) const272 status_t AudioProfileVector::writeToParcel(Parcel *parcel) const
273 {
274 status_t status = NO_ERROR;
275 if ((status = parcel->writeVectorSize(*this)) != NO_ERROR) return status;
276 for (const auto &audioProfile : *this) {
277 if ((status = parcel->writeParcelable(*audioProfile)) != NO_ERROR) {
278 break;
279 }
280 }
281 return status;
282 }
283
readFromParcel(const Parcel * parcel)284 status_t AudioProfileVector::readFromParcel(const Parcel *parcel)
285 {
286 status_t status = NO_ERROR;
287 this->clear();
288 if ((status = parcel->resizeOutVector(this)) != NO_ERROR) return status;
289 for (size_t i = 0; i < this->size(); ++i) {
290 this->at(i) = new AudioProfile(AUDIO_FORMAT_DEFAULT, AUDIO_CHANNEL_NONE, 0 /*sampleRate*/);
291 if ((status = parcel->readParcelable(this->at(i).get())) != NO_ERROR) {
292 this->clear();
293 break;
294 }
295 }
296 return status;
297 }
298
equals(const AudioProfileVector & other) const299 bool AudioProfileVector::equals(const AudioProfileVector& other) const
300 {
301 return std::equal(begin(), end(), other.begin(), other.end(),
302 [](const sp<AudioProfile>& left, const sp<AudioProfile>& right) {
303 return left->equals(right);
304 });
305 }
306
307 } // namespace android
308