/*
**
** Copyright 2012, 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:AudioStreamIn"
#include <utils/Log.h>

#include "AudioStreamIn.h"
#include "AudioHardwareInput.h"

#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <utils/String8.h>
#include <media/AudioParameter.h>

// for turning Remote mic on/off
#ifdef REMOTE_CONTROL_INTERFACE
#include <IRemoteControlService.h>
#endif

namespace android {

const audio_format_t AudioStreamIn::kAudioFormat = AUDIO_FORMAT_PCM_16_BIT;
const uint32_t AudioStreamIn::kChannelMask = AUDIO_CHANNEL_IN_MONO;

// number of periods in the ALSA buffer
const int AudioStreamIn::kPeriodCount = 4;

AudioStreamIn::AudioStreamIn(AudioHardwareInput& owner)
    : mOwnerHAL(owner)
    , mCurrentDeviceInfo(NULL)
    , mRequestedSampleRate(0)
    , mStandby(true)
    , mDisabled(false)
    , mPcm(NULL)
    , mResampler(NULL)
    , mBuffer(NULL)
    , mBufferSize(0)
    , mInputSource(AUDIO_SOURCE_DEFAULT)
    , mReadStatus(0)
    , mFramesIn(0)
{
    struct resampler_buffer_provider& provider =
            mResamplerProviderWrapper.provider;
    provider.get_next_buffer = getNextBufferThunk;
    provider.release_buffer = releaseBufferThunk;
    mResamplerProviderWrapper.thiz = this;
}

AudioStreamIn::~AudioStreamIn()
{
    Mutex::Autolock _l(mLock);
    standby_l();
}

// Perform stream initialization that may fail.
// Must only be called once at construction time.
status_t AudioStreamIn::set(audio_format_t *pFormat, uint32_t *pChannelMask,
                            uint32_t *pRate)
{
    Mutex::Autolock _l(mLock);

    assert(mRequestedSampleRate == 0);

    // Respond with a request for mono if a different format is given.
    if (*pChannelMask != kChannelMask) {
        *pChannelMask = kChannelMask;
        return BAD_VALUE;
    }

    if (*pFormat != kAudioFormat) {
        *pFormat = kAudioFormat;
        return BAD_VALUE;
    }

    mRequestedSampleRate = *pRate;

    return NO_ERROR;
}

uint32_t AudioStreamIn::getSampleRate()
{
    Mutex::Autolock _l(mLock);
    return mRequestedSampleRate;
}

status_t AudioStreamIn::setSampleRate(uint32_t rate)
{
    (void) rate;
    // this is a no-op in other audio HALs
    return NO_ERROR;
}

size_t AudioStreamIn::getBufferSize()
{
    Mutex::Autolock _l(mLock);

    size_t size = AudioHardwareInput::calculateInputBufferSize(
        mRequestedSampleRate, kAudioFormat, getChannelCount());
    return size;
}

uint32_t AudioStreamIn::getChannelMask()
{
    return kChannelMask;
}

audio_format_t AudioStreamIn::getFormat()
{
    return kAudioFormat;
}

status_t AudioStreamIn::setFormat(audio_format_t format)
{
    (void) format;
    // other audio HALs fail any call to this API (even if the format matches
    // the current format)
    return INVALID_OPERATION;
}

status_t AudioStreamIn::standby()
{
    Mutex::Autolock _l(mLock);
    return standby_l();
}

status_t AudioStreamIn::standby_l()
{
    if (mStandby) {
        return NO_ERROR;
    }
    if (mPcm) {
        ALOGD("AudioStreamIn::standby_l, call pcm_close()");
        pcm_close(mPcm);
        mPcm = NULL;
    }

    // Turn OFF Remote MIC if we were recording from Remote.
    if (mCurrentDeviceInfo != NULL) {
        if (mCurrentDeviceInfo->forVoiceRecognition) {
            setRemoteControlMicEnabled(false);
        }
    }

    if (mResampler) {
        release_resampler(mResampler);
        mResampler = NULL;
    }
    if (mBuffer) {
        delete [] mBuffer;
        mBuffer = NULL;
    }

    mCurrentDeviceInfo = NULL;
    mStandby = true;
    mDisabled = false;

    return NO_ERROR;
}

#define DUMP(a...) \
    snprintf(buffer, SIZE, a); \
    buffer[SIZE - 1] = 0; \
    result.append(buffer);

status_t AudioStreamIn::dump(int fd)
{
    const size_t SIZE = 256;
    char buffer[SIZE];
    String8 result;
    DUMP("\n AudioStreamIn::dump\n");

    {
        DUMP("\toutput sample rate: %d\n", mRequestedSampleRate);
        if (mPcm) {
            DUMP("\tinput sample rate: %d\n", mPcmConfig.rate);
            DUMP("\tinput channels: %d\n", mPcmConfig.channels);
        }
    }

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

    return NO_ERROR;
}

status_t AudioStreamIn::setParameters(struct audio_stream* stream,
                                      const char* kvpairs)
{
    (void) stream;
    AudioParameter param = AudioParameter(String8(kvpairs));
    status_t status = NO_ERROR;
    String8 keySource = String8(AudioParameter::keyInputSource);
    int intVal;

    if (param.getInt(keySource, intVal) == NO_ERROR) {
        ALOGI("AudioStreamIn::setParameters, mInputSource set to %d", intVal);
        mInputSource = intVal;
    }

    return status;
}

char* AudioStreamIn::getParameters(const char* keys)
{
    (void) keys;
    return strdup("");
}

status_t AudioStreamIn::setGain(float gain)
{
    (void) gain;
    // In other HALs, this is a no-op and returns success.
    return NO_ERROR;
}

uint32_t AudioStreamIn::getInputFramesLost()
{
    return 0;
}

status_t AudioStreamIn::addAudioEffect(effect_handle_t effect)
{
    (void) effect;
    // In other HALs, this is a no-op and returns success.
    return 0;
}

status_t AudioStreamIn::removeAudioEffect(effect_handle_t effect)
{
    (void) effect;
    // In other HALs, this is a no-op and returns success.
    return 0;
}

ssize_t AudioStreamIn::read(void* buffer, size_t bytes)
{
    Mutex::Autolock _l(mLock);

    status_t status = NO_ERROR;

    if (mStandby) {
        status = startInputStream_l();
        // Only try to start once to prevent pointless spew.
        // If mic is not available then read will return silence.
        // This is needed to prevent apps from hanging.
        mStandby = false;
        if (status != NO_ERROR) {
            mDisabled = true;
        }
    }

    if ((status == NO_ERROR) && !mDisabled) {
        int ret = readFrames_l(buffer, bytes / getFrameSize());
        status = (ret < 0) ? INVALID_OPERATION : NO_ERROR;
    }

    if ((status != NO_ERROR) || mDisabled) {
        memset(buffer, 0, bytes);

        // TODO: This code needs to project a timeline based on the number
        // of audio frames synthesized from the last time we returned data
        // from an actual audio device (or establish a fake timeline to obey
        // if we have never returned any data from an actual device and need
        // to synth on the first call to read)
        usleep(bytes * 1000000 / getFrameSize() / mRequestedSampleRate);
    } else {
        bool mute;
        mOwnerHAL.getMicMute(&mute);
        if (mute) {
            memset(buffer, 0, bytes);
        }
    }

    return bytes;
}

void AudioStreamIn::setRemoteControlMicEnabled(bool flag)
{
#ifdef REMOTE_CONTROL_INTERFACE
    sp<IRemoteControlService> service = IRemoteControlService::getInstance();
    if (service == NULL) {
        ALOGE("%s: No RemoteControl service detected, ignoring\n", __func__);
        return;
    }
    service->setMicEnabled(flag);
#else
    (void)flag;
#endif
}

status_t AudioStreamIn::startInputStream_l()
{

    ALOGI("AudioStreamIn::startInputStream_l, entry");

    // Get the most appropriate device for the given input source, eg VOICE_RECOGNITION
    const AudioHotplugThread::DeviceInfo *deviceInfo = mOwnerHAL.getBestDevice(mInputSource);
    if (deviceInfo == NULL) {
        return INVALID_OPERATION;
    }

    memset(&mPcmConfig, 0, sizeof(mPcmConfig));

    unsigned int requestedChannelCount = getChannelCount();

    // Clip to min/max available.
    if (requestedChannelCount < deviceInfo->minChannelCount ) {
        mPcmConfig.channels = deviceInfo->minChannelCount;
    } else if (requestedChannelCount > deviceInfo->maxChannelCount ) {
        mPcmConfig.channels = deviceInfo->maxChannelCount;
    } else {
        mPcmConfig.channels = requestedChannelCount;
    }

    ALOGD("AudioStreamIn::startInputStream_l, mRequestedSampleRate = %d",
        mRequestedSampleRate);

    // Clip to min/max available from driver.
    uint32_t chosenSampleRate = mRequestedSampleRate;
    if (chosenSampleRate < deviceInfo->minSampleRate) {
        chosenSampleRate = deviceInfo->minSampleRate;
    } else if (chosenSampleRate > deviceInfo->maxSampleRate) {
        chosenSampleRate = deviceInfo->maxSampleRate;
    }

    // Turn on RemoteControl MIC if we are recording from it.
    if (deviceInfo->forVoiceRecognition) {
        setRemoteControlMicEnabled(true);
    }

    mPcmConfig.rate = chosenSampleRate;

    mPcmConfig.period_size =
            AudioHardwareInput::kPeriodMsec * mPcmConfig.rate / 1000;
    mPcmConfig.period_count = kPeriodCount;
    mPcmConfig.format = PCM_FORMAT_S16_LE;

    ALOGD("AudioStreamIn::startInputStream_l, call pcm_open()");
    struct pcm* pcm = pcm_open(deviceInfo->pcmCard, deviceInfo->pcmDevice,
                               PCM_IN, &mPcmConfig);

    if (!pcm_is_ready(pcm)) {
        ALOGE("ERROR AudioStreamIn::startInputStream_l, pcm_open failed");
        pcm_close(pcm);
        if (deviceInfo->forVoiceRecognition) {
            setRemoteControlMicEnabled(false);
        }
        return NO_MEMORY;
    }

    mCurrentDeviceInfo = deviceInfo;

    mBufferSize = pcm_frames_to_bytes(pcm, mPcmConfig.period_size);
    if (mBuffer) {
        delete [] mBuffer;
    }
    mBuffer = new int16_t[mBufferSize / sizeof(uint16_t)];

    if (mResampler) {
        release_resampler(mResampler);
        mResampler = NULL;
    }
    if (mPcmConfig.rate != mRequestedSampleRate) {
        ALOGD("AudioStreamIn::startInputStream_l, call create_resampler( %d  to %d)",
            mPcmConfig.rate, mRequestedSampleRate);
        int ret = create_resampler(mPcmConfig.rate,
                                   mRequestedSampleRate,
                                   1,
                                   RESAMPLER_QUALITY_DEFAULT,
                                   &mResamplerProviderWrapper.provider,
                                   &mResampler);
        if (ret != 0) {
            ALOGW("AudioStreamIn: unable to create resampler");
            pcm_close(pcm);
            return static_cast<status_t>(ret);
        }
    }

    mPcm = pcm;

    return NO_ERROR;
}

// readFrames() reads frames from kernel driver, down samples to the capture
// rate if necessary and outputs the number of frames requested to the buffer
// specified
ssize_t AudioStreamIn::readFrames_l(void* buffer, ssize_t frames)
{
    ssize_t framesWr = 0;
    size_t frameSize = getFrameSize();

    while (framesWr < frames) {
        size_t framesRd = frames - framesWr;
        if (mResampler) {
            char* outFrame = static_cast<char*>(buffer) +
                    (framesWr * frameSize);
            mResampler->resample_from_provider(
                mResampler,
                reinterpret_cast<int16_t*>(outFrame),
                &framesRd);
        } else {
            struct resampler_buffer buf;
            buf.raw = NULL;
            buf.frame_count = framesRd;

            getNextBuffer(&buf);
            if (buf.raw != NULL) {
                memcpy(static_cast<char*>(buffer) + (framesWr * frameSize),
                       buf.raw,
                       buf.frame_count * frameSize);
                framesRd = buf.frame_count;
            }
            releaseBuffer(&buf);
        }
        // mReadStatus is updated by getNextBuffer(), which is called by the
        // resampler
        if (mReadStatus != 0)
            return mReadStatus;

        framesWr += framesRd;
    }
    return framesWr;
}

int AudioStreamIn::getNextBufferThunk(
        struct resampler_buffer_provider* bufferProvider,
        struct resampler_buffer* buffer)
{
    ResamplerBufferProviderWrapper* wrapper =
            reinterpret_cast<ResamplerBufferProviderWrapper*>(
                reinterpret_cast<char*>(bufferProvider) -
                offsetof(ResamplerBufferProviderWrapper, provider));

    return wrapper->thiz->getNextBuffer(buffer);
}

void AudioStreamIn::releaseBufferThunk(
        struct resampler_buffer_provider* bufferProvider,
        struct resampler_buffer* buffer)
{
    ResamplerBufferProviderWrapper* wrapper =
            reinterpret_cast<ResamplerBufferProviderWrapper*>(
                reinterpret_cast<char*>(bufferProvider) -
                offsetof(ResamplerBufferProviderWrapper, provider));

    wrapper->thiz->releaseBuffer(buffer);
}

// called while holding mLock
int AudioStreamIn::getNextBuffer(struct resampler_buffer* buffer)
{
    if (buffer == NULL) {
        return -EINVAL;
    }

    if (mPcm == NULL) {
        buffer->raw = NULL;
        buffer->frame_count = 0;
        mReadStatus = -ENODEV;
        return -ENODEV;
    }

    if (mFramesIn == 0) {
        mReadStatus = pcm_read(mPcm, mBuffer, mBufferSize);
        if (mReadStatus) {
            ALOGE("get_next_buffer() pcm_read error %d", mReadStatus);
            buffer->raw = NULL;
            buffer->frame_count = 0;
            return mReadStatus;
        }

        mFramesIn = mPcmConfig.period_size;
        if (mPcmConfig.channels == 2) {
            // Discard the right channel.
            // TODO: this is what other HALs are doing to handle stereo input
            // devices.  Need to verify if this is appropriate for ATV Remote.
            for (unsigned int i = 1; i < mFramesIn; i++) {
                mBuffer[i] = mBuffer[i * 2];
            }
        }
    }

    buffer->frame_count = (buffer->frame_count > mFramesIn) ?
            mFramesIn : buffer->frame_count;
    buffer->i16 = mBuffer + (mPcmConfig.period_size - mFramesIn);

    return mReadStatus;
}

// called while holding mLock
void AudioStreamIn::releaseBuffer(struct resampler_buffer* buffer)
{
    if (buffer == NULL) {
        return;
    }

    mFramesIn -= buffer->frame_count;
}

}; // namespace android
