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 int32_t volatile AudioPort::mNextUniqueId = 1;
     32 
     33 // --- AudioPort class implementation
     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
     40 audio_port_handle_t AudioPort::getNextUniqueId()
     41 {
     42     return static_cast<audio_port_handle_t>(android_atomic_inc(&mNextUniqueId));
     43 }
     44 
     45 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 
     53 uint32_t AudioPort::getModuleVersion() const
     54 {
     55     if (mModule == 0) {
     56         return 0;
     57     }
     58     return mModule->getHalVersion();
     59 }
     60 
     61 const char *AudioPort::getModuleName() const
     62 {
     63     if (mModule == 0) {
     64         return "invalid module";
     65     }
     66     return mModule->getName();
     67 }
     68 
     69 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 
    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 
    153 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 
    187 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 
    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 
    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 
    298 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 
    342 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 
    350 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 
    375 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 
    382 AudioPortConfig::AudioPortConfig()
    383 {
    384     mSamplingRate = 0;
    385     mChannelMask = AUDIO_CHANNEL_NONE;
    386     mFormat = AUDIO_FORMAT_INVALID;
    387     mGain.index = -1;
    388 }
    389 
    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 
    437 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