/*
 * 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 "AudioPolicy"
//#define LOG_NDEBUG 0
#include <utils/Log.h>
#include <media/AudioPolicy.h>

namespace android {

//
//  AudioMixMatchCriterion implementation
//
AudioMixMatchCriterion::AudioMixMatchCriterion(audio_usage_t usage,
                                                 audio_source_t source,
                                                 uint32_t rule)
: mRule(rule)
{
    if (mRule == RULE_MATCH_ATTRIBUTE_USAGE ||
            mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE) {
        mValue.mUsage = usage;
    } else {
        mValue.mSource = source;
    }
}

status_t AudioMixMatchCriterion::readFromParcel(Parcel *parcel)
{
    mRule = parcel->readInt32();
    switch (mRule) {
    case RULE_MATCH_ATTRIBUTE_USAGE:
    case RULE_EXCLUDE_ATTRIBUTE_USAGE:
        mValue.mUsage = (audio_usage_t) parcel->readInt32();
        break;
    case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
    case RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET:
        mValue.mSource = (audio_source_t) parcel->readInt32();
        break;
    case RULE_MATCH_UID:
    case RULE_EXCLUDE_UID:
        mValue.mUid = (uid_t) parcel->readInt32();
        break;
    case RULE_MATCH_USERID:
    case RULE_EXCLUDE_USERID:
        mValue.mUserId = (int) parcel->readInt32();
        break;
    case RULE_MATCH_AUDIO_SESSION_ID:
    case RULE_EXCLUDE_AUDIO_SESSION_ID:
        mValue.mAudioSessionId = (audio_session_t) parcel->readInt32();
        break;
    default:
        ALOGE("Trying to build AudioMixMatchCriterion from unknown rule %d", mRule);
        return BAD_VALUE;
    }
    return NO_ERROR;
}

status_t AudioMixMatchCriterion::writeToParcel(Parcel *parcel) const
{
    parcel->writeInt32(mRule);
    parcel->writeInt32(mValue.mUsage);
    return NO_ERROR;
}

bool AudioMixMatchCriterion::isExcludeCriterion() const {
    return mRule & RULE_EXCLUSION_MASK;
}

//
//  AudioMix implementation
//

status_t AudioMix::readFromParcel(Parcel *parcel)
{
    mMixType = parcel->readInt32();
    mFormat.sample_rate = (uint32_t)parcel->readInt32();
    mFormat.channel_mask = (audio_channel_mask_t)parcel->readInt32();
    mFormat.format = (audio_format_t)parcel->readInt32();
    mRouteFlags = parcel->readInt32();
    mDeviceType = (audio_devices_t) parcel->readInt32();
    mDeviceAddress = parcel->readString8();
    mCbFlags = (uint32_t)parcel->readInt32();
    mAllowPrivilegedMediaPlaybackCapture = parcel->readBool();
    mVoiceCommunicationCaptureAllowed = parcel->readBool();
    size_t size = (size_t)parcel->readInt32();
    if (size > MAX_CRITERIA_PER_MIX) {
        size = MAX_CRITERIA_PER_MIX;
    }
    mCriteria.reserve(size);
    for (size_t i = 0; i < size; i++) {
        AudioMixMatchCriterion criterion;
        if (criterion.readFromParcel(parcel) == NO_ERROR) {
            mCriteria.push_back(criterion);
        }
    }
    return NO_ERROR;
}

status_t AudioMix::writeToParcel(Parcel *parcel) const
{
    parcel->writeInt32(mMixType);
    parcel->writeInt32(mFormat.sample_rate);
    parcel->writeInt32(mFormat.channel_mask);
    parcel->writeInt32(mFormat.format);
    parcel->writeInt32(mRouteFlags);
    parcel->writeInt32(mDeviceType);
    parcel->writeString8(mDeviceAddress);
    parcel->writeInt32(mCbFlags);
    parcel->writeBool(mAllowPrivilegedMediaPlaybackCapture);
    parcel->writeBool(mVoiceCommunicationCaptureAllowed);
    size_t size = mCriteria.size();
    if (size > MAX_CRITERIA_PER_MIX) {
        size = MAX_CRITERIA_PER_MIX;
    }
    size_t sizePosition = parcel->dataPosition();
    parcel->writeInt32(size);
    size_t finalSize = size;
    for (size_t i = 0; i < size; i++) {
        size_t position = parcel->dataPosition();
        if (mCriteria[i].writeToParcel(parcel) != NO_ERROR) {
            parcel->setDataPosition(position);
            finalSize--;
        }
    }
    if (size != finalSize) {
        size_t position = parcel->dataPosition();
        parcel->setDataPosition(sizePosition);
        parcel->writeInt32(finalSize);
        parcel->setDataPosition(position);
    }
    return NO_ERROR;
}

void AudioMix::setExcludeUid(uid_t uid) {
    AudioMixMatchCriterion crit;
    crit.mRule = RULE_EXCLUDE_UID;
    crit.mValue.mUid = uid;
    mCriteria.push_back(crit);
}

void AudioMix::setMatchUid(uid_t uid) {
    AudioMixMatchCriterion crit;
    crit.mRule = RULE_MATCH_UID;
    crit.mValue.mUid = uid;
    mCriteria.push_back(crit);
}

bool AudioMix::hasUidRule(bool match, uid_t uid) const {
    const uint32_t rule = match ? RULE_MATCH_UID : RULE_EXCLUDE_UID;
    for (size_t i = 0; i < mCriteria.size(); i++) {
        if (mCriteria[i].mRule == rule
                && mCriteria[i].mValue.mUid == uid) {
            return true;
        }
    }
    return false;
}

bool AudioMix::hasMatchUidRule() const {
    for (size_t i = 0; i < mCriteria.size(); i++) {
        if (mCriteria[i].mRule == RULE_MATCH_UID) {
            return true;
        }
    }
    return false;
}

void AudioMix::setExcludeUserId(int userId) {
    AudioMixMatchCriterion crit;
    crit.mRule = RULE_EXCLUDE_USERID;
    crit.mValue.mUserId = userId;
    mCriteria.push_back(crit);
}

void AudioMix::setMatchUserId(int userId) {
    AudioMixMatchCriterion crit;
    crit.mRule = RULE_MATCH_USERID;
    crit.mValue.mUserId = userId;
    mCriteria.push_back(crit);
}

bool AudioMix::hasUserIdRule(bool match, int userId) const {
    const uint32_t rule = match ? RULE_MATCH_USERID : RULE_EXCLUDE_USERID;
    for (size_t i = 0; i < mCriteria.size(); i++) {
        if (mCriteria[i].mRule == rule
                && mCriteria[i].mValue.mUserId == userId) {
            return true;
        }
    }
    return false;
}

bool AudioMix::hasUserIdRule(bool match) const {
    const uint32_t rule = match ? RULE_MATCH_USERID : RULE_EXCLUDE_USERID;
    for (size_t i = 0; i < mCriteria.size(); i++) {
        if (mCriteria[i].mRule == rule) {
            return true;
        }
    }
    return false;
}

bool AudioMix::isDeviceAffinityCompatible() const {
    return ((mMixType == MIX_TYPE_PLAYERS)
            && ((mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER));
}

} // namespace android
