/*
**
** Copyright 2014, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

#define LOG_TAG "AudioHAL_AudioHardwareOutput"

#include <utils/Log.h>

#include <stdint.h>
#include <limits.h>
#include <math.h>

#include <common_time/local_clock.h>
#include <cutils/properties.h>

#include "AudioHardwareOutput.h"
#include "AudioStreamOut.h"
#include "HDMIAudioOutput.h"

namespace android {

// Global singleton.
AudioHardwareOutput gAudioHardwareOutput;

// HDMI options.
const String8 AudioHardwareOutput::kHDMIAllowedParamKey(
        "atv.hdmi_audio.allowed");
const String8 AudioHardwareOutput::kHDMIDelayCompParamKey(
        "atv.hdmi.audio_delay");
const String8 AudioHardwareOutput::kFixedHDMIOutputParamKey(
        "atv.hdmi.fixed_volume");
const String8 AudioHardwareOutput::kFixedHDMIOutputLevelParamKey(
        "atv.hdmi.fixed_level");

// Video delay comp hack options (not exposed to user level)
const String8 AudioHardwareOutput::kVideoDelayCompParamKey(
        "atv.video.delay_comp");

// Defaults for settings.
void AudioHardwareOutput::OutputSettings::setDefaults()
{
    allowed = true;
    delayCompUsec = 0;
    isFixed = false;
    fixedLvl = 0.0f;
}

void AudioHardwareOutput::Settings::setDefaults() {
    hdmi.setDefaults();

    masterVolume = 0.60;
    masterMute = false;

    // Default this to 16mSec or so.  Since audio start times are not sync'ed to
    // to the VBI, there should be a +/-0.5 output frame rate error in the AV
    // sync, even under the best of circumstances.
    //
    // In practice, the android core seems to have a hard time hitting its frame
    // cadence consistently.  Sometimes the frames are on time, and sometimes
    // they are even a little early, but more often than not, the frames are
    // late by about a full output frame time.
    //
    // ATV pretty much always uses a 60fps output rate, and the only thing
    // consuming the latency estimate provided by the HAL is the path handling
    // AV sync.  For now, we can fudge this number to move things back in the
    // direction of correct by providing a setting for video delay compensation
    // which will be subtracted from the latency estimate and defaulting it to
    // a reasonable middle gound (12mSec in this case).
    videoDelayCompUsec = 12000;
}

AudioHardwareOutput::AudioHardwareOutput()
  : mMainOutput(NULL)
  , mMCOutput(NULL)
  , mHDMIConnected(false)
  , mMaxDelayCompUsec(0)
{
    mSettings.setDefaults();
    mHDMICardID = find_alsa_card_by_name(kHDMI_ALSADeviceName);
}

AudioHardwareOutput::~AudioHardwareOutput()
{
    closeOutputStream(mMainOutput);
    closeOutputStream(mMCOutput);
}

status_t AudioHardwareOutput::initCheck() {
    return NO_ERROR;
}

AudioStreamOut* AudioHardwareOutput::openOutputStream(
        uint32_t devices,
        audio_format_t *format,
        uint32_t *channels,
        uint32_t *sampleRate,
        audio_output_flags_t flags,
        status_t *status) {
    (void) devices;
    AutoMutex lock(mStreamLock);

    AudioStreamOut** pp_out;
    AudioStreamOut* out;

    bool isIec958NonAudio = (flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO) != 0;
    if (!(flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
        pp_out = &mMainOutput;
        out = new AudioStreamOut(*this, false, isIec958NonAudio);
    } else {
        pp_out = &mMCOutput;
        out = new AudioStreamOut(*this, true, isIec958NonAudio);
    }

    if (out == NULL) {
        *status = NO_MEMORY;
        return NULL;
    }

    *status = out->set(format, channels, sampleRate);

    if (*status == NO_ERROR) {
        *pp_out = out;
        updateTgtDevices_l();
    } else {
        delete out;
    }

    return *pp_out;
}

void AudioHardwareOutput::closeOutputStream(AudioStreamOut* out) {
    if (out == NULL)
        return;

    // Putting the stream into "standby" should cause it to release all of its
    // physical outputs.
    out->standby();

    {
        Mutex::Autolock _l(mStreamLock);
        if (mMainOutput && out == mMainOutput) {
            delete mMainOutput;
            mMainOutput = NULL;
        } else if (mMCOutput && out == mMCOutput) {
            delete mMCOutput;
            mMCOutput = NULL;
        }

        updateTgtDevices_l();
    }
}

status_t AudioHardwareOutput::setMasterVolume(float volume)
{
    Mutex::Autolock _l1(mOutputLock);
    Mutex::Autolock _l2(mSettingsLock);

    mSettings.masterVolume = volume;

    AudioOutputList::iterator I;
    for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I)
        (*I)->setVolume(mSettings.masterVolume);

    return NO_ERROR;
}

status_t AudioHardwareOutput::getMasterVolume(float* volume) {

    if (NULL == volume)
        return BAD_VALUE;

    // Explicit scope for auto-lock pattern.
    {
        Mutex::Autolock _l(mSettingsLock);
        *volume = mSettings.masterVolume;
    }

    return NO_ERROR;
}

status_t AudioHardwareOutput::setMasterMute(bool muted)
{
    Mutex::Autolock _l1(mOutputLock);
    Mutex::Autolock _l2(mSettingsLock);

    mSettings.masterMute = muted;

    AudioOutputList::iterator I;
    for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I)
        (*I)->setMute(mSettings.masterMute);

    return NO_ERROR;
}

status_t AudioHardwareOutput::getMasterMute(bool* muted) {
    if (NULL == muted)
        return BAD_VALUE;

    // Explicit scope for auto-lock pattern.
    {
        Mutex::Autolock _l(mSettingsLock);
        *muted = mSettings.masterMute;
    }

    return NO_ERROR;
}

status_t AudioHardwareOutput::setParameters(const char* kvpairs) {
    AudioParameter param = AudioParameter(String8(kvpairs));
    status_t status = NO_ERROR;
    float floatVal;
    int intVal;
    Settings initial, s;

    {
        // Record the initial state of the settings from inside the lock.  Then
        // leave the lock in order to parse the changes to be made.
        Mutex::Autolock _l(mSettingsLock);
        initial = s = mSettings;
    }

    /***************************************************************
     *                     HDMI Audio Options                      *
     ***************************************************************/
    if (param.getInt(kHDMIAllowedParamKey, intVal) == NO_ERROR) {
        s.hdmi.allowed = (intVal != 0);
        param.remove(kHDMIAllowedParamKey);
    }

    if ((param.getFloat(kHDMIDelayCompParamKey, floatVal) == NO_ERROR) &&
        (floatVal >= 0.0) &&
        (floatVal <= AudioOutput::kMaxDelayCompensationMSec)) {
        uint32_t delay_comp = static_cast<uint32_t>(floatVal * 1000.0);
        s.hdmi.delayCompUsec = delay_comp;
        param.remove(kHDMIDelayCompParamKey);
    }

    if (param.getInt(kFixedHDMIOutputParamKey, intVal) == NO_ERROR) {
        s.hdmi.isFixed = (intVal != 0);
        param.remove(kFixedHDMIOutputParamKey);
    }

    if ((param.getFloat(kFixedHDMIOutputLevelParamKey, floatVal) == NO_ERROR)
        && (floatVal <= 0.0)) {
        s.hdmi.fixedLvl = floatVal;
        param.remove(kFixedHDMIOutputLevelParamKey);
    }

    /***************************************************************
     *                       Other Options                         *
     ***************************************************************/
    if ((param.getFloat(kVideoDelayCompParamKey, floatVal) == NO_ERROR) &&
        (floatVal >= 0.0) &&
        (floatVal <= AudioOutput::kMaxDelayCompensationMSec)) {
        s.videoDelayCompUsec = static_cast<uint32_t>(floatVal * 1000.0);
        param.remove(kVideoDelayCompParamKey);
    }

    if (param.size())
        status = BAD_VALUE;

    // If there was a change made to settings, go ahead and apply it now.
    bool allowedOutputsChanged = false;
    if (memcmp(&initial, &s, sizeof(initial)))  {
        Mutex::Autolock _l1(mOutputLock);
        Mutex::Autolock _l2(mSettingsLock);

        if (memcmp(&initial.hdmi, &s.hdmi, sizeof(initial.hdmi)))
            allowedOutputsChanged = allowedOutputsChanged ||
                applyOutputSettings_l(initial.hdmi, s.hdmi, mSettings.hdmi,
                                      HDMIAudioOutput::classDevMask());

        if (initial.videoDelayCompUsec != s.videoDelayCompUsec)
            mSettings.videoDelayCompUsec = s.videoDelayCompUsec;

        uint32_t tmp = 0;
        if (mSettings.hdmi.allowed && (tmp < mSettings.hdmi.delayCompUsec))
            tmp = mSettings.hdmi.delayCompUsec;
        if (mMaxDelayCompUsec != tmp)
            mMaxDelayCompUsec = tmp;
    }

    if (allowedOutputsChanged) {
        Mutex::Autolock _l(mStreamLock);
        updateTgtDevices_l();
    }

    return status;
}

