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
39// Note that is a different namespace than AudioFlinger unique IDs
40audio_port_handle_t AudioPort::getNextUniqueId()
41{
42    return static_cast<audio_port_handle_t>(android_atomic_inc(&mNextUniqueId));
43}
44
45audio_module_handle_t AudioPort::getModuleHandle() const
46{
47    if (mModule == 0) {
48        return AUDIO_MODULE_HANDLE_NONE;
49    }
50    return mModule->mHandle;
51}
52
53uint32_t AudioPort::getModuleVersion() const
54{
55    if (mModule == 0) {
56        return 0;
57    }
58    return mModule->getHalVersion();
59}
60
61const char *AudioPort::getModuleName() const
62{
63    if (mModule == 0) {
64        return "invalid module";
65    }
66    return mModule->getName();
67}
68
69void 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
130void 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
153void 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
187void 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 */
233const 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
242int 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
272bool 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
298void 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
342status_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
350void 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
375void 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
382AudioPortConfig::AudioPortConfig()
383{
384    mSamplingRate = 0;
385    mChannelMask = AUDIO_CHANNEL_NONE;
386    mFormat = AUDIO_FORMAT_INVALID;
387    mGain.index = -1;
388}
389
390status_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
427exit:
428    if (status != NO_ERROR) {
429        applyAudioPortConfig(&localBackupConfig);
430    }
431    if (backupConfig != NULL) {
432        *backupConfig = localBackupConfig;
433    }
434    return status;
435}
436
437void 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