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
31// --- AudioPort class implementation
32void AudioPort::attach(const sp<HwModule>& module)
33{
34    mModule = module;
35}
36
37// Note that is a different namespace than AudioFlinger unique IDs
38audio_port_handle_t AudioPort::getNextUniqueId()
39{
40    return getNextHandle();
41}
42
43audio_module_handle_t AudioPort::getModuleHandle() const
44{
45    return mModule != 0 ? mModule->getHandle() : AUDIO_MODULE_HANDLE_NONE;
46}
47
48uint32_t AudioPort::getModuleVersionMajor() const
49{
50    return mModule != 0 ? mModule->getHalVersionMajor() : 0;
51}
52
53const char *AudioPort::getModuleName() const
54{
55    return mModule != 0 ? mModule->getName() : "invalid module";
56}
57
58void 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
119void 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
140status_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
160void 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
194void 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 */
240const 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
249int 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
279bool 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
305void 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
349status_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
357void 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
382void 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
389AudioPortConfig::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
398status_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
429exit:
430    if (status != NO_ERROR) {
431        applyAudioPortConfig(&localBackupConfig);
432    }
433    if (backupConfig != NULL) {
434        *backupConfig = localBackupConfig;
435    }
436    return status;
437}
438
439void 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