bool AudioHardwareOutput::applyOutputSettings_l(
        const AudioHardwareOutput::OutputSettings& initial,
        const AudioHardwareOutput::OutputSettings& current,
        AudioHardwareOutput::OutputSettings& updateMe,
        uint32_t outDevMask) {
    // ASSERT(holding mOutputLock and mSettingsLock)
    sp<AudioOutput> out;

    // Check for a change in the allowed/not-allowed state.  Update if needed
    // and return true if there was a change made.
    bool ret = false;
    if (initial.allowed != current.allowed) {
        updateMe.allowed = current.allowed;
        ret = true;
    }

    // Look for an instance of the output to be updated in case other changes
    // were made.
    AudioOutputList::iterator I;
    for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) {
        if (outDevMask == (*I)->devMask()) {
            out = (*I);
            break;
        }
    }

    // Update the other settings, if needed.
    if (initial.delayCompUsec != current.delayCompUsec) {
        updateMe.delayCompUsec = current.delayCompUsec;
        if (out != NULL)
            out->setExternalDelay_uSec(current.delayCompUsec);
    }

    if (initial.isFixed != current.isFixed) {
        updateMe.isFixed = current.isFixed;
        if (out != NULL)
            out->setOutputIsFixed(current.isFixed);
    }

    if (initial.fixedLvl != current.fixedLvl) {
        updateMe.fixedLvl = current.fixedLvl;
        if (out != NULL)
            out->setFixedOutputLevel(current.fixedLvl);
    }

    return ret;
}


