/*
 * Copyright (C) 2015 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 "APM::AudioSession"
//#define LOG_NDEBUG 0

#include <AudioPolicyInterface.h>
#include "policy.h"
#include "AudioSession.h"
#include "AudioGain.h"
#include "TypeConverter.h"

#include <log/log.h>
#include <utils/String8.h>

namespace android {

AudioSession::AudioSession(audio_session_t session,
                           audio_source_t inputSource,
                           audio_format_t format,
                           uint32_t sampleRate,
                           audio_channel_mask_t channelMask,
                           audio_input_flags_t flags,
                           uid_t uid,
                           bool isSoundTrigger,
                           AudioMix* policyMix,
                           AudioPolicyClientInterface *clientInterface) :
    mRecordClientInfo({ .uid = uid, .session = session, .source = inputSource}),
    mConfig({ .format = format, .sample_rate = sampleRate, .channel_mask = channelMask}),
    mFlags(flags), mIsSoundTrigger(isSoundTrigger),
    mOpenCount(1), mActiveCount(0), mPolicyMix(policyMix), mClientInterface(clientInterface),
    mInfoProvider(NULL)
{
}

uint32_t AudioSession::changeOpenCount(int delta)
{
    if ((delta + (int)mOpenCount) < 0) {
        ALOGW("%s invalid delta %d, open count %d",
              __FUNCTION__, delta, mOpenCount);
        mOpenCount = (uint32_t)(-delta);
    }
    mOpenCount += delta;
    ALOGV("%s open count %d", __FUNCTION__, mOpenCount);
    return mOpenCount;
}

uint32_t AudioSession::changeActiveCount(int delta)
{
    const uint32_t oldActiveCount = mActiveCount;
    if ((delta + (int)mActiveCount) < 0) {
        ALOGW("%s invalid delta %d, active count %d",
              __FUNCTION__, delta, mActiveCount);
        mActiveCount = (uint32_t)(-delta);
    }
    mActiveCount += delta;
    ALOGV("%s active count %d", __FUNCTION__, mActiveCount);
    int event = RECORD_CONFIG_EVENT_NONE;

    if ((oldActiveCount == 0) && (mActiveCount > 0)) {
        event = RECORD_CONFIG_EVENT_START;
    } else if ((oldActiveCount > 0) && (mActiveCount == 0)) {
        event = RECORD_CONFIG_EVENT_STOP;
    }

    if (event != RECORD_CONFIG_EVENT_NONE) {
        // Dynamic policy callback:
        // if input maps to a dynamic policy with an activity listener, notify of state change
        if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
        {
            mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
                    (event == RECORD_CONFIG_EVENT_START) ? MIX_STATE_MIXING : MIX_STATE_IDLE);
        }

        // Recording configuration callback:
        const AudioSessionInfoProvider* provider = mInfoProvider;
        const audio_config_base_t deviceConfig = (provider != NULL) ? provider->getConfig() :
                AUDIO_CONFIG_BASE_INITIALIZER;
        const audio_patch_handle_t patchHandle = (provider != NULL) ? provider->getPatchHandle() :
                AUDIO_PATCH_HANDLE_NONE;
        if (patchHandle != AUDIO_PATCH_HANDLE_NONE) {
            mClientInterface->onRecordingConfigurationUpdate(event, &mRecordClientInfo,
                    &mConfig, &deviceConfig, patchHandle);
        }
    }

    return mActiveCount;
}

bool AudioSession::matches(const sp<AudioSession> &other) const
{
    if (other->session() == mRecordClientInfo.session &&
        other->inputSource() == mRecordClientInfo.source &&
        other->format() == mConfig.format &&
        other->sampleRate() == mConfig.sample_rate &&
        other->channelMask() == mConfig.channel_mask &&
        other->flags() == mFlags &&
        other->uid() == mRecordClientInfo.uid) {
        return true;
    }
    return false;
}

void AudioSession::setInfoProvider(AudioSessionInfoProvider *provider)
{
    mInfoProvider = provider;
}

void AudioSession::onSessionInfoUpdate() const
{
    if (mActiveCount > 0) {
        // resend the callback after requerying the informations from the info provider
        const AudioSessionInfoProvider* provider = mInfoProvider;
        const audio_config_base_t deviceConfig = (provider != NULL) ? provider->getConfig() :
                AUDIO_CONFIG_BASE_INITIALIZER;
        const audio_patch_handle_t patchHandle = (provider != NULL) ? provider->getPatchHandle() :
                AUDIO_PATCH_HANDLE_NONE;
        if (patchHandle != AUDIO_PATCH_HANDLE_NONE) {
            mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_START,
                    &mRecordClientInfo, &mConfig, &deviceConfig, patchHandle);
        }
    }
}

status_t AudioSession::dump(int fd, int spaces, int index) const
{
    const size_t SIZE = 256;
    char buffer[SIZE];
    String8 result;

    snprintf(buffer, SIZE, "%*sAudio session %d:\n", spaces, "", index+1);
    result.append(buffer);
    snprintf(buffer, SIZE, "%*s- session: %2d\n", spaces, "", mRecordClientInfo.session);
    result.append(buffer);
    snprintf(buffer, SIZE, "%*s- owner uid: %2d\n", spaces, "", mRecordClientInfo.uid);
    result.append(buffer);
    snprintf(buffer, SIZE, "%*s- input source: %d\n", spaces, "", mRecordClientInfo.source);
    result.append(buffer);
    snprintf(buffer, SIZE, "%*s- format: %08x\n", spaces, "", mConfig.format);
    result.append(buffer);
    snprintf(buffer, SIZE, "%*s- sample: %d\n", spaces, "", mConfig.sample_rate);
    result.append(buffer);
    snprintf(buffer, SIZE, "%*s- channel mask: %08x\n",
             spaces, "", mConfig.channel_mask);
    result.append(buffer);
    snprintf(buffer, SIZE, "%*s- is soundtrigger: %s\n",
             spaces, "", mIsSoundTrigger ? "true" : "false");
    result.append(buffer);
    snprintf(buffer, SIZE, "%*s- open count: %d\n", spaces, "", mOpenCount);
    result.append(buffer);
    snprintf(buffer, SIZE, "%*s- active count: %d\n", spaces, "", mActiveCount);
    result.append(buffer);

    write(fd, result.string(), result.size());
    return NO_ERROR;
}

status_t AudioSessionCollection::addSession(audio_session_t session,
                                         const sp<AudioSession>& audioSession,
                                         AudioSessionInfoProvider *provider)
{
    ssize_t index = indexOfKey(session);

    if (index >= 0) {
        ALOGW("addSession() session %d already in", session);
        return ALREADY_EXISTS;
    }
    audioSession->setInfoProvider(provider);
    add(session, audioSession);
    ALOGV("addSession() session %d  client %d source %d",
            session, audioSession->uid(), audioSession->inputSource());
    return NO_ERROR;
}

status_t AudioSessionCollection::removeSession(audio_session_t session)
{
    ssize_t index = indexOfKey(session);

    if (index < 0) {
        ALOGW("removeSession() session %d not in", session);
        return ALREADY_EXISTS;
    }
    ALOGV("removeSession() session %d", session);
    valueAt(index)->setInfoProvider(NULL);
    removeItemsAt(index);
    return NO_ERROR;
}

uint32_t AudioSessionCollection::getOpenCount() const
{
    uint32_t openCount = 0;
    for (size_t i = 0; i < size(); i++) {
        openCount += valueAt(i)->openCount();
    }
    return openCount;
}

AudioSessionCollection AudioSessionCollection::getActiveSessions() const
{
    AudioSessionCollection activeSessions;
    for (size_t i = 0; i < size(); i++) {
        if (valueAt(i)->activeCount() != 0) {
            activeSessions.add(valueAt(i)->session(), valueAt(i));
        }
    }
    return activeSessions;
}

size_t AudioSessionCollection::getActiveSessionCount() const
{
    size_t activeCount = 0;
    for (size_t i = 0; i < size(); i++) {
        if (valueAt(i)->activeCount() != 0) {
            activeCount++;
        }
    }
    return activeCount;
}

bool AudioSessionCollection::hasActiveSession() const
{
    return getActiveSessionCount() != 0;
}

bool AudioSessionCollection::isSourceActive(audio_source_t source) const
{
    for (size_t i = 0; i < size(); i++) {
        const sp<AudioSession>  audioSession = valueAt(i);
        // AUDIO_SOURCE_HOTWORD is equivalent to AUDIO_SOURCE_VOICE_RECOGNITION only if it
        // corresponds to an active capture triggered by a hardware hotword recognition
        if (audioSession->activeCount() > 0 &&
                ((audioSession->inputSource() == source) ||
                ((source == AUDIO_SOURCE_VOICE_RECOGNITION) &&
                 (audioSession->inputSource() == AUDIO_SOURCE_HOTWORD) &&
                 audioSession->isSoundTrigger()))) {
            return true;
        }
    }
    return false;
}

audio_source_t AudioSessionCollection::getHighestPrioritySource(bool activeOnly) const
{
    audio_source_t source = AUDIO_SOURCE_DEFAULT;
    int32_t priority = -1;

    for (size_t i = 0; i < size(); i++) {
        const sp<AudioSession>  audioSession = valueAt(i);
        if (activeOnly && audioSession->activeCount() == 0) {
            continue;
        }
        int32_t curPriority = source_priority(audioSession->inputSource());
        if (curPriority > priority) {
            priority = curPriority;
            source = audioSession->inputSource();
        }
    }
    return source;
}

void AudioSessionCollection::onSessionInfoUpdate() const
{
    for (size_t i = 0; i < size(); i++) {
        valueAt(i)->onSessionInfoUpdate();
    }
}

status_t AudioSessionCollection::dump(int fd, int spaces) const
{
    const size_t SIZE = 256;
    char buffer[SIZE];
    snprintf(buffer, SIZE, "%*sAudio Sessions:\n", spaces, "");
    write(fd, buffer, strlen(buffer));
    for (size_t i = 0; i < size(); i++) {
        valueAt(i)->dump(fd, spaces + 2, i);
    }
    return NO_ERROR;
}

}; // namespace android
