Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2dda40d6 authored by Eric Laurent's avatar Eric Laurent Committed by Android (Google) Code Review
Browse files

Merge "audio policy: add support for custom mixes" into lmp-mr1-dev

parents 9cea7aa4 275e8e9d
Loading
Loading
Loading
Loading
+82 −0
Original line number Diff line number Diff line
/*
 * 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.
 */


#ifndef ANDROID_AUDIO_POLICY_H
#define ANDROID_AUDIO_POLICY_H

#include <system/audio.h>
#include <system/audio_policy.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <utils/Vector.h>

namespace android {

// Keep in sync with AudioMix.java, AudioMixingRule.java, AudioPolicyConfig.java
#define RULE_EXCLUSION_MASK 0x8000
#define RULE_MATCH_ATTRIBUTE_USAGE 0x1
#define RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET (0x1 << 1)
#define RULE_EXCLUDE_ATTRIBUTE_USAGE (RULE_EXCLUSION_MASK|RULE_MATCH_ATTRIBUTE_USAGE)
#define RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET \
    (RULE_EXCLUSION_MASK|RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET)

#define MIX_TYPE_INVALID -1
#define MIX_TYPE_PLAYERS 0
#define MIX_TYPE_RECORDERS 1

#define ROUTE_FLAG_RENDER 0x1
#define ROUTE_FLAG_LOOP_BACK (0x1 << 1)

#define MAX_MIXES_PER_POLICY 10
#define MAX_CRITERIA_PER_MIX 20

class AttributeMatchCriterion {
public:
    AttributeMatchCriterion() {}
    AttributeMatchCriterion(audio_usage_t usage, audio_source_t source, uint32_t rule);

    status_t readFromParcel(Parcel *parcel);
    status_t writeToParcel(Parcel *parcel) const;

    union {
        audio_usage_t   mUsage;
        audio_source_t  mSource;
    } mAttr;
    uint32_t        mRule;
};

class AudioMix {
public:
    AudioMix() {}
    AudioMix(Vector<AttributeMatchCriterion> criteria, uint32_t mixType, audio_config_t format,
             uint32_t routeFlags, String8 registrationId) :
        mCriteria(criteria), mMixType(mixType), mFormat(format),
        mRouteFlags(routeFlags), mRegistrationId(registrationId) {}

    status_t readFromParcel(Parcel *parcel);
    status_t writeToParcel(Parcel *parcel) const;

    Vector<AttributeMatchCriterion> mCriteria;
    uint32_t        mMixType;
    audio_config_t  mFormat;
    uint32_t        mRouteFlags;
    String8         mRegistrationId;
};

}; // namespace android

#endif  // ANDROID_AUDIO_POLICY_H
+1 −1
Original line number Diff line number Diff line
@@ -63,7 +63,7 @@ static audio_stream_type_t audio_attributes_to_stream_type(const audio_attribute

static void stream_type_to_audio_attributes(audio_stream_type_t streamType,
                                     audio_attributes_t *attr) {
    attr->flags = 0x0;
    memset(attr, 0, sizeof(audio_attributes_t));

    switch (streamType) {
    case AUDIO_STREAM_DEFAULT:
+2 −1
Original line number Diff line number Diff line
@@ -59,7 +59,8 @@ LOCAL_SRC_FILES:= \
    MemoryLeakTrackUtil.cpp \
    SoundPool.cpp \
    SoundPoolThread.cpp \
    StringArray.cpp
    StringArray.cpp \
    AudioPolicy.cpp

LOCAL_SRC_FILES += ../libnbaio/roundup.c

+115 −0
Original line number Diff line number Diff line
/*
 * 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 {

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

status_t AttributeMatchCriterion::readFromParcel(Parcel *parcel)
{
    mRule = parcel->readInt32();
    if (mRule == RULE_MATCH_ATTRIBUTE_USAGE ||
            mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE) {
        mAttr.mUsage = (audio_usage_t)parcel->readInt32();
    } else {
        mAttr.mSource = (audio_source_t)parcel->readInt32();
    }
    return NO_ERROR;
}

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

//
//  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();
    mRegistrationId = parcel->readString8();
    size_t size = (size_t)parcel->readInt32();
    if (size > MAX_CRITERIA_PER_MIX) {
        size = MAX_CRITERIA_PER_MIX;
    }
    for (size_t i = 0; i < size; i++) {
        AttributeMatchCriterion criterion;
        if (criterion.readFromParcel(parcel) == NO_ERROR) {
            mCriteria.add(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->writeString8(mRegistrationId);
    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;
}

}; // namespace android
+8 −0
Original line number Diff line number Diff line
@@ -851,6 +851,10 @@ status_t AudioTrack::getPosition(uint32_t *position)
        // due to hardware latency. We leave this behavior for now.
        *position = dspFrames;
    } else {
        if (mCblk->mFlags & CBLK_INVALID) {
            restoreTrack_l("getPosition");
        }

        // IAudioTrack::stop() isn't synchronous; we don't know when presentation completes
        *position = (mState == STATE_STOPPED || mState == STATE_FLUSHED) ?
                0 : updateAndGetPosition_l();
@@ -1946,6 +1950,10 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp)
        break;
    }

    if (mCblk->mFlags & CBLK_INVALID) {
        restoreTrack_l("getTimestamp");
    }

    // The presented frame count must always lag behind the consumed frame count.
    // To avoid a race, read the presented frames first.  This ensures that presented <= consumed.
    status_t status = mAudioTrack->getTimestamp(timestamp);
Loading