char* AudioHardwareOutput::getParameters(const char* keys) {
    Settings s;

    // Explicit scope for auto-lock pattern.
    {
        // Snapshot the current settings so we don't have to hold the settings
        // lock while formatting the results.
        Mutex::Autolock _l(mSettingsLock);
        s = mSettings;
    }

    AudioParameter param = AudioParameter(String8(keys));
    String8 tmp;

    /***************************************************************
     *                     HDMI Audio Options                      *
     ***************************************************************/
    if (param.get(kHDMIAllowedParamKey, tmp) == NO_ERROR)
        param.addInt(kHDMIAllowedParamKey, s.hdmi.allowed ? 1 : 0);

    if (param.get(kHDMIDelayCompParamKey, tmp) == NO_ERROR)
        param.addFloat(kHDMIDelayCompParamKey,
                       static_cast<float>(s.hdmi.delayCompUsec) / 1000.0);

    if (param.get(kFixedHDMIOutputParamKey, tmp) == NO_ERROR)
        param.addInt(kFixedHDMIOutputParamKey, s.hdmi.isFixed ? 1 : 0);

    if (param.get(kFixedHDMIOutputLevelParamKey, tmp) == NO_ERROR)
        param.addFloat(kFixedHDMIOutputLevelParamKey, s.hdmi.fixedLvl);

    /***************************************************************
     *                       Other Options                         *
     ***************************************************************/
    if (param.get(kVideoDelayCompParamKey, tmp) == NO_ERROR)
        param.addFloat(kVideoDelayCompParamKey,
                       static_cast<float>(s.videoDelayCompUsec) / 1000.0);

    return strdup(param.toString().string());
}

