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