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