1 /*
2  * Copyright (C) 2015 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 #define LOG_TAG "APM::AudioPort"
18 //#define LOG_NDEBUG 0
19 #include "TypeConverter.h"
20 #include "AudioPort.h"
21 #include "HwModule.h"
22 #include "AudioGain.h"
23 #include <policy.h>
24 
25 #ifndef ARRAY_SIZE
26 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
27 #endif
28 
29 namespace android {
30 
31 // --- AudioPort class implementation
attach(const sp<HwModule> & module)32 void AudioPort::attach(const sp<HwModule>& module)
33 {
34     mModule = module;
35 }
36 
37 // Note that is a different namespace than AudioFlinger unique IDs
getNextUniqueId()38 audio_port_handle_t AudioPort::getNextUniqueId()
39 {
40     return getNextHandle();
41 }
42 
getModuleHandle() const43 audio_module_handle_t AudioPort::getModuleHandle() const
44 {
45     return mModule != 0 ? mModule->getHandle() : AUDIO_MODULE_HANDLE_NONE;
46 }
47 
getModuleVersionMajor() const48 uint32_t AudioPort::getModuleVersionMajor() const
49 {
50     return mModule != 0 ? mModule->getHalVersionMajor() : 0;
51 }
52 
getModuleName() const53 const char *AudioPort::getModuleName() const
54 {
55     return mModule != 0 ? mModule->getName() : "invalid module";
56 }
57 
toAudioPort(struct audio_port * port) const58 void AudioPort::toAudioPort(struct audio_port *port) const
59 {
60     // TODO: update this function once audio_port structure reflects the new profile definition.
61     // For compatibility reason: flatening the AudioProfile into audio_port structure.
62     SortedVector<audio_format_t> flatenedFormats;
63     SampleRateVector flatenedRates;
64     ChannelsVector flatenedChannels;
65     for (const auto& profile : mProfiles) {
66         if (profile->isValid()) {
67             audio_format_t formatToExport = profile->getFormat();
68             const SampleRateVector &ratesToExport = profile->getSampleRates();
69             const ChannelsVector &channelsToExport = profile->getChannels();
70 
71             if (flatenedFormats.indexOf(formatToExport) < 0) {
72                 flatenedFormats.add(formatToExport);
73             }
74             for (size_t rateIndex = 0; rateIndex < ratesToExport.size(); rateIndex++) {
75                 uint32_t rate = ratesToExport[rateIndex];
76                 if (flatenedRates.indexOf(rate) < 0) {
77                     flatenedRates.add(rate);
78                 }
79             }
80             for (size_t chanIndex = 0; chanIndex < channelsToExport.size(); chanIndex++) {
81                 audio_channel_mask_t channels = channelsToExport[chanIndex];
82                 if (flatenedChannels.indexOf(channels) < 0) {
83                     flatenedChannels.add(channels);
84                 }
85             }
86             if (flatenedRates.size() > AUDIO_PORT_MAX_SAMPLING_RATES ||
87                     flatenedChannels.size() > AUDIO_PORT_MAX_CHANNEL_MASKS ||
88                     flatenedFormats.size() > AUDIO_PORT_MAX_FORMATS) {
89                 ALOGE("%s: bailing out: cannot export profiles to port config", __FUNCTION__);
90                 return;
91             }
92         }
93     }
94     port->role = mRole;
95     port->type = mType;
96     strlcpy(port->name, mName, AUDIO_PORT_MAX_NAME_LEN);
97     port->num_sample_rates = flatenedRates.size();
98     port->num_channel_masks = flatenedChannels.size();
99     port->num_formats = flatenedFormats.size();
100     for (size_t i = 0; i < flatenedRates.size(); i++) {
101         port->sample_rates[i] = flatenedRates[i];
102     }
103     for (size_t i = 0; i < flatenedChannels.size(); i++) {
104         port->channel_masks[i] = flatenedChannels[i];
105     }
106     for (size_t i = 0; i < flatenedFormats.size(); i++) {
107         port->formats[i] = flatenedFormats[i];
108     }
109 
110     ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size());
111 
112     uint32_t i;
113     for (i = 0; i < mGains.size() && i < AUDIO_PORT_MAX_GAINS; i++) {
114         port->gains[i] = mGains[i]->getGain();
115     }
116     port->num_gains = i;
117 }
118 
importAudioPort(const sp<AudioPort> & port,bool force __unused)119 void AudioPort::importAudioPort(const sp<AudioPort>& port, bool force __unused)
120 {
121     for (const auto& profileToImport : port->mProfiles) {
122         if (profileToImport->isValid()) {
123             // Import only valid port, i.e. valid format, non empty rates and channels masks
124             bool hasSameProfile = false;
125             for (const auto& profile : mProfiles) {
126                 if (*profile == *profileToImport) {
127                     // never import a profile twice
128                     hasSameProfile = true;
129                     break;
130                 }
131             }
132             if (hasSameProfile) { // never import a same profile twice
133                 continue;
134             }
135             addAudioProfile(profileToImport);
136         }
137     }
138 }
139 
checkExactAudioProfile(const struct audio_port_config * config) const140 status_t AudioPort::checkExactAudioProfile(const struct audio_port_config *config) const
141 {
142     status_t status = NO_ERROR;
143     auto config_mask = config->config_mask;
144     if (config_mask & AUDIO_PORT_CONFIG_GAIN) {
145         config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
146         status = checkGain(&config->gain, config->gain.index);
147         if (status != NO_ERROR) {
148             return status;
149         }
150     }
151     if (config_mask != 0) {
152         // TODO should we check sample_rate / channel_mask / format separately?
153         status = mProfiles.checkExactProfile(config->sample_rate,
154                                              config->channel_mask,
155                                              config->format);
156     }
157     return status;
158 }
159 
pickSamplingRate(uint32_t & pickedRate,const SampleRateVector & samplingRates) const160 void AudioPort::pickSamplingRate(uint32_t &pickedRate,const SampleRateVector &samplingRates) const
161 {
162     pickedRate = 0;
163     // For direct outputs, pick minimum sampling rate: this helps ensuring that the
164     // channel count / sampling rate combination chosen will be supported by the connected
165     // sink
166     if (isDirectOutput()) {
167         uint32_t samplingRate = UINT_MAX;
168         for (size_t i = 0; i < samplingRates.size(); i ++) {
169             if ((samplingRates[i] < samplingRate) && (samplingRates[i] > 0)) {
170                 samplingRate = samplingRates[i];
171             }
172         }
173         pickedRate = (samplingRate == UINT_MAX) ? 0 : samplingRate;
174     } else {
175         uint32_t maxRate = SAMPLE_RATE_HZ_MAX;
176 
177         // For mixed output and inputs, use max mixer sampling rates. Do not
178         // limit sampling rate otherwise
179         // For inputs, also see checkCompatibleSamplingRate().
180         if (mType != AUDIO_PORT_TYPE_MIX) {
181             maxRate = UINT_MAX;
182         }
183         // TODO: should mSamplingRates[] be ordered in terms of our preference
184         // and we return the first (and hence most preferred) match?  This is of concern if
185         // we want to choose 96kHz over 192kHz for USB driver stability or resource constraints.
186         for (size_t i = 0; i < samplingRates.size(); i ++) {
187             if ((samplingRates[i] > pickedRate) && (samplingRates[i] <= maxRate)) {
188                 pickedRate = samplingRates[i];
189             }
190         }
191     }
192 }
193 
pickChannelMask(audio_channel_mask_t & pickedChannelMask,const ChannelsVector & channelMasks) const194 void AudioPort::pickChannelMask(audio_channel_mask_t &pickedChannelMask,
195                                 const ChannelsVector &channelMasks) const
196 {
197     pickedChannelMask = AUDIO_CHANNEL_NONE;
198     // For direct outputs, pick minimum channel count: this helps ensuring that the
199     // channel count / sampling rate combination chosen will be supported by the connected
200     // sink
201     if (isDirectOutput()) {
202         uint32_t channelCount = UINT_MAX;
203         for (size_t i = 0; i < channelMasks.size(); i ++) {
204             uint32_t cnlCount;
205             if (useInputChannelMask()) {
206                 cnlCount = audio_channel_count_from_in_mask(channelMasks[i]);
207             } else {
208                 cnlCount = audio_channel_count_from_out_mask(channelMasks[i]);
209             }
210             if ((cnlCount < channelCount) && (cnlCount > 0)) {
211                 pickedChannelMask = channelMasks[i];
212                 channelCount = cnlCount;
213             }
214         }
215     } else {
216         uint32_t channelCount = 0;
217         uint32_t maxCount = MAX_MIXER_CHANNEL_COUNT;
218 
219         // For mixed output and inputs, use max mixer channel count. Do not
220         // limit channel count otherwise
221         if (mType != AUDIO_PORT_TYPE_MIX) {
222             maxCount = UINT_MAX;
223         }
224         for (size_t i = 0; i < channelMasks.size(); i ++) {
225             uint32_t cnlCount;
226             if (useInputChannelMask()) {
227                 cnlCount = audio_channel_count_from_in_mask(channelMasks[i]);
228             } else {
229                 cnlCount = audio_channel_count_from_out_mask(channelMasks[i]);
230             }
231             if ((cnlCount > channelCount) && (cnlCount <= maxCount)) {
232                 pickedChannelMask = channelMasks[i];
233                 channelCount = cnlCount;
234             }
235         }
236     }
237 }
238 
239 /* format in order of increasing preference */
240 const audio_format_t AudioPort::sPcmFormatCompareTable[] = {
241         AUDIO_FORMAT_DEFAULT,
242         AUDIO_FORMAT_PCM_16_BIT,
243         AUDIO_FORMAT_PCM_8_24_BIT,
244         AUDIO_FORMAT_PCM_24_BIT_PACKED,
245         AUDIO_FORMAT_PCM_32_BIT,
246         AUDIO_FORMAT_PCM_FLOAT,
247 };
248 
compareFormats(audio_format_t format1,audio_format_t format2)249 int AudioPort::compareFormats(audio_format_t format1, audio_format_t format2)
250 {
251     // NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any
252     // compressed format and better than any PCM format. This is by design of pickFormat()
253     if (!audio_is_linear_pcm(format1)) {
254         if (!audio_is_linear_pcm(format2)) {
255             return 0;
256         }
257         return 1;
258     }
259     if (!audio_is_linear_pcm(format2)) {
260         return -1;
261     }
262 
263     int index1 = -1, index2 = -1;
264     for (size_t i = 0;
265             (i < ARRAY_SIZE(sPcmFormatCompareTable)) && ((index1 == -1) || (index2 == -1));
266             i ++) {
267         if (sPcmFormatCompareTable[i] == format1) {
268             index1 = i;
269         }
270         if (sPcmFormatCompareTable[i] == format2) {
271             index2 = i;
272         }
273     }
274     // format1 not found => index1 < 0 => format2 > format1
275     // format2 not found => index2 < 0 => format2 < format1
276     return index1 - index2;
277 }
278 
isBetterFormatMatch(audio_format_t newFormat,audio_format_t currentFormat,audio_format_t targetFormat)279 bool AudioPort::isBetterFormatMatch(audio_format_t newFormat,
280                                     audio_format_t currentFormat,
281                                     audio_format_t targetFormat)
282 {
283     if (newFormat == currentFormat) {
284         return false;
285     }
286     if (currentFormat == AUDIO_FORMAT_INVALID) {
287         return true;
288     }
289     if (newFormat == targetFormat) {
290         return true;
291     }
292     int currentDiffBytes = (int)audio_bytes_per_sample(targetFormat) -
293             audio_bytes_per_sample(currentFormat);
294     int newDiffBytes = (int)audio_bytes_per_sample(targetFormat) -
295             audio_bytes_per_sample(newFormat);
296 
297     if (abs(newDiffBytes) < abs(currentDiffBytes)) {
298         return true;
299     } else if (abs(newDiffBytes) == abs(currentDiffBytes)) {
300         return (newDiffBytes >= 0);
301     }
302     return false;
303 }
304 
pickAudioProfile(uint32_t & samplingRate,audio_channel_mask_t & channelMask,audio_format_t & format) const305 void AudioPort::pickAudioProfile(uint32_t &samplingRate,
306                                  audio_channel_mask_t &channelMask,
307                                  audio_format_t &format) const
308 {
309     format = AUDIO_FORMAT_DEFAULT;
310     samplingRate = 0;
311     channelMask = AUDIO_CHANNEL_NONE;
312 
313     // special case for uninitialized dynamic profile
314     if (!mProfiles.hasValidProfile()) {
315         return;
316     }
317     audio_format_t bestFormat = sPcmFormatCompareTable[ARRAY_SIZE(sPcmFormatCompareTable) - 1];
318     // For mixed output and inputs, use best mixer output format.
319     // Do not limit format otherwise
320     if ((mType != AUDIO_PORT_TYPE_MIX) || isDirectOutput()) {
321         bestFormat = AUDIO_FORMAT_INVALID;
322     }
323 
324     for (size_t i = 0; i < mProfiles.size(); i ++) {
325         if (!mProfiles[i]->isValid()) {
326             continue;
327         }
328         audio_format_t formatToCompare = mProfiles[i]->getFormat();
329         if ((compareFormats(formatToCompare, format) > 0) &&
330                 (compareFormats(formatToCompare, bestFormat) <= 0)) {
331             uint32_t pickedSamplingRate = 0;
332             audio_channel_mask_t pickedChannelMask = AUDIO_CHANNEL_NONE;
333             pickChannelMask(pickedChannelMask, mProfiles[i]->getChannels());
334             pickSamplingRate(pickedSamplingRate, mProfiles[i]->getSampleRates());
335 
336             if (formatToCompare != AUDIO_FORMAT_DEFAULT && pickedChannelMask != AUDIO_CHANNEL_NONE
337                     && pickedSamplingRate != 0) {
338                 format = formatToCompare;
339                 channelMask = pickedChannelMask;
340                 samplingRate = pickedSamplingRate;
341                 // TODO: shall we return on the first one or still trying to pick a better Profile?
342             }
343         }
344     }
345     ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__, mName.string(),
346           samplingRate, channelMask, format);
347 }
348 
checkGain(const struct audio_gain_config * gainConfig,int index) const349 status_t AudioPort::checkGain(const struct audio_gain_config *gainConfig, int index) const
350 {
351     if (index < 0 || (size_t)index >= mGains.size()) {
352         return BAD_VALUE;
353     }
354     return mGains[index]->checkConfig(gainConfig);
355 }
356 
dump(int fd,int spaces,bool verbose) const357 void AudioPort::dump(int fd, int spaces, bool verbose) const
358 {
359     const size_t SIZE = 256;
360     char buffer[SIZE];
361     String8 result;
362 
363     if (!mName.isEmpty()) {
364         snprintf(buffer, SIZE, "%*s- name: %s\n", spaces, "", mName.string());
365         result.append(buffer);
366         write(fd, result.string(), result.size());
367     }
368     if (verbose) {
369         mProfiles.dump(fd, spaces);
370 
371         if (mGains.size() != 0) {
372             snprintf(buffer, SIZE, "%*s- gains:\n", spaces, "");
373             result = buffer;
374             write(fd, result.string(), result.size());
375             for (size_t i = 0; i < mGains.size(); i++) {
376                 mGains[i]->dump(fd, spaces + 2, i);
377             }
378         }
379     }
380 }
381 
log(const char * indent) const382 void AudioPort::log(const char* indent) const
383 {
384     ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.string(), mType, mRole);
385 }
386 
387 // --- AudioPortConfig class implementation
388 
AudioPortConfig()389 AudioPortConfig::AudioPortConfig()
390 {
391     mSamplingRate = 0;
392     mChannelMask = AUDIO_CHANNEL_NONE;
393     mFormat = AUDIO_FORMAT_INVALID;
394     memset(&mGain, 0, sizeof(struct audio_gain_config));
395     mGain.index = -1;
396 }
397 
applyAudioPortConfig(const struct audio_port_config * config,struct audio_port_config * backupConfig)398 status_t AudioPortConfig::applyAudioPortConfig(const struct audio_port_config *config,
399                                                struct audio_port_config *backupConfig)
400 {
401     struct audio_port_config localBackupConfig;
402     status_t status = NO_ERROR;
403 
404     localBackupConfig.config_mask = config->config_mask;
405     toAudioPortConfig(&localBackupConfig);
406 
407     sp<AudioPort> audioport = getAudioPort();
408     if (audioport == 0) {
409         status = NO_INIT;
410         goto exit;
411     }
412     status = audioport->checkExactAudioProfile(config);
413     if (status != NO_ERROR) {
414         goto exit;
415     }
416     if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
417         mSamplingRate = config->sample_rate;
418     }
419     if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
420         mChannelMask = config->channel_mask;
421     }
422     if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
423         mFormat = config->format;
424     }
425     if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) {
426         mGain = config->gain;
427     }
428 
429 exit:
430     if (status != NO_ERROR) {
431         applyAudioPortConfig(&localBackupConfig);
432     }
433     if (backupConfig != NULL) {
434         *backupConfig = localBackupConfig;
435     }
436     return status;
437 }
438 
toAudioPortConfig(struct audio_port_config * dstConfig,const struct audio_port_config * srcConfig) const439 void AudioPortConfig::toAudioPortConfig(struct audio_port_config *dstConfig,
440                                         const struct audio_port_config *srcConfig) const
441 {
442     if (dstConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
443         dstConfig->sample_rate = mSamplingRate;
444         if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE)) {
445             dstConfig->sample_rate = srcConfig->sample_rate;
446         }
447     } else {
448         dstConfig->sample_rate = 0;
449     }
450     if (dstConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
451         dstConfig->channel_mask = mChannelMask;
452         if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK)) {
453             dstConfig->channel_mask = srcConfig->channel_mask;
454         }
455     } else {
456         dstConfig->channel_mask = AUDIO_CHANNEL_NONE;
457     }
458     if (dstConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
459         dstConfig->format = mFormat;
460         if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT)) {
461             dstConfig->format = srcConfig->format;
462         }
463     } else {
464         dstConfig->format = AUDIO_FORMAT_INVALID;
465     }
466     sp<AudioPort> audioport = getAudioPort();
467     if ((dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) && audioport != NULL) {
468         dstConfig->gain = mGain;
469         if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN)
470                 && audioport->checkGain(&srcConfig->gain, srcConfig->gain.index) == OK) {
471             dstConfig->gain = srcConfig->gain;
472         }
473     } else {
474         dstConfig->gain.index = -1;
475     }
476     if (dstConfig->gain.index != -1) {
477         dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN;
478     } else {
479         dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
480     }
481 }
482 
483 } // namespace android
484