void AudioHardwareOutput::updateRouting(uint32_t devMask) {
    Mutex::Autolock _l(mStreamLock);

    bool hasHDMI = 0 != (devMask & HDMIAudioOutput::classDevMask());
    ALOGI("%s: hasHDMI = %d, mHDMIConnected = %d", __func__, hasHDMI, mHDMIConnected);
    if (mHDMIConnected != hasHDMI) {
        mHDMIConnected = hasHDMI;

        if (mHDMIConnected)
            mHDMIAudioCaps.loadCaps(mHDMICardID);
        else
            mHDMIAudioCaps.reset();

        updateTgtDevices_l();
    }
}

status_t AudioHardwareOutput::obtainOutput(const AudioStreamOut& tgtStream,
                                     uint32_t devMask,
                                     sp<AudioOutput>* newOutput) {
    Mutex::Autolock _l1(mOutputLock);

    // Sanity check the device mask passed to us.  There should exactly one bit
    // set, no less, no more.
    if (popcount(devMask) != 1) {
        ALOGW("bad device mask in obtainOutput, %08x", devMask);
        return INVALID_OPERATION;
    }

    // Start by checking to see if the requested output is currently busy.
    AudioOutputList::iterator I;
    for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I)
        if (devMask & (*I)->devMask())
            return OK; // Yup; its busy.

    // Looks like we don't currently have an output of the requested type.
    // Figure out which type is being requested and try to construct one.
    OutputSettings* S = NULL;
    if (devMask & HDMIAudioOutput::classDevMask()) {
        *newOutput = new HDMIAudioOutput();
        S = &mSettings.hdmi;
    }
    else {
        ALOGW("%s stream out requested output of unknown type %08x",
                tgtStream.getName(), devMask);
        return BAD_VALUE;
    }

    if (*newOutput == NULL)
        return NO_MEMORY;

    status_t res = (*newOutput)->setupForStream(tgtStream);
    if (res != OK) {
        ALOGE("%s setupForStream() returned %d",
              tgtStream.getName(), res);
        *newOutput = NULL;
    } else {
        ALOGI("%s stream out adding %s output.",
                tgtStream.getName(), (*newOutput)->getOutputName());
        mPhysOutputs.push_back(*newOutput);

        {  // Apply current settings
            Mutex::Autolock _l2(mSettingsLock);
            (*newOutput)->setVolume(mSettings.masterVolume);
            (*newOutput)->setMute(mSettings.masterMute);
            (*newOutput)->setExternalDelay_uSec(S->delayCompUsec);
            (*newOutput)->setOutputIsFixed(S->isFixed);
            (*newOutput)->setFixedOutputLevel(S->fixedLvl);
        }
    }

    return res;
}

void AudioHardwareOutput::releaseOutput(const AudioStreamOut& tgtStream,
                                        const sp<AudioOutput>& releaseMe) {
    Mutex::Autolock _l(mOutputLock);

    ALOGI("%s stream out removing %s output.",
            tgtStream.getName(), releaseMe->getOutputName());

    // Immediately release any resources associated with this output (In
    // particular, make sure to close any ALSA device driver handles ASAP)
    releaseMe->cleanupResources();

    // Now, clear our internal bookkeeping.
    AudioOutputList::iterator I;
    for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) {
        if (releaseMe.get() == (*I).get()) {
            mPhysOutputs.erase(I);
            break;
        }
    }
}

