Home | History | Annotate | Download | only in libaudio
      1 /*
      2 **
      3 ** Copyright 2014, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 #define LOG_TAG "AudioHAL:AudioHardwareOutput"
     19 
     20 #include <utils/Log.h>
     21 
     22 #include <stdint.h>
     23 #include <limits.h>
     24 #include <math.h>
     25 
     26 #include <common_time/local_clock.h>
     27 #include <cutils/properties.h>
     28 
     29 #include "AudioHardwareOutput.h"
     30 #include "AudioStreamOut.h"
     31 #include "HDMIAudioOutput.h"
     32 
     33 namespace android {
     34 
     35 // Global singleton.
     36 AudioHardwareOutput gAudioHardwareOutput;
     37 
     38 // HDMI options.
     39 const String8 AudioHardwareOutput::kHDMIAllowedParamKey(
     40         "atv.hdmi_audio.allowed");
     41 const String8 AudioHardwareOutput::kHDMIDelayCompParamKey(
     42         "atv.hdmi.audio_delay");
     43 const String8 AudioHardwareOutput::kFixedHDMIOutputParamKey(
     44         "atv.hdmi.fixed_volume");
     45 const String8 AudioHardwareOutput::kFixedHDMIOutputLevelParamKey(
     46         "atv.hdmi.fixed_level");
     47 
     48 // Video delay comp hack options (not exposed to user level)
     49 const String8 AudioHardwareOutput::kVideoDelayCompParamKey(
     50         "atv.video.delay_comp");
     51 
     52 // Defaults for settings.
     53 void AudioHardwareOutput::OutputSettings::setDefaults()
     54 {
     55     allowed = true;
     56     delayCompUsec = 0;
     57     isFixed = false;
     58     fixedLvl = 0.0f;
     59 }
     60 
     61 void AudioHardwareOutput::Settings::setDefaults() {
     62     hdmi.setDefaults();
     63 
     64     masterVolume = 0.60;
     65     masterMute = false;
     66 
     67     // Default this to 16mSec or so.  Since audio start times are not sync'ed to
     68     // to the VBI, there should be a +/-0.5 output frame rate error in the AV
     69     // sync, even under the best of circumstances.
     70     //
     71     // In practice, the android core seems to have a hard time hitting its frame
     72     // cadence consistently.  Sometimes the frames are on time, and sometimes
     73     // they are even a little early, but more often than not, the frames are
     74     // late by about a full output frame time.
     75     //
     76     // ATV pretty much always uses a 60fps output rate, and the only thing
     77     // consuming the latency estimate provided by the HAL is the path handling
     78     // AV sync.  For now, we can fudge this number to move things back in the
     79     // direction of correct by providing a setting for video delay compensation
     80     // which will be subtracted from the latency estimate and defaulting it to
     81     // a reasonable middle gound (12mSec in this case).
     82     videoDelayCompUsec = 12000;
     83 }
     84 
     85 AudioHardwareOutput::AudioHardwareOutput()
     86   : mMainOutput(NULL)
     87   , mMCOutput(NULL)
     88   , mHDMIConnected(false)
     89   , mMaxDelayCompUsec(0)
     90 {
     91     mSettings.setDefaults();
     92     mHDMICardID = find_alsa_card_by_name(kHDMI_ALSADeviceName);
     93 }
     94 
     95 AudioHardwareOutput::~AudioHardwareOutput()
     96 {
     97     closeOutputStream(mMainOutput);
     98     closeOutputStream(mMCOutput);
     99 }
    100 
    101 status_t AudioHardwareOutput::initCheck() {
    102     return NO_ERROR;
    103 }
    104 
    105 AudioStreamOut* AudioHardwareOutput::openOutputStream(
    106         uint32_t devices,
    107         audio_format_t *format,
    108         uint32_t *channels,
    109         uint32_t *sampleRate,
    110         audio_output_flags_t flags,
    111         status_t *status) {
    112     (void) devices;
    113     AutoMutex lock(mStreamLock);
    114 
    115     AudioStreamOut** pp_out;
    116     AudioStreamOut* out;
    117 
    118     if (!(flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
    119         pp_out = &mMainOutput;
    120         out = new AudioStreamOut(*this, false);
    121     } else {
    122         pp_out = &mMCOutput;
    123         out = new AudioStreamOut(*this, true);
    124     }
    125 
    126     if (out == NULL) {
    127         *status = NO_MEMORY;
    128         return NULL;
    129     }
    130 
    131     *status = out->set(format, channels, sampleRate);
    132 
    133     if (*status == NO_ERROR) {
    134         *pp_out = out;
    135         updateTgtDevices_l();
    136     } else {
    137         delete out;
    138     }
    139 
    140     return *pp_out;
    141 }
    142 
    143 void AudioHardwareOutput::closeOutputStream(AudioStreamOut* out) {
    144     if (out == NULL)
    145         return;
    146 
    147     // Putting the stream into "standby" should cause it to release all of its
    148     // physical outputs.
    149     out->standby();
    150 
    151     {
    152         Mutex::Autolock _l(mStreamLock);
    153         if (mMainOutput && out == mMainOutput) {
    154             delete mMainOutput;
    155             mMainOutput = NULL;
    156         } else if (mMCOutput && out == mMCOutput) {
    157             delete mMCOutput;
    158             mMCOutput = NULL;
    159         }
    160 
    161         updateTgtDevices_l();
    162     }
    163 }
    164 
    165 status_t AudioHardwareOutput::setMasterVolume(float volume)
    166 {
    167     Mutex::Autolock _l1(mOutputLock);
    168     Mutex::Autolock _l2(mSettingsLock);
    169 
    170     mSettings.masterVolume = volume;
    171 
    172     AudioOutputList::iterator I;
    173     for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I)
    174         (*I)->setVolume(mSettings.masterVolume);
    175 
    176     return NO_ERROR;
    177 }
    178 
    179 status_t AudioHardwareOutput::getMasterVolume(float* volume) {
    180 
    181     if (NULL == volume)
    182         return BAD_VALUE;
    183 
    184     // Explicit scope for auto-lock pattern.
    185     {
    186         Mutex::Autolock _l(mSettingsLock);
    187         *volume = mSettings.masterVolume;
    188     }
    189 
    190     return NO_ERROR;
    191 }
    192 
    193 status_t AudioHardwareOutput::setMasterMute(bool muted)
    194 {
    195     Mutex::Autolock _l1(mOutputLock);
    196     Mutex::Autolock _l2(mSettingsLock);
    197 
    198     mSettings.masterMute = muted;
    199 
    200     AudioOutputList::iterator I;
    201     for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I)
    202         (*I)->setMute(mSettings.masterMute);
    203 
    204     return NO_ERROR;
    205 }
    206 
    207 status_t AudioHardwareOutput::getMasterMute(bool* muted) {
    208     if (NULL == muted)
    209         return BAD_VALUE;
    210 
    211     // Explicit scope for auto-lock pattern.
    212     {
    213         Mutex::Autolock _l(mSettingsLock);
    214         *muted = mSettings.masterMute;
    215     }
    216 
    217     return NO_ERROR;
    218 }
    219 
    220 status_t AudioHardwareOutput::setParameters(const char* kvpairs) {
    221     AudioParameter param = AudioParameter(String8(kvpairs));
    222     status_t status = NO_ERROR;
    223     float floatVal;
    224     int intVal;
    225     Settings initial, s;
    226 
    227     {
    228         // Record the initial state of the settings from inside the lock.  Then
    229         // leave the lock in order to parse the changes to be made.
    230         Mutex::Autolock _l(mSettingsLock);
    231         initial = s = mSettings;
    232     }
    233 
    234     /***************************************************************
    235      *                     HDMI Audio Options                      *
    236      ***************************************************************/
    237     if (param.getInt(kHDMIAllowedParamKey, intVal) == NO_ERROR) {
    238         s.hdmi.allowed = (intVal != 0);
    239         param.remove(kHDMIAllowedParamKey);
    240     }
    241 
    242     if ((param.getFloat(kHDMIDelayCompParamKey, floatVal) == NO_ERROR) &&
    243         (floatVal >= 0.0) &&
    244         (floatVal <= AudioOutput::kMaxDelayCompensationMSec)) {
    245         uint32_t delay_comp = static_cast<uint32_t>(floatVal * 1000.0);
    246         s.hdmi.delayCompUsec = delay_comp;
    247         param.remove(kHDMIDelayCompParamKey);
    248     }
    249 
    250     if (param.getInt(kFixedHDMIOutputParamKey, intVal) == NO_ERROR) {
    251         s.hdmi.isFixed = (intVal != 0);
    252         param.remove(kFixedHDMIOutputParamKey);
    253     }
    254 
    255     if ((param.getFloat(kFixedHDMIOutputLevelParamKey, floatVal) == NO_ERROR)
    256         && (floatVal <= 0.0)) {
    257         s.hdmi.fixedLvl = floatVal;
    258         param.remove(kFixedHDMIOutputLevelParamKey);
    259     }
    260 
    261     /***************************************************************
    262      *                       Other Options                         *
    263      ***************************************************************/
    264     if ((param.getFloat(kVideoDelayCompParamKey, floatVal) == NO_ERROR) &&
    265         (floatVal >= 0.0) &&
    266         (floatVal <= AudioOutput::kMaxDelayCompensationMSec)) {
    267         s.videoDelayCompUsec = static_cast<uint32_t>(floatVal * 1000.0);
    268         param.remove(kVideoDelayCompParamKey);
    269     }
    270 
    271     if (param.size())
    272         status = BAD_VALUE;
    273 
    274     // If there was a change made to settings, go ahead and apply it now.
    275     bool allowedOutputsChanged = false;
    276     if (memcmp(&initial, &s, sizeof(initial)))  {
    277         Mutex::Autolock _l1(mOutputLock);
    278         Mutex::Autolock _l2(mSettingsLock);
    279 
    280         if (memcmp(&initial.hdmi, &s.hdmi, sizeof(initial.hdmi)))
    281             allowedOutputsChanged = allowedOutputsChanged ||
    282                 applyOutputSettings_l(initial.hdmi, s.hdmi, mSettings.hdmi,
    283                                       HDMIAudioOutput::classDevMask());
    284 
    285         if (initial.videoDelayCompUsec != s.videoDelayCompUsec)
    286             mSettings.videoDelayCompUsec = s.videoDelayCompUsec;
    287 
    288         uint32_t tmp = 0;
    289         if (mSettings.hdmi.allowed && (tmp < mSettings.hdmi.delayCompUsec))
    290             tmp = mSettings.hdmi.delayCompUsec;
    291         if (mMaxDelayCompUsec != tmp)
    292             mMaxDelayCompUsec = tmp;
    293     }
    294 
    295     if (allowedOutputsChanged) {
    296         Mutex::Autolock _l(mStreamLock);
    297         updateTgtDevices_l();
    298     }
    299 
    300     return status;
    301 }
    302 
    303 bool AudioHardwareOutput::applyOutputSettings_l(
    304         const AudioHardwareOutput::OutputSettings& initial,
    305         const AudioHardwareOutput::OutputSettings& current,
    306         AudioHardwareOutput::OutputSettings& updateMe,
    307         uint32_t outDevMask) {
    308     // ASSERT(holding mOutputLock and mSettingsLock)
    309     sp<AudioOutput> out;
    310 
    311     // Check for a change in the allowed/not-allowed state.  Update if needed
    312     // and return true if there was a change made.
    313     bool ret = false;
    314     if (initial.allowed != current.allowed) {
    315         updateMe.allowed = current.allowed;
    316         ret = true;
    317     }
    318 
    319     // Look for an instance of the output to be updated in case other changes
    320     // were made.
    321     AudioOutputList::iterator I;
    322     for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) {
    323         if (outDevMask == (*I)->devMask()) {
    324             out = (*I);
    325             break;
    326         }
    327     }
    328 
    329     // Update the other settings, if needed.
    330     if (initial.delayCompUsec != current.delayCompUsec) {
    331         updateMe.delayCompUsec = current.delayCompUsec;
    332         if (out != NULL)
    333             out->setExternalDelay_uSec(current.delayCompUsec);
    334     }
    335 
    336     if (initial.isFixed != current.isFixed) {
    337         updateMe.isFixed = current.isFixed;
    338         if (out != NULL)
    339             out->setOutputIsFixed(current.isFixed);
    340     }
    341 
    342     if (initial.fixedLvl != current.fixedLvl) {
    343         updateMe.fixedLvl = current.fixedLvl;
    344         if (out != NULL)
    345             out->setFixedOutputLevel(current.fixedLvl);
    346     }
    347 
    348     return ret;
    349 }
    350 
    351 
    352 char* AudioHardwareOutput::getParameters(const char* keys) {
    353     Settings s;
    354 
    355     // Explicit scope for auto-lock pattern.
    356     {
    357         // Snapshot the current settings so we don't have to hold the settings
    358         // lock while formatting the results.
    359         Mutex::Autolock _l(mSettingsLock);
    360         s = mSettings;
    361     }
    362 
    363     AudioParameter param = AudioParameter(String8(keys));
    364     String8 tmp;
    365 
    366     /***************************************************************
    367      *                     HDMI Audio Options                      *
    368      ***************************************************************/
    369     if (param.get(kHDMIAllowedParamKey, tmp) == NO_ERROR)
    370         param.addInt(kHDMIAllowedParamKey, s.hdmi.allowed ? 1 : 0);
    371 
    372     if (param.get(kHDMIDelayCompParamKey, tmp) == NO_ERROR)
    373         param.addFloat(kHDMIDelayCompParamKey,
    374                        static_cast<float>(s.hdmi.delayCompUsec) / 1000.0);
    375 
    376     if (param.get(kFixedHDMIOutputParamKey, tmp) == NO_ERROR)
    377         param.addInt(kFixedHDMIOutputParamKey, s.hdmi.isFixed ? 1 : 0);
    378 
    379     if (param.get(kFixedHDMIOutputLevelParamKey, tmp) == NO_ERROR)
    380         param.addFloat(kFixedHDMIOutputLevelParamKey, s.hdmi.fixedLvl);
    381 
    382     /***************************************************************
    383      *                       Other Options                         *
    384      ***************************************************************/
    385     if (param.get(kVideoDelayCompParamKey, tmp) == NO_ERROR)
    386         param.addFloat(kVideoDelayCompParamKey,
    387                        static_cast<float>(s.videoDelayCompUsec) / 1000.0);
    388 
    389     return strdup(param.toString().string());
    390 }
    391 
    392 void AudioHardwareOutput::updateRouting(uint32_t devMask) {
    393     Mutex::Autolock _l(mStreamLock);
    394 
    395     bool hasHDMI = 0 != (devMask & HDMIAudioOutput::classDevMask());
    396     ALOGI("%s: hasHDMI = %d, mHDMIConnected = %d", __func__, hasHDMI, mHDMIConnected);
    397     if (mHDMIConnected != hasHDMI) {
    398         mHDMIConnected = hasHDMI;
    399 
    400         if (mHDMIConnected)
    401             mHDMIAudioCaps.loadCaps(mHDMICardID);
    402         else
    403             mHDMIAudioCaps.reset();
    404 
    405         updateTgtDevices_l();
    406     }
    407 }
    408 
    409 status_t AudioHardwareOutput::obtainOutput(const AudioStreamOut& tgtStream,
    410                                      uint32_t devMask,
    411                                      sp<AudioOutput>* newOutput) {
    412     Mutex::Autolock _l1(mOutputLock);
    413 
    414     // Sanity check the device mask passed to us.  There should exactly one bit
    415     // set, no less, no more.
    416     if (popcount(devMask) != 1) {
    417         ALOGW("bad device mask in obtainOutput, %08x", devMask);
    418         return INVALID_OPERATION;
    419     }
    420 
    421     // Start by checking to see if the requested output is currently busy.
    422     AudioOutputList::iterator I;
    423     for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I)
    424         if (devMask & (*I)->devMask())
    425             return OK; // Yup; its busy.
    426 
    427     // Looks like we don't currently have an output of the requested type.
    428     // Figure out which type is being requested and try to construct one.
    429     OutputSettings* S = NULL;
    430     if (devMask & HDMIAudioOutput::classDevMask()) {
    431         *newOutput = new HDMIAudioOutput();
    432         S = &mSettings.hdmi;
    433     }
    434     else {
    435         ALOGW("%s stream out requested output of unknown type %08x",
    436                 tgtStream.getName(), devMask);
    437         return BAD_VALUE;
    438     }
    439 
    440     if (*newOutput == NULL)
    441         return NO_MEMORY;
    442 
    443     status_t res = (*newOutput)->setupForStream(tgtStream);
    444     if (res != OK) {
    445         ALOGE("%s setupForStream() returned %d",
    446               tgtStream.getName(), res);
    447         *newOutput = NULL;
    448     } else {
    449         ALOGI("%s stream out adding %s output.",
    450                 tgtStream.getName(), (*newOutput)->getOutputName());
    451         mPhysOutputs.push_back(*newOutput);
    452 
    453         {  // Apply current settings
    454             Mutex::Autolock _l2(mSettingsLock);
    455             (*newOutput)->setVolume(mSettings.masterVolume);
    456             (*newOutput)->setMute(mSettings.masterMute);
    457             (*newOutput)->setExternalDelay_uSec(S->delayCompUsec);
    458             (*newOutput)->setOutputIsFixed(S->isFixed);
    459             (*newOutput)->setFixedOutputLevel(S->fixedLvl);
    460         }
    461     }
    462 
    463     return res;
    464 }
    465 
    466 void AudioHardwareOutput::releaseOutput(const AudioStreamOut& tgtStream,
    467                                         const sp<AudioOutput>& releaseMe) {
    468     Mutex::Autolock _l(mOutputLock);
    469 
    470     ALOGI("%s stream out removing %s output.",
    471             tgtStream.getName(), releaseMe->getOutputName());
    472 
    473     // Immediately release any resources associated with this output (In
    474     // particular, make sure to close any ALSA device driver handles ASAP)
    475     releaseMe->cleanupResources();
    476 
    477     // Now, clear our internal bookkeeping.
    478     AudioOutputList::iterator I;
    479     for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) {
    480         if (releaseMe.get() == (*I).get()) {
    481             mPhysOutputs.erase(I);
    482             break;
    483         }
    484     }
    485 }
    486 
    487 void AudioHardwareOutput::updateTgtDevices_l() {
    488     // ASSERT(holding mStreamLock)
    489     uint32_t mcMask = 0;
    490     uint32_t mainMask = 0;
    491 
    492     {
    493         Mutex::Autolock _l(mSettingsLock);
    494         if (mSettings.hdmi.allowed && mHDMIConnected) {
    495             if (NULL != mMCOutput)
    496                 mcMask |= HDMIAudioOutput::classDevMask();
    497             else
    498                 mainMask |= HDMIAudioOutput::classDevMask();
    499         }
    500     }
    501 
    502     if (NULL != mMainOutput)
    503         mMainOutput->setTgtDevices(mainMask);
    504 
    505     if (NULL != mMCOutput)
    506         mMCOutput->setTgtDevices(mcMask);
    507 }
    508 
    509 void AudioHardwareOutput::standbyStatusUpdate(bool isInStandby, bool isMCStream) {
    510 
    511     Mutex::Autolock _l1(mStreamLock);
    512     Mutex::Autolock _l2(mSettingsLock);
    513 
    514     // If there is no HDMI, do nothing
    515     if (mSettings.hdmi.allowed && mHDMIConnected) {
    516         // If a multi-channel stream goes to standy state, we must switch
    517         // to stereo stream. If MC comes out of standby, we must switch
    518         // back to MC. No special processing needed for main stream.
    519         // AudioStreamOut class handles that correctly
    520         if (isMCStream) {
    521             uint32_t mcMask;
    522             uint32_t mainMask;
    523             if (isInStandby) {
    524                 mainMask = HDMIAudioOutput::classDevMask();
    525                 mcMask = 0;
    526             } else {
    527                 mainMask = 0;
    528                 mcMask = HDMIAudioOutput::classDevMask();
    529             }
    530 
    531             if (NULL != mMainOutput)
    532                 mMainOutput->setTgtDevices(mainMask);
    533 
    534             if (NULL != mMCOutput)
    535                 mMCOutput->setTgtDevices(mcMask);
    536         }
    537     }
    538 }
    539 
    540 #define DUMP(a...) \
    541     snprintf(buffer, SIZE, a); \
    542     buffer[SIZE - 1] = 0; \
    543     result.append(buffer);
    544 #define B2STR(b) b ? "true" : "false"
    545 
    546 status_t AudioHardwareOutput::dump(int fd)
    547 {
    548     const size_t SIZE = 256;
    549     char buffer[SIZE];
    550     String8 result;
    551     Settings s;
    552 
    553     // Explicit scope for auto-lock pattern.
    554     {
    555         // Snapshot the current settings so we don't have to hold the settings
    556         // lock while formatting the results.
    557         Mutex::Autolock _l(mSettingsLock);
    558         s = mSettings;
    559     }
    560 
    561     DUMP("AudioHardwareOutput::dump\n");
    562     DUMP("\tMaster Volume          : %0.3f\n", s.masterVolume);
    563     DUMP("\tMaster Mute            : %s\n", B2STR(s.masterMute));
    564     DUMP("\tHDMI Output Allowed    : %s\n", B2STR(s.hdmi.allowed));
    565     DUMP("\tHDMI Delay Comp        : %u uSec\n", s.hdmi.delayCompUsec);
    566     DUMP("\tHDMI Output Fixed      : %s\n", B2STR(s.hdmi.isFixed));
    567     DUMP("\tHDMI Fixed Level       : %.1f dB\n", s.hdmi.fixedLvl);
    568     DUMP("\tVideo Delay Comp       : %u uSec\n", s.videoDelayCompUsec);
    569 
    570     ::write(fd, result.string(), result.size());
    571 
    572     // Explicit scope for auto-lock pattern.
    573     {
    574         Mutex::Autolock _l(mOutputLock);
    575         if (mMainOutput)
    576             mMainOutput->dump(fd);
    577 
    578         if (mMCOutput)
    579             mMCOutput->dump(fd);
    580     }
    581 
    582     return NO_ERROR;
    583 }
    584 
    585 #undef B2STR
    586 #undef DUMP
    587 
    588 }; // namespace android
    589