Home | History | Annotate | Download | only in src
      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
     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
     38 audio_port_handle_t AudioPort::getNextUniqueId()
     39 {
     40     return getNextHandle();
     41 }
     42 
     43 audio_module_handle_t AudioPort::getModuleHandle() const
     44 {
     45     return mModule != 0 ? mModule->getHandle() : AUDIO_MODULE_HANDLE_NONE;
     46 }
     47 
     48 uint32_t AudioPort::getModuleVersionMajor() const
     49 {
     50     return mModule != 0 ? mModule->getHalVersionMajor() : 0;
     51 }
     52 
     53 const char *AudioPort::getModuleName() const
     54 {
     55     return mModule != 0 ? mModule->getName() : "invalid module";
     56 }
     57 
     58 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 
    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 
    140 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 
    160 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 
    194 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 
    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 
    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 
    305 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 
    349 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 
    357 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 
    382 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 
    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 
    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 
    439 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