void AudioHardwareOutput::updateTgtDevices_l() {
    // ASSERT(holding mStreamLock)
    uint32_t mcMask = 0;
    uint32_t mainMask = 0;

    {
        Mutex::Autolock _l(mSettingsLock);
        if (mSettings.hdmi.allowed && mHDMIConnected) {
            if (NULL != mMCOutput)
                mcMask |= HDMIAudioOutput::classDevMask();
            else
                mainMask |= HDMIAudioOutput::classDevMask();
        }
    }

    if (NULL != mMainOutput)
        mMainOutput->setTgtDevices(mainMask);

    if (NULL != mMCOutput)
        mMCOutput->setTgtDevices(mcMask);
}

void AudioHardwareOutput::standbyStatusUpdate(bool isInStandby, bool isMCStream) {

    Mutex::Autolock _l1(mStreamLock);
    bool hdmiAllowed;
    {
        Mutex::Autolock _l2(mSettingsLock);
        hdmiAllowed = mSettings.hdmi.allowed;
    }
    // If there is no HDMI, do nothing
    if (hdmiAllowed && mHDMIConnected) {
        // If a multi-channel stream goes to standy state, we must switch
        // to stereo stream. If MC comes out of standby, we must switch
        // back to MC. No special processing needed for main stream.
        // AudioStreamOut class handles that correctly
        if (isMCStream) {
            uint32_t mcMask;
            uint32_t mainMask;
            if (isInStandby) {
                mainMask = HDMIAudioOutput::classDevMask();
                mcMask = 0;
            } else {
                mainMask = 0;
                mcMask = HDMIAudioOutput::classDevMask();
            }

            if (NULL != mMainOutput)
                mMainOutput->setTgtDevices(mainMask);

            if (NULL != mMCOutput)
                mMCOutput->setTgtDevices(mcMask);
        }
    }
}

#define DUMP(a...) \
    snprintf(buffer, SIZE, a); \
    buffer[SIZE - 1] = 0; \
    result.append(buffer);
#define B2STR(b) b ? "true" : "false"

status_t AudioHardwareOutput::dump(int fd)
{
    const size_t SIZE = 256;
    char buffer[SIZE];
    String8 result;
    Settings s;

    // Explicit scope for auto-lock pattern.
    {
        // Snapshot the current settings so we don't have to hold the settings
        // lock while formatting the results.
        Mutex::Autolock _l(mSettingsLock);
        s = mSettings;
    }

    DUMP("AudioHardwareOutput::dump\n");
    DUMP("\tMaster Volume          : %0.3f\n", s.masterVolume);
    DUMP("\tMaster Mute            : %s\n", B2STR(s.masterMute));
    DUMP("\tHDMI Output Allowed    : %s\n", B2STR(s.hdmi.allowed));
    DUMP("\tHDMI Delay Comp        : %u uSec\n", s.hdmi.delayCompUsec);
    DUMP("\tHDMI Output Fixed      : %s\n", B2STR(s.hdmi.isFixed));
    DUMP("\tHDMI Fixed Level       : %.1f dB\n", s.hdmi.fixedLvl);
    DUMP("\tVideo Delay Comp       : %u uSec\n", s.videoDelayCompUsec);

    ::write(fd, result.string(), result.size());

    // Explicit scope for auto-lock pattern.
    {
        Mutex::Autolock _l(mOutputLock);
        if (mMainOutput)
            mMainOutput->dump(fd);

        if (mMCOutput)
            mMCOutput->dump(fd);
    }

    return NO_ERROR;
}

#undef B2STR
#undef DUMP

}; // namespace android
