/*
 * Copyright (C) 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 "FastCapture"
//#define LOG_NDEBUG 0

#define ATRACE_TAG ATRACE_TAG_AUDIO

#include "Configuration.h"
#include <linux/futex.h>
#include <sys/syscall.h>
#include <media/AudioBufferProvider.h>
#include <utils/Log.h>
#include <utils/Trace.h>
#include "FastCapture.h"

namespace android {

/*static*/ const FastCaptureState FastCapture::initial;

FastCapture::FastCapture() : FastThread(),
    inputSource(NULL), inputSourceGen(0), pipeSink(NULL), pipeSinkGen(0),
    readBuffer(NULL), readBufferState(-1), format(Format_Invalid), sampleRate(0),
    // dummyDumpState
    totalNativeFramesRead(0)
{
    previous = &initial;
    current = &initial;

    mDummyDumpState = &dummyDumpState;
}

FastCapture::~FastCapture()
{
}

FastCaptureStateQueue* FastCapture::sq()
{
    return &mSQ;
}

const FastThreadState *FastCapture::poll()
{
    return mSQ.poll();
}

void FastCapture::setLog(NBLog::Writer *logWriter __unused)
{
}

void FastCapture::onIdle()
{
    preIdle = *(const FastCaptureState *)current;
    current = &preIdle;
}

void FastCapture::onExit()
{
    delete[] readBuffer;
}

bool FastCapture::isSubClassCommand(FastThreadState::Command command)
{
    switch ((FastCaptureState::Command) command) {
    case FastCaptureState::READ:
    case FastCaptureState::WRITE:
    case FastCaptureState::READ_WRITE:
        return true;
    default:
        return false;
    }
}

void FastCapture::onStateChange()
{
    const FastCaptureState * const current = (const FastCaptureState *) this->current;
    const FastCaptureState * const previous = (const FastCaptureState *) this->previous;
    FastCaptureDumpState * const dumpState = (FastCaptureDumpState *) this->dumpState;
    const size_t frameCount = current->mFrameCount;

    bool eitherChanged = false;

    // check for change in input HAL configuration
    NBAIO_Format previousFormat = format;
    if (current->mInputSourceGen != inputSourceGen) {
        inputSource = current->mInputSource;
        inputSourceGen = current->mInputSourceGen;
        if (inputSource == NULL) {
            format = Format_Invalid;
            sampleRate = 0;
        } else {
            format = inputSource->format();
            sampleRate = Format_sampleRate(format);
            unsigned channelCount = Format_channelCount(format);
            ALOG_ASSERT(channelCount == 1 || channelCount == 2);
        }
        dumpState->mSampleRate = sampleRate;
        eitherChanged = true;
    }

    // check for change in pipe
    if (current->mPipeSinkGen != pipeSinkGen) {
        pipeSink = current->mPipeSink;
        pipeSinkGen = current->mPipeSinkGen;
        eitherChanged = true;
    }

    // input source and pipe sink must be compatible
    if (eitherChanged && inputSource != NULL && pipeSink != NULL) {
        ALOG_ASSERT(Format_isEqual(format, pipeSink->format()));
    }

    if ((!Format_isEqual(format, previousFormat)) || (frameCount != previous->mFrameCount)) {
        // FIXME to avoid priority inversion, don't delete here
        delete[] readBuffer;
        readBuffer = NULL;
        if (frameCount > 0 && sampleRate > 0) {
            // FIXME new may block for unbounded time at internal mutex of the heap
            //       implementation; it would be better to have normal capture thread allocate for
            //       us to avoid blocking here and to prevent possible priority inversion
            unsigned channelCount = Format_channelCount(format);
            // FIXME frameSize
            readBuffer = new short[frameCount * channelCount];
            periodNs = (frameCount * 1000000000LL) / sampleRate;    // 1.00
            underrunNs = (frameCount * 1750000000LL) / sampleRate;  // 1.75
            overrunNs = (frameCount * 500000000LL) / sampleRate;    // 0.50
            forceNs = (frameCount * 950000000LL) / sampleRate;      // 0.95
            warmupNsMin = (frameCount * 750000000LL) / sampleRate;  // 0.75
            warmupNsMax = (frameCount * 1250000000LL) / sampleRate; // 1.25
        } else {
            periodNs = 0;
            underrunNs = 0;
            overrunNs = 0;
            forceNs = 0;
            warmupNsMin = 0;
            warmupNsMax = LONG_MAX;
        }
        readBufferState = -1;
        dumpState->mFrameCount = frameCount;
    }

}

void FastCapture::onWork()
{
    const FastCaptureState * const current = (const FastCaptureState *) this->current;
    FastCaptureDumpState * const dumpState = (FastCaptureDumpState *) this->dumpState;
    const FastCaptureState::Command command = this->command;
    const size_t frameCount = current->mFrameCount;

    if ((command & FastCaptureState::READ) /*&& isWarm*/) {
        ALOG_ASSERT(inputSource != NULL);
        ALOG_ASSERT(readBuffer != NULL);
        dumpState->mReadSequence++;
        ATRACE_BEGIN("read");
        ssize_t framesRead = inputSource->read(readBuffer, frameCount,
                AudioBufferProvider::kInvalidPTS);
        ATRACE_END();
        dumpState->mReadSequence++;
        if (framesRead >= 0) {
            LOG_ALWAYS_FATAL_IF((size_t) framesRead > frameCount);
            totalNativeFramesRead += framesRead;
            dumpState->mFramesRead = totalNativeFramesRead;
            readBufferState = framesRead;
        } else {
            dumpState->mReadErrors++;
            readBufferState = 0;
        }
        // FIXME rename to attemptedIO
        attemptedWrite = true;
    }

    if (command & FastCaptureState::WRITE) {
        ALOG_ASSERT(pipeSink != NULL);
        ALOG_ASSERT(readBuffer != NULL);
        if (readBufferState < 0) {
            unsigned channelCount = Format_channelCount(format);
            // FIXME frameSize
            memset(readBuffer, 0, frameCount * channelCount * sizeof(short));
            readBufferState = frameCount;
        }
        if (readBufferState > 0) {
            ssize_t framesWritten = pipeSink->write(readBuffer, readBufferState);
            // FIXME This supports at most one fast capture client.
            //       To handle multiple clients this could be converted to an array,
            //       or with a lot more work the control block could be shared by all clients.
            audio_track_cblk_t* cblk = current->mCblk;
            if (cblk != NULL && framesWritten > 0) {
                int32_t rear = cblk->u.mStreaming.mRear;
                android_atomic_release_store(framesWritten + rear, &cblk->u.mStreaming.mRear);
                cblk->mServer += framesWritten;
                int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
                if (!(old & CBLK_FUTEX_WAKE)) {
                    // client is never in server process, so don't use FUTEX_WAKE_PRIVATE
                    (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, 1);
                }
            }
        }
    }
}

}   // namespace android
