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