• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define LOG_TAG "AudioPort"
17 
18 #include <algorithm>
19 #include <utility>
20 
21 #include <android/media/ExtraAudioDescriptor.h>
22 #include <android-base/stringprintf.h>
23 #include <media/AudioPort.h>
24 #include <utils/Log.h>
25 
26 namespace android {
27 
importAudioPort(const sp<AudioPort> & port,bool force __unused)28 void AudioPort::importAudioPort(const sp<AudioPort>& port, bool force __unused)
29 {
30     for (const auto& profileToImport : port->mProfiles) {
31         // Import only valid port, i.e. valid format, non empty rates and channels masks
32         if (!profileToImport->isValid()) {
33             continue;
34         }
35         if (std::find_if(mProfiles.begin(), mProfiles.end(),
36                 [profileToImport](const auto &profile) {
37                         return *profile == *profileToImport; }) == mProfiles.end()) {
38             addAudioProfile(profileToImport);
39         }
40     }
41 }
42 
importAudioPort(const audio_port_v7 & port)43 void AudioPort::importAudioPort(const audio_port_v7 &port) {
44     for (size_t i = 0; i < port.num_audio_profiles; ++i) {
45         sp<AudioProfile> profile = new AudioProfile(port.audio_profiles[i].format,
46                 ChannelMaskSet(port.audio_profiles[i].channel_masks,
47                         port.audio_profiles[i].channel_masks +
48                         port.audio_profiles->num_channel_masks),
49                 SampleRateSet(port.audio_profiles[i].sample_rates,
50                         port.audio_profiles[i].sample_rates +
51                         port.audio_profiles[i].num_sample_rates),
52                 port.audio_profiles[i].encapsulation_type);
53         if (!mProfiles.contains(profile)) {
54             addAudioProfile(profile);
55         }
56     }
57 
58     for (size_t i = 0; i < port.num_extra_audio_descriptors; ++i) {
59         auto convertedResult = legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor(
60                 port.extra_audio_descriptors[i]);
61         if (!convertedResult.ok()) {
62             ALOGE("%s, failed to convert extra audio descriptor", __func__);
63             continue;
64         }
65         if (std::find(mExtraAudioDescriptors.begin(),
66                       mExtraAudioDescriptors.end(),
67                       convertedResult.value()) == mExtraAudioDescriptors.end()) {
68             mExtraAudioDescriptors.push_back(std::move(convertedResult.value()));
69         }
70     }
71 }
72 
toAudioPort(struct audio_port * port) const73 void AudioPort::toAudioPort(struct audio_port *port) const {
74     // TODO: update this function once audio_port structure reflects the new profile definition.
75     // For compatibility reason: flatening the AudioProfile into audio_port structure.
76     FormatSet flatenedFormats;
77     SampleRateSet flatenedRates;
78     ChannelMaskSet flatenedChannels;
79     for (const auto& profile : mProfiles) {
80         if (profile->isValid()) {
81             audio_format_t formatToExport = profile->getFormat();
82             const SampleRateSet &ratesToExport = profile->getSampleRates();
83             const ChannelMaskSet &channelsToExport = profile->getChannels();
84 
85             flatenedFormats.insert(formatToExport);
86             flatenedRates.insert(ratesToExport.begin(), ratesToExport.end());
87             flatenedChannels.insert(channelsToExport.begin(), channelsToExport.end());
88 
89             if (flatenedRates.size() > AUDIO_PORT_MAX_SAMPLING_RATES ||
90                     flatenedChannels.size() > AUDIO_PORT_MAX_CHANNEL_MASKS ||
91                     flatenedFormats.size() > AUDIO_PORT_MAX_FORMATS) {
92                 ALOGE("%s: bailing out: cannot export profiles to port config", __func__);
93                 return;
94             }
95         }
96     }
97     toAudioPortBase(port);
98     port->num_sample_rates = flatenedRates.size();
99     port->num_channel_masks = flatenedChannels.size();
100     port->num_formats = flatenedFormats.size();
101     std::copy(flatenedRates.begin(), flatenedRates.end(), port->sample_rates);
102     std::copy(flatenedChannels.begin(), flatenedChannels.end(), port->channel_masks);
103     std::copy(flatenedFormats.begin(), flatenedFormats.end(), port->formats);
104 }
105 
toAudioPort(struct audio_port_v7 * port) const106 void AudioPort::toAudioPort(struct audio_port_v7 *port) const {
107     toAudioPortBase(port);
108     port->num_audio_profiles = 0;
109     for (const auto& profile : mProfiles) {
110         if (profile->isValid()) {
111             const SampleRateSet &sampleRates = profile->getSampleRates();
112             const ChannelMaskSet &channelMasks = profile->getChannels();
113 
114             if (sampleRates.size() > AUDIO_PORT_MAX_SAMPLING_RATES ||
115                     channelMasks.size() > AUDIO_PORT_MAX_CHANNEL_MASKS ||
116                     port->num_audio_profiles >= AUDIO_PORT_MAX_AUDIO_PROFILES) {
117                 ALOGE("%s: bailing out: cannot export profiles to port config", __func__);
118                 break;
119             }
120 
121             auto& dstProfile = port->audio_profiles[port->num_audio_profiles++];
122             dstProfile.format = profile->getFormat();
123             dstProfile.num_sample_rates = sampleRates.size();
124             std::copy(sampleRates.begin(), sampleRates.end(),
125                     std::begin(dstProfile.sample_rates));
126             dstProfile.num_channel_masks = channelMasks.size();
127             std::copy(channelMasks.begin(), channelMasks.end(),
128                     std::begin(dstProfile.channel_masks));
129             dstProfile.encapsulation_type = profile->getEncapsulationType();
130         }
131     }
132 
133     port->num_extra_audio_descriptors = 0;
134     for (const auto& desc : mExtraAudioDescriptors) {
135         if (port->num_extra_audio_descriptors >= AUDIO_PORT_MAX_EXTRA_AUDIO_DESCRIPTORS) {
136             ALOGE("%s: bailing out: cannot export extra audio descriptor to port config", __func__);
137             return;
138         }
139 
140         auto convertedResult = aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(desc);
141         if (!convertedResult.ok()) {
142             ALOGE("%s: failed to convert extra audio descriptor", __func__);
143             continue;
144         }
145         port->extra_audio_descriptors[port->num_extra_audio_descriptors++] =
146                 std::move(convertedResult.value());
147     }
148 }
149 
dump(std::string * dst,int spaces,bool verbose) const150 void AudioPort::dump(std::string *dst, int spaces, bool verbose) const {
151     if (!mName.empty()) {
152         dst->append(base::StringPrintf("%*s- name: %s\n", spaces, "", mName.c_str()));
153     }
154     if (verbose) {
155         std::string profilesStr;
156         mProfiles.dump(&profilesStr, spaces);
157         dst->append(profilesStr);
158         if (!mExtraAudioDescriptors.empty()) {
159             dst->append(base::StringPrintf("%*s- extra audio descriptors: \n", spaces, ""));
160             const int eadSpaces = spaces + 4;
161             const int descSpaces = eadSpaces + 4;
162             for (size_t i = 0; i < mExtraAudioDescriptors.size(); i++) {
163                 dst->append(
164                         base::StringPrintf("%*s extra audio descriptor %zu:\n", eadSpaces, "", i));
165                 dst->append(base::StringPrintf(
166                     "%*s- standard: %u\n", descSpaces, "", mExtraAudioDescriptors[i].standard));
167                 dst->append(base::StringPrintf("%*s- descriptor:", descSpaces, ""));
168                 for (auto v : mExtraAudioDescriptors[i].audioDescriptor) {
169                     dst->append(base::StringPrintf(" %02x", v));
170                 }
171                 dst->append("\n");
172             }
173         }
174 
175         if (mGains.size() != 0) {
176             dst->append(base::StringPrintf("%*s- gains:\n", spaces, ""));
177             for (size_t i = 0; i < mGains.size(); i++) {
178                 std::string gainStr;
179                 mGains[i]->dump(&gainStr, spaces + 2, i);
180                 dst->append(gainStr);
181             }
182         }
183     }
184 }
185 
log(const char * indent) const186 void AudioPort::log(const char* indent) const
187 {
188     ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.c_str(), mType, mRole);
189 }
190 
equals(const sp<AudioPort> & other) const191 bool AudioPort::equals(const sp<AudioPort> &other) const
192 {
193     return other != nullptr &&
194            mGains.equals(other->getGains()) &&
195            mName.compare(other->getName()) == 0 &&
196            mType == other->getType() &&
197            mRole == other->getRole() &&
198            mProfiles.equals(other->getAudioProfiles()) &&
199            mExtraAudioDescriptors == other->getExtraAudioDescriptors();
200 }
201 
writeToParcel(Parcel * parcel) const202 status_t AudioPort::writeToParcel(Parcel *parcel) const
203 {
204     media::AudioPort parcelable;
205     return writeToParcelable(&parcelable)
206         ?: parcelable.writeToParcel(parcel);
207 }
208 
writeToParcelable(media::AudioPort * parcelable) const209 status_t AudioPort::writeToParcelable(media::AudioPort* parcelable) const {
210     parcelable->name = mName;
211     parcelable->type = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_type_t_AudioPortType(mType));
212     parcelable->role = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_role_t_AudioPortRole(mRole));
213     parcelable->profiles = VALUE_OR_RETURN_STATUS(legacy2aidl_AudioProfileVector(mProfiles));
214     parcelable->extraAudioDescriptors = mExtraAudioDescriptors;
215     parcelable->gains = VALUE_OR_RETURN_STATUS(legacy2aidl_AudioGains(mGains));
216     return OK;
217 }
218 
readFromParcel(const Parcel * parcel)219 status_t AudioPort::readFromParcel(const Parcel *parcel) {
220     media::AudioPort parcelable;
221     return parcelable.readFromParcel(parcel)
222         ?: readFromParcelable(parcelable);
223 }
224 
readFromParcelable(const media::AudioPort & parcelable)225 status_t AudioPort::readFromParcelable(const media::AudioPort& parcelable) {
226     mName = parcelable.name;
227     mType = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioPortType_audio_port_type_t(parcelable.type));
228     mRole = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioPortRole_audio_port_role_t(parcelable.role));
229     mProfiles = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioProfileVector(parcelable.profiles));
230     mExtraAudioDescriptors = parcelable.extraAudioDescriptors;
231     mGains = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioGains(parcelable.gains));
232     return OK;
233 }
234 
235 // --- AudioPortConfig class implementation
236 
applyAudioPortConfig(const struct audio_port_config * config,struct audio_port_config * backupConfig __unused)237 status_t AudioPortConfig::applyAudioPortConfig(
238         const struct audio_port_config *config,
239         struct audio_port_config *backupConfig __unused)
240 {
241     if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
242         mSamplingRate = config->sample_rate;
243     }
244     if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
245         mChannelMask = config->channel_mask;
246     }
247     if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
248         mFormat = config->format;
249     }
250     if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) {
251         mGain = config->gain;
252     }
253 
254     return NO_ERROR;
255 }
256 
257 namespace {
258 
259 template<typename T>
updateField(const T & portConfigField,T audio_port_config::* port_config_field,struct audio_port_config * dstConfig,const struct audio_port_config * srcConfig,unsigned int configMask,T defaultValue)260 void updateField(
261         const T& portConfigField, T audio_port_config::*port_config_field,
262         struct audio_port_config *dstConfig, const struct audio_port_config *srcConfig,
263         unsigned int configMask, T defaultValue)
264 {
265     if (dstConfig->config_mask & configMask) {
266         if ((srcConfig != nullptr) && (srcConfig->config_mask & configMask)) {
267             dstConfig->*port_config_field = srcConfig->*port_config_field;
268         } else {
269             dstConfig->*port_config_field = portConfigField;
270         }
271     } else {
272         dstConfig->*port_config_field = defaultValue;
273     }
274 }
275 
276 } // namespace
277 
toAudioPortConfig(struct audio_port_config * dstConfig,const struct audio_port_config * srcConfig) const278 void AudioPortConfig::toAudioPortConfig(
279         struct audio_port_config *dstConfig,
280         const struct audio_port_config *srcConfig) const
281 {
282     updateField(mSamplingRate, &audio_port_config::sample_rate,
283             dstConfig, srcConfig, AUDIO_PORT_CONFIG_SAMPLE_RATE, 0u);
284     updateField(mChannelMask, &audio_port_config::channel_mask,
285             dstConfig, srcConfig, AUDIO_PORT_CONFIG_CHANNEL_MASK,
286             (audio_channel_mask_t)AUDIO_CHANNEL_NONE);
287     updateField(mFormat, &audio_port_config::format,
288             dstConfig, srcConfig, AUDIO_PORT_CONFIG_FORMAT, AUDIO_FORMAT_INVALID);
289     dstConfig->id = mId;
290 
291     sp<AudioPort> audioport = getAudioPort();
292     if ((dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) && audioport != NULL) {
293         dstConfig->gain = mGain;
294         if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN)
295                 && audioport->checkGain(&srcConfig->gain, srcConfig->gain.index) == OK) {
296             dstConfig->gain = srcConfig->gain;
297         }
298     } else {
299         dstConfig->gain.index = -1;
300     }
301     if (dstConfig->gain.index != -1) {
302         dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN;
303     } else {
304         dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
305     }
306 }
307 
hasGainController(bool canUseForVolume) const308 bool AudioPortConfig::hasGainController(bool canUseForVolume) const
309 {
310     sp<AudioPort> audioport = getAudioPort();
311     if (!audioport) {
312         return false;
313     }
314     return canUseForVolume ? audioport->getGains().canUseForVolume()
315                            : audioport->getGains().size() > 0;
316 }
317 
equals(const sp<AudioPortConfig> & other) const318 bool AudioPortConfig::equals(const sp<AudioPortConfig> &other) const
319 {
320     return other != nullptr &&
321            mSamplingRate == other->getSamplingRate() &&
322            mFormat == other->getFormat() &&
323            mChannelMask == other->getChannelMask() &&
324            // Compare audio gain config
325            mGain.index == other->mGain.index &&
326            mGain.mode == other->mGain.mode &&
327            mGain.channel_mask == other->mGain.channel_mask &&
328            std::equal(std::begin(mGain.values), std::end(mGain.values),
329                       std::begin(other->mGain.values)) &&
330            mGain.ramp_duration_ms == other->mGain.ramp_duration_ms;
331 }
332 
writeToParcel(Parcel * parcel) const333 status_t AudioPortConfig::writeToParcel(Parcel *parcel) const {
334     media::AudioPortConfig parcelable;
335     return writeToParcelable(&parcelable)
336         ?: parcelable.writeToParcel(parcel);
337 }
338 
writeToParcelable(media::AudioPortConfig * parcelable) const339 status_t AudioPortConfig::writeToParcelable(media::AudioPortConfig* parcelable) const {
340     parcelable->sampleRate = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(mSamplingRate));
341     parcelable->format = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_format_t_AudioFormat(mFormat));
342     parcelable->channelMask = VALUE_OR_RETURN_STATUS(
343             legacy2aidl_audio_channel_mask_t_int32_t(mChannelMask));
344     parcelable->id = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_handle_t_int32_t(mId));
345     parcelable->gain.index = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(mGain.index));
346     parcelable->gain.mode = VALUE_OR_RETURN_STATUS(
347             legacy2aidl_audio_gain_mode_t_int32_t_mask(mGain.mode));
348     parcelable->gain.channelMask = VALUE_OR_RETURN_STATUS(
349             legacy2aidl_audio_channel_mask_t_int32_t(mGain.channel_mask));
350     parcelable->gain.rampDurationMs = VALUE_OR_RETURN_STATUS(
351             convertIntegral<int32_t>(mGain.ramp_duration_ms));
352     parcelable->gain.values = VALUE_OR_RETURN_STATUS(convertContainer<std::vector<int32_t>>(
353             mGain.values, convertIntegral<int32_t, int>));
354     return OK;
355 }
356 
readFromParcel(const Parcel * parcel)357 status_t AudioPortConfig::readFromParcel(const Parcel *parcel) {
358     media::AudioPortConfig parcelable;
359     return parcelable.readFromParcel(parcel)
360         ?: readFromParcelable(parcelable);
361 }
362 
readFromParcelable(const media::AudioPortConfig & parcelable)363 status_t AudioPortConfig::readFromParcelable(const media::AudioPortConfig& parcelable) {
364     mSamplingRate = VALUE_OR_RETURN_STATUS(convertIntegral<unsigned int>(parcelable.sampleRate));
365     mFormat = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioFormat_audio_format_t(parcelable.format));
366     mChannelMask = VALUE_OR_RETURN_STATUS(
367             aidl2legacy_int32_t_audio_channel_mask_t(parcelable.channelMask));
368     mId = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_audio_port_handle_t(parcelable.id));
369     mGain.index = VALUE_OR_RETURN_STATUS(convertIntegral<int>(parcelable.gain.index));
370     mGain.mode = VALUE_OR_RETURN_STATUS(
371             aidl2legacy_int32_t_audio_gain_mode_t_mask(parcelable.gain.mode));
372     mGain.channel_mask = VALUE_OR_RETURN_STATUS(
373             aidl2legacy_int32_t_audio_channel_mask_t(parcelable.gain.channelMask));
374     mGain.ramp_duration_ms = VALUE_OR_RETURN_STATUS(
375             convertIntegral<unsigned int>(parcelable.gain.rampDurationMs));
376     if (parcelable.gain.values.size() > std::size(mGain.values)) {
377         return BAD_VALUE;
378     }
379     for (size_t i = 0; i < parcelable.gain.values.size(); ++i) {
380         mGain.values[i] = VALUE_OR_RETURN_STATUS(convertIntegral<int>(parcelable.gain.values[i]));
381     }
382     return OK;
383 }
384 
385 } // namespace android
386