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     bool isIec958NonAudio = (flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO) != 0;
    119     if (!(flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
    120         pp_out = &mMainOutput;
    121         out = new AudioStreamOut(*this, false, isIec958NonAudio);
    122     } else {
    123         pp_out = &mMCOutput;
    124         out = new AudioStreamOut(*this, true, isIec958NonAudio);
    125     }
    126 
    127     if (out == NULL) {
    128         *status = NO_MEMORY;
    129         return NULL;
    130     }
    131 
    132     *status = out->set(format, channels, sampleRate);
    133 
    134     if (*status == NO_ERROR) {
    135         *pp_out = out;
    136         updateTgtDevices_l();
    137     } else {
    138         delete out;
    139     }
    140 
    141     return *pp_out;
    142 }
    143 
    144 void AudioHardwareOutput::closeOutputStream(AudioStreamOut* out) {
    145     if (out == NULL)
    146         return;
    147 
    148     // Putting the stream into "standby" should cause it to release all of its
    149     // physical outputs.
    150     out->standby();
    151 
    152     {
    153         Mutex::Autolock _l(mStreamLock);
    154         if (mMainOutput && out == mMainOutput) {
    155             delete mMainOutput;
    156             mMainOutput = NULL;
    157         } else if (mMCOutput && out == mMCOutput) {
    158             delete mMCOutput;
    159             mMCOutput = NULL;
    160         }
    161 
    162         updateTgtDevices_l();
    163     }
    164 }
    165 
    166 status_t AudioHardwareOutput::setMasterVolume(float volume)
    167 {
    168     Mutex::Autolock _l1(mOutputLock);
    169     Mutex::Autolock _l2(mSettingsLock);
    170 
    171     mSettings.masterVolume = volume;
    172 
    173     AudioOutputList::iterator I;
    174     for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I)
    175         (*I)->setVolume(mSettings.masterVolume);
    176 
    177     return NO_ERROR;
    178 }
    179 
    180 status_t AudioHardwareOutput::getMasterVolume(float* volume) {
    181 
    182     if (NULL == volume)
    183         return BAD_VALUE;
    184 
    185     // Explicit scope for auto-lock pattern.
    186     {
    187         Mutex::Autolock _l(mSettingsLock);
    188         *volume = mSettings.masterVolume;
    189     }
    190 
    191     return NO_ERROR;
    192 }
    193 
    194 status_t AudioHardwareOutput::setMasterMute(bool muted)
    195 {
    196     Mutex::Autolock _l1(mOutputLock);
    197     Mutex::Autolock _l2(mSettingsLock);
    198 
    199     mSettings.masterMute = muted;
    200 
    201     AudioOutputList::iterator I;
    202     for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I)
    203         (*I)->setMute(mSettings.masterMute);
    204 
    205     return NO_ERROR;
    206 }
    207 
    208 status_t AudioHardwareOutput::getMasterMute(bool* muted) {
    209     if (NULL == muted)
    210         return BAD_VALUE;
    211 
    212     // Explicit scope for auto-lock pattern.
    213     {
    214         Mutex::Autolock _l(mSettingsLock);
    215         *muted = mSettings.masterMute;
    216     }
    217 
    218     return NO_ERROR;
    219 }
    220 
    221 status_t AudioHardwareOutput::setParameters(const char* kvpairs) {
    222     AudioParameter param = AudioParameter(String8(kvpairs));
    223     status_t status = NO_ERROR;
    224     float floatVal;
    225     int intVal;
    226     Settings initial, s;
    227 
    228     {
    229         // Record the initial state of the settings from inside the lock.  Then
    230         // leave the lock in order to parse the changes to be made.
    231         Mutex::Autolock _l(mSettingsLock);
    232         initial = s = mSettings;
    233     }
    234 
    235     /***************************************************************
    236      *                     HDMI Audio Options                      *
    237      ***************************************************************/
    238     if (param.getInt(kHDMIAllowedParamKey, intVal) == NO_ERROR) {
    239         s.hdmi.allowed = (intVal != 0);
    240         param.remove(kHDMIAllowedParamKey);
    241     }
    242 
    243     if ((param.getFloat(kHDMIDelayCompParamKey, floatVal) == NO_ERROR) &&
    244         (floatVal >= 0.0) &&
    245         (floatVal <= AudioOutput::kMaxDelayCompensationMSec)) {
    246         uint32_t delay_comp = static_cast<uint32_t>(floatVal * 1000.0);
    247         s.hdmi.delayCompUsec = delay_comp;
    248         param.remove(kHDMIDelayCompParamKey);
    249     }
    250 
    251     if (param.getInt(kFixedHDMIOutputParamKey, intVal) == NO_ERROR) {
    252         s.hdmi.isFixed = (intVal != 0);
    253         param.remove(kFixedHDMIOutputParamKey);
    254     }
    255 
    256     if ((param.getFloat(kFixedHDMIOutputLevelParamKey, floatVal) == NO_ERROR)
    257         && (floatVal <= 0.0)) {
    258         s.hdmi.fixedLvl = floatVal;
    259         param.remove(kFixedHDMIOutputLevelParamKey);
    260     }
    261 
    262     /***************************************************************
    263      *                       Other Options                         *
    264      ***************************************************************/
    265     if ((param.getFloat(kVideoDelayCompParamKey, floatVal) == NO_ERROR) &&
    266         (floatVal >= 0.0) &&
    267         (floatVal <= AudioOutput::kMaxDelayCompensationMSec)) {
    268         s.videoDelayCompUsec = static_cast<uint32_t>(floatVal * 1000.0);
    269         param.remove(kVideoDelayCompParamKey);
    270     }
    271 
    272     if (param.size())
    273         status = BAD_VALUE;
    274 
    275     // If there was a change made to settings, go ahead and apply it now.
    276     bool allowedOutputsChanged = false;
    277     if (memcmp(&initial, &s, sizeof(initial)))  {
    278         Mutex::Autolock _l1(mOutputLock);
    279         Mutex::Autolock _l2(mSettingsLock);
    280 
    281         if (memcmp(&initial.hdmi, &s.hdmi, sizeof(initial.hdmi)))
    282             allowedOutputsChanged = allowedOutputsChanged ||
    283                 applyOutputSettings_l(initial.hdmi, s.hdmi, mSettings.hdmi,
    284                                       HDMIAudioOutput::classDevMask());
    285 
    286         if (initial.videoDelayCompUsec != s.videoDelayCompUsec)
    287             mSettings.videoDelayCompUsec = s.videoDelayCompUsec;
    288 
    289         uint32_t tmp = 0;
    290         if (mSettings.hdmi.allowed && (tmp < mSettings.hdmi.delayCompUsec))
    291             tmp = mSettings.hdmi.delayCompUsec;
    292         if (mMaxDelayCompUsec != tmp)
    293             mMaxDelayCompUsec = tmp;
    294     }
    295 
    296     if (allowedOutputsChanged) {
    297         Mutex::Autolock _l(mStreamLock);
    298         updateTgtDevices_l();
    299     }
    300 
    301     return status;
    302 }
    303 
    304 bool AudioHardwareOutput::applyOutputSettings_l(
    305         const AudioHardwareOutput::OutputSettings& initial,
    306         const AudioHardwareOutput::OutputSettings& current,
    307         AudioHardwareOutput::OutputSettings& updateMe,
    308         uint32_t outDevMask) {
    309     // ASSERT(holding mOutputLock and mSettingsLock)
    310     sp<AudioOutput> out;
    311 
    312     // Check for a change in the allowed/not-allowed state.  Update if needed
    313     // and return true if there was a change made.
    314     bool ret = false;
    315     if (initial.allowed != current.allowed) {
    316         updateMe.allowed = current.allowed;
    317         ret = true;
    318     }
    319 
    320     // Look for an instance of the output to be updated in case other changes
    321     // were made.
    322     AudioOutputList::iterator I;
    323     for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) {
    324         if (outDevMask == (*I)->devMask()) {
    325             out = (*I);
    326             break;
    327         }
    328     }
    329 
    330     // Update the other settings, if needed.
    331     if (initial.delayCompUsec != current.delayCompUsec) {
    332         updateMe.delayCompUsec = current.delayCompUsec;
    333         if (out != NULL)
    334             out->setExternalDelay_uSec(current.delayCompUsec);
    335     }
    336 
    337     if (initial.isFixed != current.isFixed) {
    338         updateMe.isFixed = current.isFixed;
    339         if (out != NULL)
    340             out->setOutputIsFixed(current.isFixed);
    341     }
    342 
    343     if (initial.fixedLvl != current.fixedLvl) {
    344         updateMe.fixedLvl = current.fixedLvl;
    345         if (out != NULL)
    346             out->setFixedOutputLevel(current.fixedLvl);
    347     }
    348 
    349     return ret;
    350 }
    351 
    352 
    353 char* AudioHardwareOutput::getParameters(const char* keys) {
    354     Settings s;
    355 
    356     // Explicit scope for auto-lock pattern.
    357     {
    358         // Snapshot the current settings so we don't have to hold the settings
    359         // lock while formatting the results.
    360         Mutex::Autolock _l(mSettingsLock);
    361         s = mSettings;
    362     }
    363 
    364     AudioParameter param = AudioParameter(String8(keys));
    365     String8 tmp;
    366 
    367     /***************************************************************
    368      *                     HDMI Audio Options                      *
    369      ***************************************************************/
    370     if (param.get(kHDMIAllowedParamKey, tmp) == NO_ERROR)
    371         param.addInt(kHDMIAllowedParamKey, s.hdmi.allowed ? 1 : 0);
    372 
    373     if (param.get(kHDMIDelayCompParamKey, tmp) == NO_ERROR)
    374         param.addFloat(kHDMIDelayCompParamKey,
    375                        static_cast<float>(s.hdmi.delayCompUsec) / 1000.0);
    376 
    377     if (param.get(kFixedHDMIOutputParamKey, tmp) == NO_ERROR)
    378         param.addInt(kFixedHDMIOutputParamKey, s.hdmi.isFixed ? 1 : 0);
    379 
    380     if (param.get(kFixedHDMIOutputLevelParamKey, tmp) == NO_ERROR)
    381         param.addFloat(kFixedHDMIOutputLevelParamKey, s.hdmi.fixedLvl);
    382 
    383     /***************************************************************
    384      *                       Other Options                         *
    385      ***************************************************************/
    386     if (param.get(kVideoDelayCompParamKey, tmp) == NO_ERROR)
    387         param.addFloat(kVideoDelayCompParamKey,
    388                        static_cast<float>(s.videoDelayCompUsec) / 1000.0);
    389 
    390     return strdup(param.toString().string());
    391 }
    392 
    393 void AudioHardwareOutput::updateRouting(uint32_t devMask) {
    394     Mutex::Autolock _l(mStreamLock);
    395 
    396     bool hasHDMI = 0 != (devMask & HDMIAudioOutput::classDevMask());
    397     ALOGI("%s: hasHDMI = %d, mHDMIConnected = %d", __func__, hasHDMI, mHDMIConnected);
    398     if (mHDMIConnected != hasHDMI) {
    399         mHDMIConnected = hasHDMI;
    400 
    401         if (mHDMIConnected)
    402             mHDMIAudioCaps.loadCaps(mHDMICardID);
    403         else
    404             mHDMIAudioCaps.reset();
    405 
    406         updateTgtDevices_l();
    407     }
    408 }
    409 
    410 status_t AudioHardwareOutput::obtainOutput(const AudioStreamOut& tgtStream,
    411                                      uint32_t devMask,
    412                                      sp<AudioOutput>* newOutput) {
    413     Mutex::Autolock _l1(mOutputLock);
    414 
    415     // Sanity check the device mask passed to us.  There should exactly one bit
    416     // set, no less, no more.
    417     if (popcount(devMask) != 1) {
    418         ALOGW("bad device mask in obtainOutput, %08x", devMask);
    419         return INVALID_OPERATION;
    420     }
    421 
    422     // Start by checking to see if the requested output is currently busy.
    423     AudioOutputList::iterator I;
    424     for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I)
    425         if (devMask & (*I)->devMask())
    426             return OK; // Yup; its busy.
    427 
    428     // Looks like we don't currently have an output of the requested type.
    429     // Figure out which type is being requested and try to construct one.
    430     OutputSettings* S = NULL;
    431     if (devMask & HDMIAudioOutput::classDevMask()) {
    432         *newOutput = new HDMIAudioOutput();
    433         S = &mSettings.hdmi;
    434     }
    435     else {
    436         ALOGW("%s stream out requested output of unknown type %08x",
    437                 tgtStream.getName(), devMask);
    438         return BAD_VALUE;
    439     }
    440 
    441     if (*newOutput == NULL)
    442         return NO_MEMORY;
    443 
    444     status_t res = (*newOutput)->setupForStream(tgtStream);
    445     if (res != OK) {
    446         ALOGE("%s setupForStream() returned %d",
    447               tgtStream.getName(), res);
    448         *newOutput = NULL;
    449     } else {
    450         ALOGI("%s stream out adding %s output.",
    451                 tgtStream.getName(), (*newOutput)->getOutputName());
    452         mPhysOutputs.push_back(*newOutput);
    453 
    454         {  // Apply current settings
    455             Mutex::Autolock _l2(mSettingsLock);
    456             (*newOutput)->setVolume(mSettings.masterVolume);
    457             (*newOutput)->setMute(mSettings.masterMute);
    458             (*newOutput)->setExternalDelay_uSec(S->delayCompUsec);
    459             (*newOutput)->setOutputIsFixed(S->isFixed);
    460             (*newOutput)->setFixedOutputLevel(S->fixedLvl);
    461         }
    462     }
    463 
    464     return res;
    465 }
    466 
    467 void AudioHardwareOutput::releaseOutput(const AudioStreamOut& tgtStream,
    468                                         const sp<AudioOutput>& releaseMe) {
    469     Mutex::Autolock _l(mOutputLock);
    470 
    471     ALOGI("%s stream out removing %s output.",
    472             tgtStream.getName(), releaseMe->getOutputName());
    473 
    474     // Immediately release any resources associated with this output (In
    475     // particular, make sure to close any ALSA device driver handles ASAP)
    476     releaseMe->cleanupResources();
    477 
    478     // Now, clear our internal bookkeeping.
    479     AudioOutputList::iterator I;
    480     for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) {
    481         if (releaseMe.get() == (*I).get()) {
    482             mPhysOutputs.erase(I);
    483             break;
    484         }
    485     }
    486 }
    487 
    488 void AudioHardwareOutput::updateTgtDevices_l() {
    489     // ASSERT(holding mStreamLock)
    490     uint32_t mcMask = 0;
    491     uint32_t mainMask = 0;
    492 
    493     {
    494         Mutex::Autolock _l(mSettingsLock);
    495         if (mSettings.hdmi.allowed && mHDMIConnected) {
    496             if (NULL != mMCOutput)
    497                 mcMask |= HDMIAudioOutput::classDevMask();
    498             else
    499                 mainMask |= HDMIAudioOutput::classDevMask();
    500         }
    501     }
    502 
    503     if (NULL != mMainOutput)
    504         mMainOutput->setTgtDevices(mainMask);
    505 
    506     if (NULL != mMCOutput)
    507         mMCOutput->setTgtDevices(mcMask);
    508 }
    509 
    510 void AudioHardwareOutput::standbyStatusUpdate(bool isInStandby, bool isMCStream) {
    511 
    512     Mutex::Autolock _l1(mStreamLock);
    513     bool hdmiAllowed;
    514     {
    515         Mutex::Autolock _l2(mSettingsLock);
    516         hdmiAllowed = mSettings.hdmi.allowed;
    517     }
    518     // If there is no HDMI, do nothing
    519     if (hdmiAllowed && mHDMIConnected) {
    520         // If a multi-channel stream goes to standy state, we must switch
    521         // to stereo stream. If MC comes out of standby, we must switch
    522         // back to MC. No special processing needed for main stream.
    523         // AudioStreamOut class handles that correctly
    524         if (isMCStream) {
    525             uint32_t mcMask;
    526             uint32_t mainMask;
    527             if (isInStandby) {
    528                 mainMask = HDMIAudioOutput::classDevMask();
    529                 mcMask = 0;
    530             } else {
    531                 mainMask = 0;
    532                 mcMask = HDMIAudioOutput::classDevMask();
    533             }
    534 
    535             if (NULL != mMainOutput)
    536                 mMainOutput->setTgtDevices(mainMask);
    537 
    538             if (NULL != mMCOutput)
    539                 mMCOutput->setTgtDevices(mcMask);
    540         }
    541     }
    542 }
    543 
    544 #define DUMP(a...) \
    545     snprintf(buffer, SIZE, a); \
    546     buffer[SIZE - 1] = 0; \
    547     result.append(buffer);
    548 #define B2STR(b) b ? "true" : "false"
    549 
    550 status_t AudioHardwareOutput::dump(int fd)
    551 {
    552     const size_t SIZE = 256;
    553     char buffer[SIZE];
    554     String8 result;
    555     Settings s;
    556 
    557     // Explicit scope for auto-lock pattern.
    558     {
    559         // Snapshot the current settings so we don't have to hold the settings
    560         // lock while formatting the results.
    561         Mutex::Autolock _l(mSettingsLock);
    562         s = mSettings;
    563     }
    564 
    565     DUMP("AudioHardwareOutput::dump\n");
    566     DUMP("\tMaster Volume          : %0.3f\n", s.masterVolume);
    567     DUMP("\tMaster Mute            : %s\n", B2STR(s.masterMute));
    568     DUMP("\tHDMI Output Allowed    : %s\n", B2STR(s.hdmi.allowed));
    569     DUMP("\tHDMI Delay Comp        : %u uSec\n", s.hdmi.delayCompUsec);
    570     DUMP("\tHDMI Output Fixed      : %s\n", B2STR(s.hdmi.isFixed));
    571     DUMP("\tHDMI Fixed Level       : %.1f dB\n", s.hdmi.fixedLvl);
    572     DUMP("\tVideo Delay Comp       : %u uSec\n", s.videoDelayCompUsec);
    573 
    574     ::write(fd, result.string(), result.size());
    575 
    576     // Explicit scope for auto-lock pattern.
    577     {
    578         Mutex::Autolock _l(mOutputLock);
    579         if (mMainOutput)
    580             mMainOutput->dump(fd);
    581 
    582         if (mMCOutput)
    583             mMCOutput->dump(fd);
    584     }
    585 
    586     return NO_ERROR;
    587 }
    588 
    589 #undef B2STR
    590 #undef DUMP
    591 
    592 }; // namespace android
    593