audiopolicy: engine: Add Volume Groups to common Engine

This CL adds the concept of Volume Group to the engine.
It generalizes the volume management today controled by stream types
and hard coded into AOSP.
The goal is to control the volume per attributes, being able to define
a group of attributes that follow the same volume curves.

It intends to replace the concept of aliases in AudioService.

Bug: 124767636
Test: build

Change-Id: Icd079374cc1680d074b01836eca0bceb0b0c5247
Signed-off-by: François Gaffie <francois.gaffie@renault.com>
gugelfrei
François Gaffie 6 years ago committed by Eric Laurent
parent a666d61efb
commit 251c7f0a9d

@ -43,7 +43,7 @@ status_t AudioAttributes::readFromParcel(const Parcel *parcel)
strcpy(mAttributes.tags, "");
}
mStreamType = static_cast<audio_stream_type_t>(parcel->readInt32());
mGroupId = parcel->readUint32();
mGroupId = static_cast<volume_group_t>(parcel->readUint32());
return NO_ERROR;
}
@ -60,7 +60,7 @@ status_t AudioAttributes::writeToParcel(Parcel *parcel) const
parcel->writeUtf8AsUtf16(mAttributes.tags);
}
parcel->writeInt32(static_cast<int32_t>(mStreamType));
parcel->writeUint32(mGroupId);
parcel->writeUint32(static_cast<uint32_t>(mGroupId));
return NO_ERROR;
}

@ -17,6 +17,7 @@
#pragma once
#include <media/AudioCommonTypes.h>
#include <system/audio.h>
#include <system/audio_policy.h>
#include <binder/Parcelable.h>
@ -28,7 +29,7 @@ class AudioAttributes : public Parcelable
public:
AudioAttributes() = default;
AudioAttributes(const audio_attributes_t &attributes) : mAttributes(attributes) {}
AudioAttributes(uint32_t groupId,
AudioAttributes(volume_group_t groupId,
audio_stream_type_t stream,
const audio_attributes_t &attributes) :
mAttributes(attributes), mStreamType(stream), mGroupId(groupId) {}
@ -39,7 +40,7 @@ public:
status_t writeToParcel(Parcel *parcel) const override;
audio_stream_type_t getStreamType() const { return mStreamType; }
uint32_t getGroupId() const { return mGroupId; }
volume_group_t getGroupId() const { return mGroupId; }
private:
audio_attributes_t mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
@ -53,7 +54,7 @@ private:
* @brief mGroupId: for future volume management, define groups within a strategy that follows
* the same curves of volume (extension of stream types to manage volume)
*/
uint32_t mGroupId = 0;
volume_group_t mGroupId = VOLUME_GROUP_NONE;
};
} // namespace android

@ -27,7 +27,7 @@ enum product_strategy_t : uint32_t;
const product_strategy_t PRODUCT_STRATEGY_NONE = static_cast<product_strategy_t>(-1);
using AttributesVector = std::vector<audio_attributes_t>;
using StreamTypes = std::vector<audio_stream_type_t>;
using StreamTypeVector = std::vector<audio_stream_type_t>;
constexpr bool operator==(const audio_attributes_t &lhs, const audio_attributes_t &rhs)
{
@ -38,5 +38,9 @@ constexpr bool operator!=(const audio_attributes_t &lhs, const audio_attributes_
{
return !(lhs==rhs);
}
enum volume_group_t : uint32_t;
static const volume_group_t VOLUME_GROUP_NONE = static_cast<volume_group_t>(-1);
} // namespace android

@ -21,6 +21,7 @@
#include <math.h>
namespace android {
/**
* VolumeSource is the discriminent for volume management on an output.
* It used to be the stream type by legacy, it may be host volume group or a volume curves if

@ -38,6 +38,8 @@ public:
virtual float volIndexToDb(device_category device, int indexInUi) const = 0;
virtual bool hasVolumeIndexForDevice(audio_devices_t device) const = 0;
virtual status_t initVolume(int indexMin, int indexMax) = 0;
virtual std::vector<audio_attributes_t> getAttributes() const = 0;
virtual std::vector<audio_stream_type_t> getStreamTypes() const = 0;
virtual void dump(String8 *dst, int spaces = 0, bool curvePoints = false) const = 0;
};

@ -341,7 +341,7 @@ sp<DeviceDescriptor> HwModuleCollection::getDeviceDescriptor(const audio_devices
}
}
if (!allowToCreate) {
ALOGE("%s: could not find HW module for device %s %04x address %s", __FUNCTION__,
ALOGV("%s: could not find HW module for device %s %04x address %s", __FUNCTION__,
name, deviceType, address);
return nullptr;
}

@ -19,7 +19,7 @@
#include <EngineConfig.h>
#include <AudioPolicyManagerInterface.h>
#include <ProductStrategy.h>
#include <StreamVolumeCurves.h>
#include <VolumeGroup.h>
namespace android {
namespace audio_policy {
@ -68,9 +68,25 @@ public:
status_t listAudioProductStrategies(AudioProductStrategyVector &strategies) const override;
VolumeCurves *getVolumeCurvesForAttributes(const audio_attributes_t &attr) override;
VolumeCurves *getVolumeCurvesForAttributes(const audio_attributes_t &attr) const override;
VolumeCurves *getVolumeCurvesForStreamType(audio_stream_type_t stream) override;
VolumeCurves *getVolumeCurvesForStreamType(audio_stream_type_t stream) const override;
IVolumeCurves *getVolumeCurvesForVolumeGroup(volume_group_t group) const override
{
return mVolumeGroups.find(group) != end(mVolumeGroups) ?
mVolumeGroups.at(group)->getVolumeCurves() : nullptr;
}
VolumeGroupVector getVolumeGroups() const override;
volume_group_t getVolumeGroupForAttributes(const audio_attributes_t &attr) const override;
volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const override;
StreamTypeVector getStreamTypesForVolumeGroup(volume_group_t volumeGroup) const override;
AttributesVector getAllAttributesForVolumeGroup(volume_group_t volumeGroup) const override;
void dump(String8 *dst) const override;
@ -105,12 +121,11 @@ public:
AudioPolicyManagerObserver *mApmObserver = nullptr;
ProductStrategyMap mProductStrategies;
VolumeGroupMap mVolumeGroups;
audio_mode_t mPhoneState = AUDIO_MODE_NORMAL; /**< current phone state. */
/** current forced use configuration. */
audio_policy_forced_cfg_t mForceUse[AUDIO_POLICY_FORCE_USE_CNT] = {};
StreamVolumeCurves mStreamVolumeCurves;
};
} // namespace audio_policy

@ -16,6 +16,8 @@
#pragma once
#include "VolumeGroup.h"
#include <system/audio.h>
#include <AudioPolicyManagerInterface.h>
#include <utils/RefBase.h>
@ -38,7 +40,7 @@ class ProductStrategy : public virtual RefBase, private HandleGenerator<uint32_t
private:
struct AudioAttributes {
audio_stream_type_t mStream = AUDIO_STREAM_DEFAULT;
uint32_t mGroupId = 0;
volume_group_t mVolumeGroup = VOLUME_GROUP_NONE;
audio_attributes_t mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
};
@ -85,6 +87,12 @@ public:
audio_attributes_t getAttributesForStreamType(audio_stream_type_t stream) const;
audio_stream_type_t getStreamTypeForAttributes(const audio_attributes_t &attr) const;
volume_group_t getVolumeGroupForAttributes(const audio_attributes_t &attr) const;
volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const;
volume_group_t getDefaultVolumeGroup() const;
bool isDefault() const;
void dump(String8 *dst, int spaces = 0) const;
@ -107,6 +115,10 @@ private:
class ProductStrategyMap : public std::map<product_strategy_t, sp<ProductStrategy> >
{
public:
/**
* @brief initialize: set default product strategy in cache.
*/
void initialize();
/**
* @brief getProductStrategyForAttribute. The order of the vector is dimensionning.
* @param attr
@ -136,9 +148,16 @@ public:
std::string getDeviceAddressForProductStrategy(product_strategy_t strategy) const;
volume_group_t getVolumeGroupForAttributes(const audio_attributes_t &attr) const;
volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const;
product_strategy_t getDefault() const;
void dump(String8 *dst, int spaces = 0) const;
private:
product_strategy_t mDefaultStrategy = PRODUCT_STRATEGY_NONE;
};
} // namespace android

@ -1,95 +0,0 @@
/*
* Copyright (C) 2018 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.
*/
#pragma once
#include <VolumeCurve.h>
#include <map>
namespace android {
class StreamVolumeCurves
{
public:
StreamVolumeCurves() = default;
/**
* @brief switchVolumeCurve control API for Engine, allows to switch the volume curves
* from one stream type to another.
* @param src source stream type
* @param dst destination stream type
*/
status_t switchVolumeCurve(audio_stream_type_t streamSrc, audio_stream_type_t streamDst)
{
if (!hasCurvesFor(streamSrc) || !hasCurvesFor(streamDst)) {
ALOGE("%s: No curves defined for streams %d %d", __FUNCTION__, streamSrc, streamDst);
return NO_INIT;
}
const VolumeCurves &sourceCurves = getCurvesFor(streamSrc);
VolumeCurves &dstCurves = editCurvesFor(streamDst);
return dstCurves.switchCurvesFrom(sourceCurves);
}
void dump(String8 *dst, int spaces = 0) const;
void add(const VolumeCurves &curves, audio_stream_type_t streamType)
{
mCurves.emplace(streamType, curves);
}
bool hasCurvesFor(audio_stream_type_t stream)
{
return mCurves.find(stream) != end(mCurves);
}
VolumeCurves &editCurvesFor(audio_stream_type_t stream)
{
ALOG_ASSERT(mCurves.find(stream) != end(mCurves), "Invalid stream type for Volume Curve");
return mCurves[stream];
}
const VolumeCurves &getCurvesFor(audio_stream_type_t stream) const
{
ALOG_ASSERT(mCurves.find(stream) != end(mCurves), "Invalid stream type for Volume Curve");
return mCurves.at(stream);
}
/**
* @brief getVolumeCurvesForStream
* @param stream type for which the volume curves interface is requested
* @return the VolumeCurves for a given stream type.
*/
VolumeCurves &getVolumeCurvesForStream(audio_stream_type_t stream)
{
ALOG_ASSERT(mCurves.find(stream) != end(mCurves), "Invalid stream type for Volume Curve");
return mCurves[stream];
}
/**
* @brief restoreOriginVolumeCurve helper control API for engine to restore the original volume
* curves for a given stream type
* @param stream for which the volume curves will be restored.
*/
status_t restoreOriginVolumeCurve(audio_stream_type_t stream)
{
if (!hasCurvesFor(stream)) {
ALOGE("%s: No curves defined for streams", __FUNCTION__);
return NO_INIT;
}
return switchVolumeCurve(stream, stream);
}
private:
std::map<audio_stream_type_t, VolumeCurves> mCurves;
};
} // namespace android

@ -18,7 +18,9 @@
#include "IVolumeCurves.h"
#include <policy.h>
#include <AudioPolicyManagerInterface.h>
#include <utils/RefBase.h>
#include <HandleGenerator.h>
#include <utils/String8.h>
#include <utils/SortedVector.h>
#include <utils/KeyedVector.h>
@ -71,18 +73,11 @@ class VolumeCurves : public KeyedVector<device_category, sp<VolumeCurve> >,
{
public:
VolumeCurves(int indexMin = 0, int indexMax = 100) :
mIndexMin(indexMin), mIndexMax(indexMax), mStream(AUDIO_STREAM_DEFAULT)
mIndexMin(indexMin), mIndexMax(indexMax)
{
addCurrentVolumeIndex(AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, 0);
}
VolumeCurves(audio_stream_type_t stream, int indexMin, int indexMax) :
mIndexMin(indexMin), mIndexMax(indexMax), mStream(stream)
{
addCurrentVolumeIndex(AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, 0);
}
// Once XML has been parsed, must be call first to sanity check table and initialize indexes
virtual status_t initVolume(int indexMin, int indexMax)
status_t initVolume(int indexMin, int indexMax) override
{
mIndexMin = indexMin;
mIndexMax = indexMax;
@ -174,8 +169,16 @@ public:
return 0.0f;
}
}
audio_stream_type_t getStreamType() const { return mStream; }
void addAttributes(const audio_attributes_t &attr)
{
mAttributes.push_back(attr);
}
AttributesVector getAttributes() const override { return mAttributes; }
void addStreamType(audio_stream_type_t stream)
{
mStreams.push_back(stream);
}
StreamTypeVector getStreamTypes() const override { return mStreams; }
void dump(String8 *dst, int spaces = 0, bool curvePoints = false) const override;
@ -186,7 +189,8 @@ private:
int mIndexMax; /**< max volume index. */
const bool mCanBeMuted = true; /**< true is the stream can be muted. */
const audio_stream_type_t mStream; /**< Keep it for legacy. */
AttributesVector mAttributes;
StreamTypeVector mStreams; /**< Keep it for legacy. */
};
} // namespace android

@ -0,0 +1,62 @@
/*
* Copyright (C) 2018 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.
*/
#pragma once
#include <AudioPolicyManagerInterface.h>
#include <VolumeCurve.h>
#include <system/audio.h>
#include <utils/RefBase.h>
#include <HandleGenerator.h>
#include <string>
#include <vector>
#include <map>
#include <utils/Errors.h>
namespace android {
class VolumeGroup : public virtual RefBase, private HandleGenerator<uint32_t>
{
public:
VolumeGroup(const std::string &name, int indexMin, int indexMax);
std::string getName() const { return mName; }
volume_group_t getId() const { return mId; }
void add(const sp<VolumeCurve> &curve);
VolumeCurves *getVolumeCurves() { return &mGroupVolumeCurves; }
void addSupportedAttributes(const audio_attributes_t &attr);
AttributesVector getSupportedAttributes() const { return mGroupVolumeCurves.getAttributes(); }
void addSupportedStream(audio_stream_type_t stream);
StreamTypeVector getStreamTypes() const { return mGroupVolumeCurves.getStreamTypes(); }
void dump(String8 *dst, int spaces = 0) const;
private:
const std::string mName;
const volume_group_t mId;
VolumeCurves mGroupVolumeCurves;
};
class VolumeGroupMap : public std::map<volume_group_t, sp<VolumeGroup> >
{
public:
void dump(String8 *dst, int spaces = 0) const;
};
} // namespace android

@ -15,7 +15,7 @@
*/
#define LOG_TAG "APM::AudioPolicyEngine/Base"
#define LOG_NDEBUG 0
//#define LOG_NDEBUG 0
#include "EngineBase.h"
#include "EngineDefaultConfig.h"
@ -96,46 +96,47 @@ product_strategy_t EngineBase::getProductStrategyByName(const std::string &name)
engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig()
{
auto loadProductStrategies =
[](auto& strategyConfigs, auto& productStrategies) {
uint32_t groupid = 0;
[](auto& strategyConfigs, auto& productStrategies, auto& volumeGroups) {
for (auto& strategyConfig : strategyConfigs) {
sp<ProductStrategy> strategy = new ProductStrategy(strategyConfig.name);
for (const auto &group : strategyConfig.attributesGroups) {
const auto &iter = std::find_if(begin(volumeGroups), end(volumeGroups),
[&group](const auto &volumeGroup) {
return group.volumeGroup == volumeGroup.second->getName(); });
ALOG_ASSERT(iter != end(volumeGroups), "Invalid Volume Group Name %s",
group.volumeGroup.c_str());
if (group.stream != AUDIO_STREAM_DEFAULT) {
iter->second->addSupportedStream(group.stream);
}
for (const auto &attr : group.attributesVect) {
strategy->addAttributes({group.stream, groupid, attr});
strategy->addAttributes({group.stream, iter->second->getId(), attr});
iter->second->addSupportedAttributes(attr);
}
groupid += 1;
}
product_strategy_t strategyId = strategy->getId();
productStrategies[strategyId] = strategy;
}
};
auto loadVolumeCurves = [](const auto &configVolumes, auto &streamVolumeCollection) {
for (auto &configVolume : configVolumes) {
audio_stream_type_t streamType = AUDIO_STREAM_DEFAULT;
if (configVolume.stream.empty() ||
!StreamTypeConverter::fromString(configVolume.stream, streamType)) {
ALOGE("%s: Invalid stream type", __FUNCTION__);
continue;
}
VolumeCurves volumeCurves(streamType, configVolume.indexMin, configVolume.indexMax);
for (auto &configCurve : configVolume.volumeCurves) {
device_category deviceCategory = DEVICE_CATEGORY_SPEAKER;
if (!DeviceCategoryConverter::fromString(configCurve.deviceCategory,
deviceCategory)) {
auto loadVolumeGroups = [](auto &volumeConfigs, auto &volumeGroups) {
for (auto &volumeConfig : volumeConfigs) {
sp<VolumeGroup> volumeGroup = new VolumeGroup(volumeConfig.name, volumeConfig.indexMin,
volumeConfig.indexMax);
volumeGroups[volumeGroup->getId()] = volumeGroup;
for (auto &configCurve : volumeConfig.volumeCurves) {
device_category deviceCat = DEVICE_CATEGORY_SPEAKER;
if (!DeviceCategoryConverter::fromString(configCurve.deviceCategory, deviceCat)) {
ALOGE("%s: Invalid %s", __FUNCTION__, configCurve.deviceCategory.c_str());
continue;
}
sp<VolumeCurve> curve = new VolumeCurve(deviceCategory);
sp<VolumeCurve> curve = new VolumeCurve(deviceCat);
for (auto &point : configCurve.curvePoints) {
curve->add({point.index, point.attenuationInMb});
}
volumeCurves.add(curve);
volumeGroup->add(curve);
}
streamVolumeCollection.add(volumeCurves, streamType);
}
};
auto result = engineConfig::parse();
if (result.parsedConfig == nullptr) {
ALOGW("%s: No configuration found, using default matching phone experience.", __FUNCTION__);
@ -145,8 +146,10 @@ engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig()
static_cast<size_t>(ret == NO_ERROR ? 0 : 1)};
}
ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement);
loadProductStrategies(result.parsedConfig->productStrategies, mProductStrategies);
loadVolumeCurves(result.parsedConfig->volumeGroups, mStreamVolumeCurves);
loadVolumeGroups(result.parsedConfig->volumeGroups, mVolumeGroups);
loadProductStrategies(result.parsedConfig->productStrategies, mProductStrategies,
mVolumeGroups);
mProductStrategies.initialize();
return result;
}
@ -204,30 +207,77 @@ status_t EngineBase::listAudioProductStrategies(AudioProductStrategyVector &stra
return NO_ERROR;
}
VolumeCurves *EngineBase::getVolumeCurvesForAttributes(const audio_attributes_t &attr)
VolumeCurves *EngineBase::getVolumeCurvesForAttributes(const audio_attributes_t &attr) const
{
return &mStreamVolumeCurves.getVolumeCurvesForStream(getStreamTypeForAttributes(attr));
volume_group_t volGr = mProductStrategies.getVolumeGroupForAttributes(attr);
const auto &iter = mVolumeGroups.find(volGr);
LOG_ALWAYS_FATAL_IF(iter == std::end(mVolumeGroups), "No volume groups for %s", toString(attr).c_str());
return mVolumeGroups.at(volGr)->getVolumeCurves();
}
VolumeCurves *EngineBase::getVolumeCurvesForStreamType(audio_stream_type_t stream)
VolumeCurves *EngineBase::getVolumeCurvesForStreamType(audio_stream_type_t stream) const
{
return &mStreamVolumeCurves.getVolumeCurvesForStream(stream);
volume_group_t volGr = mProductStrategies.getVolumeGroupForStreamType(stream);
const auto &iter = mVolumeGroups.find(volGr);
LOG_ALWAYS_FATAL_IF(iter == std::end(mVolumeGroups), "No volume groups for %s",
toString(stream).c_str());
return mVolumeGroups.at(volGr)->getVolumeCurves();
}
status_t EngineBase::switchVolumeCurve(audio_stream_type_t streamSrc, audio_stream_type_t streamDst)
{
return mStreamVolumeCurves.switchVolumeCurve(streamSrc, streamDst);;
auto srcCurves = getVolumeCurvesForStreamType(streamSrc);
auto dstCurves = getVolumeCurvesForStreamType(streamDst);
if (srcCurves == nullptr || dstCurves == nullptr) {
return BAD_VALUE;
}
return dstCurves->switchCurvesFrom(*srcCurves);
}
status_t EngineBase::restoreOriginVolumeCurve(audio_stream_type_t stream)
{
return mStreamVolumeCurves.restoreOriginVolumeCurve(stream);
VolumeCurves *curves = getVolumeCurvesForStreamType(stream);
return curves != nullptr ? curves->switchCurvesFrom(*curves) : BAD_VALUE;
}
VolumeGroupVector EngineBase::getVolumeGroups() const
{
VolumeGroupVector group;
for (const auto &iter : mVolumeGroups) {
group.push_back(iter.first);
}
return group;
}
volume_group_t EngineBase::getVolumeGroupForAttributes(const audio_attributes_t &attr) const
{
return mProductStrategies.getVolumeGroupForAttributes(attr);
}
volume_group_t EngineBase::getVolumeGroupForStreamType(audio_stream_type_t stream) const
{
return mProductStrategies.getVolumeGroupForStreamType(stream);
}
StreamTypeVector EngineBase::getStreamTypesForVolumeGroup(volume_group_t volumeGroup) const
{
// @TODO default music stream to control volume if no group?
return (mVolumeGroups.find(volumeGroup) != end(mVolumeGroups)) ?
mVolumeGroups.at(volumeGroup)->getStreamTypes() :
StreamTypeVector(AUDIO_STREAM_MUSIC);
}
AttributesVector EngineBase::getAllAttributesForVolumeGroup(volume_group_t volumeGroup) const
{
return (mVolumeGroups.find(volumeGroup) != end(mVolumeGroups)) ?
mVolumeGroups.at(volumeGroup)->getSupportedAttributes() : AttributesVector();
}
void EngineBase::dump(String8 *dst) const
{
mProductStrategies.dump(dst, 2);
mStreamVolumeCurves.dump(dst, 2);
mVolumeGroups.dump(dst, 2);
}
} // namespace audio_policy

@ -25,11 +25,11 @@ namespace android {
const engineConfig::ProductStrategies gOrderedStrategies = {
{"STRATEGY_PHONE",
{
{"phone", AUDIO_STREAM_VOICE_CALL,
{"phone", AUDIO_STREAM_VOICE_CALL, "AUDIO_STREAM_VOICE_CALL",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_SOURCE_DEFAULT, 0,
""}},
},
{"sco", AUDIO_STREAM_BLUETOOTH_SCO,
{"sco", AUDIO_STREAM_BLUETOOTH_SCO, "AUDIO_STREAM_BLUETOOTH_SCO",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_SCO,
""}},
}
@ -37,18 +37,18 @@ const engineConfig::ProductStrategies gOrderedStrategies = {
},
{"STRATEGY_SONIFICATION",
{
{"ring", AUDIO_STREAM_RING,
{"ring", AUDIO_STREAM_RING, "AUDIO_STREAM_RING",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
AUDIO_SOURCE_DEFAULT, 0, ""}}
},
{"alarm", AUDIO_STREAM_ALARM,
{"alarm", AUDIO_STREAM_ALARM, "AUDIO_STREAM_ALARM",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ALARM, AUDIO_SOURCE_DEFAULT, 0, ""}},
}
},
},
{"STRATEGY_ENFORCED_AUDIBLE",
{
{"", AUDIO_STREAM_ENFORCED_AUDIBLE,
{"", AUDIO_STREAM_ENFORCED_AUDIBLE, "AUDIO_STREAM_ENFORCED_AUDIBLE",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
AUDIO_FLAG_AUDIBILITY_ENFORCED, ""}}
}
@ -56,7 +56,7 @@ const engineConfig::ProductStrategies gOrderedStrategies = {
},
{"STRATEGY_ACCESSIBILITY",
{
{"", AUDIO_STREAM_ACCESSIBILITY,
{"", AUDIO_STREAM_ACCESSIBILITY, "AUDIO_STREAM_ACCESSIBILITY",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
AUDIO_SOURCE_DEFAULT, 0, ""}}
}
@ -64,7 +64,7 @@ const engineConfig::ProductStrategies gOrderedStrategies = {
},
{"STRATEGY_SONIFICATION_RESPECTFUL",
{
{"", AUDIO_STREAM_NOTIFICATION,
{"", AUDIO_STREAM_NOTIFICATION, "AUDIO_STREAM_NOTIFICATION",
{
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION, AUDIO_SOURCE_DEFAULT, 0, ""},
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
@ -81,7 +81,7 @@ const engineConfig::ProductStrategies gOrderedStrategies = {
},
{"STRATEGY_MEDIA",
{
{"music", AUDIO_STREAM_MUSIC,
{"music", AUDIO_STREAM_MUSIC, "AUDIO_STREAM_MUSIC",
{
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_MEDIA, AUDIO_SOURCE_DEFAULT, 0, ""},
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_GAME, AUDIO_SOURCE_DEFAULT, 0, ""},
@ -91,7 +91,7 @@ const engineConfig::ProductStrategies gOrderedStrategies = {
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, 0, ""}
},
},
{"system", AUDIO_STREAM_SYSTEM,
{"system", AUDIO_STREAM_SYSTEM, "AUDIO_STREAM_SYSTEM",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANCE_SONIFICATION,
AUDIO_SOURCE_DEFAULT, 0, ""}}
}
@ -99,7 +99,7 @@ const engineConfig::ProductStrategies gOrderedStrategies = {
},
{"STRATEGY_DTMF",
{
{"", AUDIO_STREAM_DTMF,
{"", AUDIO_STREAM_DTMF, "AUDIO_STREAM_DTMF",
{
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
AUDIO_SOURCE_DEFAULT, 0, ""}
@ -109,7 +109,7 @@ const engineConfig::ProductStrategies gOrderedStrategies = {
},
{"STRATEGY_TRANSMITTED_THROUGH_SPEAKER",
{
{"", AUDIO_STREAM_TTS,
{"", AUDIO_STREAM_TTS, "AUDIO_STREAM_TTS",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
AUDIO_FLAG_BEACON, ""}}
}
@ -117,14 +117,14 @@ const engineConfig::ProductStrategies gOrderedStrategies = {
},
{"STRATEGY_REROUTING",
{
{"", AUDIO_STREAM_REROUTING,
{"", AUDIO_STREAM_REROUTING, "AUDIO_STREAM_REROUTING",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, 0, ""}}
}
},
},
{"STRATEGY_PATCH",
{
{"", AUDIO_STREAM_PATCH,
{"", AUDIO_STREAM_PATCH, "AUDIO_STREAM_PATCH",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, 0, ""}}
}
},

@ -44,7 +44,7 @@ std::vector<android::AudioAttributes> ProductStrategy::listAudioAttributes() con
{
std::vector<android::AudioAttributes> androidAa;
for (const auto &attr : mAttributesVector) {
androidAa.push_back({attr.mGroupId, attr.mStream, attr.mAttributes});
androidAa.push_back({attr.mVolumeGroup, attr.mStream, attr.mAttributes});
}
return androidAa;
}
@ -69,7 +69,8 @@ bool ProductStrategy::matches(const audio_attributes_t attr) const
}) != end(mAttributesVector);
}
audio_stream_type_t ProductStrategy::getStreamTypeForAttributes(const audio_attributes_t &attr) const
audio_stream_type_t ProductStrategy::getStreamTypeForAttributes(
const audio_attributes_t &attr) const
{
const auto iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
[&attr](const auto &supportedAttr) {
@ -110,6 +111,33 @@ bool ProductStrategy::supportStreamType(const audio_stream_type_t &streamType) c
return supportedAttr.mStream == streamType; }) != end(mAttributesVector);
}
volume_group_t ProductStrategy::getVolumeGroupForAttributes(const audio_attributes_t &attr) const
{
for (const auto &supportedAttr : mAttributesVector) {
if (AudioProductStrategy::attributesMatches(supportedAttr.mAttributes, attr)) {
return supportedAttr.mVolumeGroup;
}
}
return VOLUME_GROUP_NONE;
}
volume_group_t ProductStrategy::getVolumeGroupForStreamType(audio_stream_type_t stream) const
{
for (const auto &supportedAttr : mAttributesVector) {
if (supportedAttr.mStream == stream) {
return supportedAttr.mVolumeGroup;
}
}
return VOLUME_GROUP_NONE;
}
volume_group_t ProductStrategy::getDefaultVolumeGroup() const
{
const auto &iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
[](const auto &attr) {return attr.mAttributes == defaultAttr;});
return iter != end(mAttributesVector) ? iter->mVolumeGroup : VOLUME_GROUP_NONE;
}
void ProductStrategy::dump(String8 *dst, int spaces) const
{
dst->appendFormat("\n%*s-%s (id: %d)\n", spaces, "", mName.c_str(), mId);
@ -121,7 +149,7 @@ void ProductStrategy::dump(String8 *dst, int spaces) const
deviceLiteral.c_str(), mDeviceAddress.c_str());
for (const auto &attr : mAttributesVector) {
dst->appendFormat("%*sGroup: %d stream: %s\n", spaces + 3, "", attr.mGroupId,
dst->appendFormat("%*sGroup: %d stream: %s\n", spaces + 3, "", attr.mVolumeGroup,
android::toString(attr.mStream).c_str());
dst->appendFormat("%*s Attributes: ", spaces + 3, "");
std::string attStr =
@ -172,6 +200,9 @@ audio_stream_type_t ProductStrategyMap::getStreamTypeForAttributes(
product_strategy_t ProductStrategyMap::getDefault() const
{
if (mDefaultStrategy != PRODUCT_STRATEGY_NONE) {
return mDefaultStrategy;
}
for (const auto &iter : *this) {
if (iter.second->isDefault()) {
ALOGV("%s: using default %s", __FUNCTION__, iter.second->getName().c_str());
@ -231,6 +262,42 @@ std::string ProductStrategyMap::getDeviceAddressForProductStrategy(product_strat
return at(psId)->getDeviceAddress();
}
volume_group_t ProductStrategyMap::getVolumeGroupForAttributes(const audio_attributes_t &attr) const
{
for (const auto &iter : *this) {
volume_group_t group = iter.second->getVolumeGroupForAttributes(attr);
if (group != VOLUME_GROUP_NONE) {
return group;
}
}
product_strategy_t defaultStrategy = getDefault();
if (defaultStrategy == PRODUCT_STRATEGY_NONE) {
return VOLUME_GROUP_NONE;
}
return at(defaultStrategy)->getDefaultVolumeGroup();
}
volume_group_t ProductStrategyMap::getVolumeGroupForStreamType(audio_stream_type_t stream) const
{
for (const auto &iter : *this) {
volume_group_t group = iter.second->getVolumeGroupForStreamType(stream);
if (group != VOLUME_GROUP_NONE) {
return group;
}
}
product_strategy_t defaultStrategy = getDefault();
if (defaultStrategy == PRODUCT_STRATEGY_NONE) {
return VOLUME_GROUP_NONE;
}
return at(defaultStrategy)->getDefaultVolumeGroup();
}
void ProductStrategyMap::initialize()
{
mDefaultStrategy = getDefault();
ALOG_ASSERT(mDefaultStrategy != PRODUCT_STRATEGY_NONE, "No default product strategy found");
}
void ProductStrategyMap::dump(String8 *dst, int spaces) const
{
dst->appendFormat("%*sProduct Strategies dump:", spaces, "");

@ -1,47 +0,0 @@
/*
* Copyright (C) 2018 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::Engine::StreamVolumeCurves"
//#define LOG_NDEBUG 0
#include "StreamVolumeCurves.h"
#include <TypeConverter.h>
namespace android {
void StreamVolumeCurves::dump(String8 *dst, int spaces) const
{
if (mCurves.empty()) {
return;
}
dst->appendFormat("\n%*sStreams dump:\n", spaces, "");
dst->appendFormat(
"%*sStream Can be muted Index Min Index Max Index Cur [device : index]...\n", spaces + 2, "");
for (const auto &streamCurve : mCurves) {
streamCurve.second.dump(dst, spaces + 2, false);
}
dst->appendFormat("\n%*sVolume Curves for Use Cases (aka Stream types) dump:\n", spaces, "");
for (const auto &streamCurve : mCurves) {
std::string streamTypeLiteral;
StreamTypeConverter::toString(streamCurve.first, streamTypeLiteral);
dst->appendFormat(
" %s (%02d): Curve points for device category (index, attenuation in millibel)\n",
streamTypeLiteral.c_str(), streamCurve.first);
streamCurve.second.dump(dst, spaces + 2, true);
}
}
} // namespace android

@ -19,13 +19,17 @@
#include "VolumeCurve.h"
#include "TypeConverter.h"
#include <media/TypeConverter.h>
namespace android {
float VolumeCurve::volIndexToDb(int indexInUi, int volIndexMin, int volIndexMax) const
{
ALOG_ASSERT(!mCurvePoints.isEmpty(), "Invalid volume curve");
if (volIndexMin < 0 || volIndexMax < 0) {
// In order to let AudioService initialize the min and max, convention is to use -1
return NAN;
}
if (indexInUi < volIndexMin) {
// an index of 0 means mute request when volIndexMin > 0
if (indexInUi == 0) {
@ -80,8 +84,8 @@ void VolumeCurve::dump(String8 *dst, int spaces, bool curvePoints) const
}
dst->append(" {");
for (size_t i = 0; i < mCurvePoints.size(); i++) {
dst->appendFormat("%*s (%3d, %5d)", spaces, "",
mCurvePoints[i].mIndex, mCurvePoints[i].mAttenuationInMb);
dst->appendFormat("%*s(%3d, %5d)", spaces, "", mCurvePoints[i].mIndex,
mCurvePoints[i].mAttenuationInMb);
dst->appendFormat(i == (mCurvePoints.size() - 1) ? " }\n" : ", ");
}
}
@ -89,19 +93,36 @@ void VolumeCurve::dump(String8 *dst, int spaces, bool curvePoints) const
void VolumeCurves::dump(String8 *dst, int spaces, bool curvePoints) const
{
if (!curvePoints) {
dst->appendFormat("%*s%02d %s %03d %03d ", spaces, "",
mStream, mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax);
// dst->appendFormat("%*s%02d %s %03d %03d ", spaces, "",
// mStream, mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax);
dst->appendFormat("%*s Can be muted Index Min Index Max Index Cur [device : index]...\n",
spaces + 1, "");
dst->appendFormat("%*s %s %02d %02d ", spaces + 1, "",
mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax);
for (const auto &pair : mIndexCur) {
dst->appendFormat("%*s %04x : %02d, ", spaces, "", pair.first, pair.second);
dst->appendFormat("%04x : %02d, ", pair.first, pair.second);
}
dst->appendFormat("\n");
return;
}
std::string streamNames;
for (const auto &stream : mStreams) {
streamNames += android::toString(stream) + "("+std::to_string(stream)+") ";
}
dst->appendFormat("%*sVolume Curves Streams/Attributes, Curve points Streams for device"
" category (index, attenuation in millibel)\n", spaces, "");
dst->appendFormat("%*s Streams: %s \n", spaces, "", streamNames.c_str());
if (!mAttributes.empty()) dst->appendFormat("%*s Attributes:", spaces, "");
for (const auto &attributes : mAttributes) {
std::string attStr = attributes == defaultAttr ? "{ Any }" : android::toString(attributes);
dst->appendFormat("%*s %s\n", attributes == mAttributes.front() ? 0 : spaces + 13, "",
attStr.c_str());
}
for (size_t i = 0; i < size(); i++) {
std::string deviceCatLiteral;
DeviceCategoryConverter::toString(keyAt(i), deviceCatLiteral);
dst->appendFormat("%*s %s :", spaces, "", deviceCatLiteral.c_str());
valueAt(i)->dump(dst, 2, true);
valueAt(i)->dump(dst, 1, true);
}
}

@ -0,0 +1,75 @@
/*
* Copyright (C) 2018 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::AudioPolicyEngine/VolumeGroup"
//#define LOG_NDEBUG 0
#include "VolumeGroup.h"
#include <media/TypeConverter.h>
#include <utils/String8.h>
#include <cstdint>
#include <string>
#include <log/log.h>
namespace android {
//
// VolumeGroup implementation
//
VolumeGroup::VolumeGroup(const std::string &name, int indexMin, int indexMax) :
mName(name), mId(static_cast<volume_group_t>(HandleGenerator<uint32_t>::getNextHandle())),
mGroupVolumeCurves(VolumeCurves(indexMin, indexMax))
{
}
void VolumeGroup::dump(String8 *dst, int spaces) const
{
dst->appendFormat("\n%*s-%s (id: %d)\n", spaces, "", mName.c_str(), mId);
mGroupVolumeCurves.dump(dst, spaces + 2, true);
mGroupVolumeCurves.dump(dst, spaces + 2, false);
dst->appendFormat("\n");
}
void VolumeGroup::add(const sp<VolumeCurve> &curve)
{
mGroupVolumeCurves.add(curve);
}
void VolumeGroup::addSupportedAttributes(const audio_attributes_t &attr)
{
mGroupVolumeCurves.addAttributes(attr);
}
void VolumeGroup::addSupportedStream(audio_stream_type_t stream)
{
mGroupVolumeCurves.addStreamType(stream);
}
//
// VolumeGroupMap implementation
//
void VolumeGroupMap::dump(String8 *dst, int spaces) const
{
dst->appendFormat("\n%*sVolume Groups dump:", spaces, "");
for (const auto &iter : *this) {
iter.second->dump(dst, spaces + 2);
}
}
} // namespace android

@ -40,6 +40,7 @@ using StreamVector = std::vector<audio_stream_type_t>;
struct AttributesGroup {
std::string name;
audio_stream_type_t stream;
std::string volumeGroup;
AttributesVector attributesVect;
};
@ -59,7 +60,6 @@ using VolumeCurves = std::vector<VolumeCurve>;
struct VolumeGroup {
std::string name;
std::string stream;
int indexMin;
int indexMax;
VolumeCurves volumeCurves;

@ -59,6 +59,7 @@ struct AttributesGroupTraits : public BaseSerializerTraits<AttributesGroup, Attr
struct Attributes {
static constexpr const char *name = "name";
static constexpr const char *streamType = "streamType";
static constexpr const char *volumeGroup = "volumeGroup";
};
static android::status_t deserialize(_xmlDoc *doc, const _xmlNode *root, Collection &ps);
};
@ -116,6 +117,7 @@ struct VolumeTraits : public BaseSerializerTraits<VolumeCurve, VolumeCurves> {
struct Attributes {
static constexpr const char *deviceCategory = "deviceCategory";
static constexpr const char *stream = "stream"; // For legacy volume curves
static constexpr const char *reference = "ref"; /**< For volume curves factorization. */
};
@ -139,8 +141,6 @@ struct VolumeGroupTraits : public BaseSerializerTraits<VolumeGroup, VolumeGroups
using xmlCharUnique = std::unique_ptr<xmlChar, decltype(xmlFree)>;
using xmlCharUnique = std::unique_ptr<xmlChar, decltype(xmlFree)>;
std::string getXmlAttribute(const xmlNode *cur, const char *attribute)
{
xmlCharUnique charPtr(xmlGetProp(cur, reinterpret_cast<const xmlChar *>(attribute)), xmlFree);
@ -304,6 +304,12 @@ status_t AttributesGroupTraits::deserialize(_xmlDoc *doc, const _xmlNode *child,
}
ALOGV("%s: %s = %s", __FUNCTION__, Attributes::name, name.c_str());
std::string volumeGroup = getXmlAttribute(child, Attributes::volumeGroup);
if (volumeGroup.empty()) {
ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::volumeGroup);
}
ALOGV("%s: %s = %s", __FUNCTION__, Attributes::volumeGroup, volumeGroup.c_str());
audio_stream_type_t streamType = AUDIO_STREAM_DEFAULT;
std::string streamTypeXml = getXmlAttribute(child, Attributes::streamType);
if (streamTypeXml.empty()) {
@ -318,7 +324,7 @@ status_t AttributesGroupTraits::deserialize(_xmlDoc *doc, const _xmlNode *child,
AttributesVector attributesVect;
deserializeAttributesCollection(doc, child, attributesVect);
attributesGroup.push_back({name, streamType, attributesVect});
attributesGroup.push_back({name, streamType, volumeGroup, attributesVect});
return NO_ERROR;
}
@ -420,7 +426,6 @@ status_t VolumeTraits::deserialize(_xmlDoc *doc, const _xmlNode *root, Collectio
if (deviceCategory.empty()) {
ALOGW("%s: No %s found", __FUNCTION__, Attributes::deviceCategory);
}
std::string referenceName = getXmlAttribute(root, Attributes::reference);
const _xmlNode *ref = NULL;
if (!referenceName.empty()) {
@ -458,9 +463,10 @@ status_t VolumeTraits::deserialize(_xmlDoc *doc, const _xmlNode *root, Collectio
status_t VolumeGroupTraits::deserialize(_xmlDoc *doc, const _xmlNode *root, Collection &volumes)
{
std::string name;
std::string stream = {};
int indexMin = 0;
int indexMax = 0;
StreamVector streams = {};
AttributesVector attributesVect = {};
for (const xmlNode *child = root->xmlChildrenNode; child != NULL; child = child->next) {
if (not xmlStrcmp(child->name, (const xmlChar *)Attributes::name)) {
@ -470,13 +476,6 @@ status_t VolumeGroupTraits::deserialize(_xmlDoc *doc, const _xmlNode *root, Coll
}
name = reinterpret_cast<const char*>(nameXml.get());
}
if (not xmlStrcmp(child->name, (const xmlChar *)Attributes::stream)) {
xmlCharUnique streamXml(xmlNodeListGetString(doc, child->xmlChildrenNode, 1), xmlFree);
if (streamXml == nullptr) {
return BAD_VALUE;
}
stream = reinterpret_cast<const char*>(streamXml.get());
}
if (not xmlStrcmp(child->name, (const xmlChar *)Attributes::indexMin)) {
xmlCharUnique indexMinXml(xmlNodeListGetString(doc, child->xmlChildrenNode, 1), xmlFree);
if (indexMinXml == nullptr) {
@ -498,13 +497,23 @@ status_t VolumeGroupTraits::deserialize(_xmlDoc *doc, const _xmlNode *root, Coll
}
}
}
ALOGV("%s: group=%s stream=%s indexMin=%d, indexMax=%d",
__func__, name.c_str(), stream.c_str(), indexMin, indexMax);
deserializeAttributesCollection(doc, root, attributesVect);
std::string streamNames;
for (const auto &stream : streams) {
streamNames += android::toString(stream) + " ";
}
std::string attrmNames;
for (const auto &attr : attributesVect) {
attrmNames += android::toString(attr) + "\n";
}
ALOGV("%s: group=%s indexMin=%d, indexMax=%d streams=%s attributes=%s",
__func__, name.c_str(), indexMin, indexMax, streamNames.c_str(), attrmNames.c_str( ));
VolumeCurves groupVolumeCurves;
size_t skipped = 0;
deserializeCollection<VolumeTraits>(doc, root, groupVolumeCurves, skipped);
volumes.push_back({ name, stream, indexMin, indexMax, groupVolumeCurves });
volumes.push_back({ name, indexMin, indexMax, groupVolumeCurves });
return NO_ERROR;
}
@ -580,8 +589,16 @@ static status_t deserializeLegacyVolumeCollection(_xmlDoc *doc, const _xmlNode *
}
}
for (const auto &volumeMapIter : legacyVolumeMap) {
volumeGroups.push_back({ volumeMapIter.first, volumeMapIter.first, 0, 100,
volumeMapIter.second });
// In order to let AudioService setting the min and max (compatibility), set Min and Max
// to -1 except for private streams
audio_stream_type_t streamType;
if (!StreamTypeConverter::fromString(volumeMapIter.first, streamType)) {
ALOGE("%s: Invalid stream %s", __func__, volumeMapIter.first.c_str());
return BAD_VALUE;
}
int indexMin = streamType >= AUDIO_STREAM_PUBLIC_CNT ? 0 : -1;
int indexMax = streamType >= AUDIO_STREAM_PUBLIC_CNT ? 100 : -1;
volumeGroups.push_back({ volumeMapIter.first, indexMin, indexMax, volumeMapIter.second });
}
return NO_ERROR;
}

@ -32,7 +32,7 @@ namespace android {
using DeviceStrategyMap = std::map<product_strategy_t, DeviceVector>;
using StrategyVector = std::vector<product_strategy_t>;
using VolumeGroupVector = std::vector<volume_group_t>;
/**
* This interface is dedicated to the policy manager that a Policy Engine shall implement.
@ -182,6 +182,7 @@ public:
/**
* @brief getAttributesForStream get the audio attributes from legacy stream type
* Attributes returned might only be used to check upon routing decision, not volume decisions.
* @param stream to consider
* @return audio attributes matching the legacy stream type
*/
@ -241,14 +242,49 @@ public:
* @param attr to be considered
* @return IVolumeCurves interface pointer if found, nullptr otherwise
*/
virtual IVolumeCurves *getVolumeCurvesForAttributes(const audio_attributes_t &attr) = 0;
virtual IVolumeCurves *getVolumeCurvesForAttributes(const audio_attributes_t &attr) const = 0;
/**
* @brief getVolumeCurvesForStreamType retrieves the Volume Curves interface for the stream
* @param stream to be considered
* @return IVolumeCurves interface pointer if found, nullptr otherwise
*/
virtual IVolumeCurves *getVolumeCurvesForStreamType(audio_stream_type_t stream) = 0;
virtual IVolumeCurves *getVolumeCurvesForStreamType(audio_stream_type_t stream) const = 0;
/**
* @brief getVolumeCurvesForVolumeGroup retrieves the Volume Curves interface for volume group
* @param group to be considered
* @return IVolumeCurves interface pointer if found, nullptr otherwise
*/
virtual IVolumeCurves *getVolumeCurvesForVolumeGroup(volume_group_t group) const = 0;
/**
* @brief getVolumeGroups retrieves the collection of volume groups.
* @return vector of volume groups
*/
virtual VolumeGroupVector getVolumeGroups() const = 0;
/**
* @brief getVolumeGroupForAttributes gets the appropriate volume group to be used for a given
* Audio Attributes.
* @param attr to be considered
* @return volume group associated to the given audio attributes, default group if none
* applicable, VOLUME_GROUP_NONE if no default group defined.
*/
virtual volume_group_t getVolumeGroupForAttributes(const audio_attributes_t &attr) const = 0;
/**
* @brief getVolumeGroupForStreamType gets the appropriate volume group to be used for a given
* legacy stream type
* @param stream type to be considered
* @return volume group associated to the given stream type, default group if none applicable,
* VOLUME_GROUP_NONE if no default group defined.
*/
virtual volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const = 0;
virtual StreamTypeVector getStreamTypesForVolumeGroup(volume_group_t volumeGroup) const = 0;
virtual AttributesVector getAllAttributesForVolumeGroup(volume_group_t volumeGroup) const = 0;
virtual void dump(String8 *dst) const = 0;

@ -13,7 +13,7 @@ LOCAL_SRC_FILES := \
src/Stream.cpp \
src/InputSource.cpp \
../engine/common/src/VolumeCurve.cpp \
../engine/common/src/StreamVolumeCurves.cpp \
../engine/common/src/VolumeGroup.cpp \
../engine/common/src/ProductStrategy.cpp \
../engine/common/src/EngineBase.cpp

@ -72,7 +72,8 @@ LOCAL_SRC_FILES := automotive/$(LOCAL_MODULE_STEM)
LOCAL_REQUIRED_MODULES := \
audio_policy_engine_product_strategies_automotive.xml \
audio_policy_engine_criteria.xml \
audio_policy_engine_criterion_types.xml
audio_policy_engine_criterion_types.xml \
audio_policy_engine_volumes.xml
include $(BUILD_PREBUILT)
@ -89,6 +90,14 @@ LOCAL_VENDOR_MODULE := true
LOCAL_SRC_FILES := automotive/$(LOCAL_MODULE_STEM)
include $(BUILD_PREBUILT)
include $(CLEAR_VARS)
LOCAL_MODULE := audio_policy_engine_volumes.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
LOCAL_VENDOR_MODULE := true
LOCAL_SRC_FILES := automotive/$(LOCAL_MODULE)
include $(BUILD_PREBUILT)
endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), automotive_configurable)
ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable))

@ -19,6 +19,7 @@
<xi:include href="audio_policy_engine_product_strategies.xml"/>
<xi:include href="audio_policy_engine_criterion_types.xml"/>
<xi:include href="audio_policy_engine_criteria.xml"/>
<xi:include href="audio_policy_engine_volumes.xml"/>
</configuration>

@ -31,7 +31,7 @@ limitations under the License.
-->
<ProductStrategy name="oem_traffic_anouncement">
<AttributesGroup>
<AttributesGroup volumeGroup="oem_traffic_anouncement">
<ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
<Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
<!-- traffic_annoucement = 1 -->
@ -39,14 +39,14 @@ limitations under the License.
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="oem_strategy_1">
<AttributesGroup>
<AttributesGroup volumeGroup="oem_adas_2">
<ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
<Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
<Bundle key="oem" value="2"/>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="oem_strategy_2">
<AttributesGroup>
<AttributesGroup volumeGroup="oem_adas_3">
<ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
<Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
<Bundle key="oem" value="3"/>
@ -70,21 +70,21 @@ limitations under the License.
( type == CAR_AUDIO_TYPE_RADIO ) )
-->
<ProductStrategy name="radio">
<AttributesGroup>
<AttributesGroup volumeGroup="media_car_audio_type_3">
<ContentType value="AUDIO_CONTENT_TYPE_MUSIC"/>
<Usage value="AUDIO_USAGE_MEDIA"/>
<Bundle key="car_audio_type" value="3"/>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="ext_audio_source">
<AttributesGroup>
<AttributesGroup volumeGroup="media_car_audio_type_7">
<ContentType value="AUDIO_CONTENT_TYPE_MUSIC"/>
<Usage value="AUDIO_USAGE_MEDIA"/>
<Bundle key="car_audio_type" value="7"/>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="voice_command">
<AttributesGroup>
<AttributesGroup volumeGroup="speech">
<Attributes>
<ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
<Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
@ -96,7 +96,7 @@ limitations under the License.
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="safety_alert">
<AttributesGroup>
<AttributesGroup volumeGroup="system">
<ContentType value="AUDIO_CONTENT_TYPE_SONIFICATION"/>
<Usage value="AUDIO_USAGE_NOTIFICATION"/>
<!-- CAR_AUDIO_TYPE_SAFETY_ALERT = 2 -->
@ -112,7 +112,7 @@ limitations under the License.
<!-- Generic Usages -->
<ProductStrategy name="music">
<AttributesGroup streamType="AUDIO_STREAM_MUSIC">
<AttributesGroup streamType="AUDIO_STREAM_MUSIC" volumeGroup="media">
<Attributes> <Usage value="AUDIO_USAGE_MEDIA"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_GAME"/> </Attributes>
<!-- Default product strategy has empty attributes -->
@ -121,29 +121,31 @@ limitations under the License.
</ProductStrategy>
<ProductStrategy name="nav_guidance">
<AttributesGroup>
<AttributesGroup volumeGroup="speech">
<Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="voice_call">
<AttributesGroup streamType="AUDIO_STREAM_VOICE_CALL">
<AttributesGroup streamType="AUDIO_STREAM_VOICE_CALL" volumeGroup="phone">
<Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING"/> </Attributes>
</AttributesGroup>
<AttributesGroup streamType="AUDIO_STREAM_BLUETOOTH_SCO" volumeGroup="phone">
<Attributes> <Flags value="AUDIO_FLAG_SCO"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="alarm">
<AttributesGroup streamType="AUDIO_STREAM_ALARM">
<AttributesGroup streamType="AUDIO_STREAM_ALARM" volumeGroup="ring">
<Usage value="AUDIO_USAGE_ALARM"/>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="ring">
<AttributesGroup streamType="AUDIO_STREAM_RING">
<AttributesGroup streamType="AUDIO_STREAM_RING" volumeGroup="ring">
<Usage value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE"/>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="notification">
<AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION">
<AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION" volumeGroup="ring">
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED"/> </Attributes>
@ -152,10 +154,17 @@ limitations under the License.
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="system">
<AttributesGroup streamType="AUDIO_STREAM_SYSTEM">
<AttributesGroup streamType="AUDIO_STREAM_SYSTEM" volumeGroup="system">
<Usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION"/>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="tts">
<!-- TTS stream MUST BE MANAGED OUTSIDE default product strategy if NO DEDICATED OUTPUT
for TTS, otherwise when beacon happens, default strategy is ... muted.
If it is media, it is annoying... -->
<AttributesGroup streamType="AUDIO_STREAM_TTS" volumeGroup="tts">
<Attributes> <Flags value="AUDIO_FLAG_BEACON"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
</ProductStrategies>

@ -0,0 +1,192 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Copyright (C) 2018 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.
-->
<!-- Volume Groups Tables included by Audio Policy Configuration file -->
<!-- Note:
It is VALID to have a group without attributes if a product strategy is following
this group for all attributes.
Otherwise, attributes must be specified
-->
<volumeGroups>
<volumeGroup>
<name>oem_traffic_anouncement</name>
<indexMin>0</indexMin>
<indexMax>40</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
<point>0,-4200</point>
<point>33,-2800</point>
<point>66,-1400</point>
<point>100,0</point>
</volume>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
<point>0,-4200</point>
<point>33,-2800</point>
<point>66,-1400</point>
<point>100,0</point>
</volume>
<volume deviceCategory="DEVICE_CATEGORY_EARPIECE">
<point>0,-4200</point>
<point>33,-2800</point>
<point>66,-1400</point>
<point>100,0</point>
</volume>
<volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA">
<point>0,-4200</point>
<point>33,-2800</point>
<point>66,-1400</point>
<point>100,0</point>
</volume>
</volumeGroup>
<!-- OEM ADAS is a volume group that has a single port gain (this is the reason why it is a group
but may host different streams.
A priority must be given among them (either they are multualy excluisve, so the volume
will be the one of the currently acitve stream, otherwise a priority must be given by
any mean. -->
<volumeGroup>
<name>oem_adas_2</name>
<indexMin>0</indexMin>
<indexMax>40</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
<point>0,-4200</point>
<point>33,-2800</point>
<point>66,-1400</point>
<point>100,0</point>
</volume>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
<point>0,-4200</point>
<point>33,-2800</point>
<point>66,-1400</point>
<point>100,0</point>
</volume>
</volumeGroup>
<volumeGroup>
<name>oem_adas_3</name>
<indexMin>0</indexMin>
<indexMax>40</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
<point>0,-2400</point>
<point>33,-1600</point>
<point>66,-800</point>
<point>100,0</point>
</volume>
<volume deviceCategory="DEVICE_CATEGORY_EARPIECE">
<point>0,-2400</point>
<point>33,-1600</point>
<point>66,-800</point>
<point>100,0</point>
</volume>
</volumeGroup>
<!-- MEDIA is a volume group that has a single port gain (this is the reason why it is a group
but may host different streams.
A priority must be given among them (either they are multualy exclusive, so the volume
will be the one of the active stream with highest priority (ORDER MATTERS) unless the curves
followed will the the curves for the requested attributes.-->
<volumeGroup>
<name>media_car_audio_type_3</name>
<indexMin>0</indexMin>
<indexMax>40</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
<point>0,-4200</point>
<point>33,-2800</point>
<point>66,-1400</point>
<point>100,0</point>
</volume>
</volumeGroup>
<volumeGroup>
<name>media_car_audio_type_7</name>
<indexMin>0</indexMin>
<indexMax>40</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
<point>0,-2400</point>
<point>33,-1600</point>
<point>66,-800</point>
<point>100,0</point>
</volume>
</volumeGroup>
<volumeGroup>
<name>media</name>
<indexMin>0</indexMin>
<indexMax>40</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
<point>0,-2400</point>
<point>33,-1600</point>
<point>66,-800</point>
<point>100,0</point>
</volume>
</volumeGroup>
<volumeGroup>
<name>speech</name>
<indexMin>1</indexMin>
<indexMax>40</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
<point>0,-4200</point>
<point>33,-2800</point>
<point>66,-1400</point>
<point>100,0</point>
</volume>
</volumeGroup>
<volumeGroup>
<name>system</name>
<indexMin>0</indexMin>
<indexMax>40</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
<point>0,-4200</point>
<point>33,-2800</point>
<point>66,-1400</point>
<point>100,0</point>
</volume>
</volumeGroup>
<volumeGroup>
<name>phone</name>
<indexMin>1</indexMin>
<indexMax>40</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
<point>0,-4200</point>
<point>33,-2800</point>
<point>66,-1400</point>
<point>100,0</point>
</volume>
</volumeGroup>
<volumeGroup>
<name>ring</name>
<indexMin>0</indexMin>
<indexMax>40</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
<point>0,-4200</point>
<point>33,-2800</point>
<point>66,-1400</point>
<point>100,0</point>
</volume>
</volumeGroup>
<volumeGroup>
<name>tts</name>
<indexMin>0</indexMin>
<indexMax>15</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
<point>0,-0</point>
<point>100,0</point>
</volume>
</volumeGroup>
</volumeGroups>

@ -25,37 +25,37 @@
enforced. -->
<ProductStrategy name="STRATEGY_PHONE">
<AttributesGroup streamType="AUDIO_STREAM_VOICE_CALL">
<AttributesGroup streamType="AUDIO_STREAM_VOICE_CALL" volumeGroup="voice_call">
<Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION"/> </Attributes>
</AttributesGroup>
<AttributesGroup streamType="AUDIO_STREAM_BLUETOOTH_SCO">
<AttributesGroup streamType="AUDIO_STREAM_BLUETOOTH_SCO" volumeGroup="bluetooth_sco">
<Attributes> <Flags value="AUDIO_FLAG_SCO"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="STRATEGY_SONIFICATION">
<AttributesGroup streamType="AUDIO_STREAM_RING">
<AttributesGroup streamType="AUDIO_STREAM_RING" volumeGroup="ring">
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE"/> </Attributes>
</AttributesGroup>
<AttributesGroup streamType="AUDIO_STREAM_ALARM">
<AttributesGroup streamType="AUDIO_STREAM_ALARM" volumeGroup="alarm">
<Attributes> <Usage value="AUDIO_USAGE_ALARM"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="STRATEGY_ENFORCED_AUDIBLE">
<AttributesGroup streamType="AUDIO_STREAM_ENFORCED_AUDIBLE">
<AttributesGroup streamType="AUDIO_STREAM_ENFORCED_AUDIBLE" volumeGroup="enforced_audible">
<Attributes> <Flags value="AUDIO_FLAG_AUDIBILITY_ENFORCED"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="STRATEGY_ACCESSIBILITY">
<AttributesGroup streamType="AUDIO_STREAM_ACCESSIBILITY">
<AttributesGroup streamType="AUDIO_STREAM_ACCESSIBILITY" volumeGroup="accessibility">
<Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="STRATEGY_SONIFICATION_RESPECTFUL">
<AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION">
<AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION" volumeGroup="notification">
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/> </Attributes>
@ -65,20 +65,20 @@
</ProductStrategy>
<ProductStrategy name="STRATEGY_MEDIA">
<AttributesGroup streamType="AUDIO_STREAM_MUSIC">
<AttributesGroup streamType="AUDIO_STREAM_MUSIC" volumeGroup="music">
<Attributes> <Usage value="AUDIO_USAGE_MEDIA"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_GAME"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_ASSISTANT"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/> </Attributes>
<Attributes></Attributes>
</AttributesGroup>
<AttributesGroup streamType="AUDIO_STREAM_SYSTEM">
<AttributesGroup streamType="AUDIO_STREAM_SYSTEM" volumeGroup="system">
<Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="STRATEGY_DTMF">
<AttributesGroup streamType="AUDIO_STREAM_DTMF">
<AttributesGroup streamType="AUDIO_STREAM_DTMF" volumeGroup="dtmf">
<Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
@ -86,21 +86,21 @@
<!-- Used to identify the volume of audio streams exclusively transmitted through the speaker
(TTS) of the device -->
<ProductStrategy name="STRATEGY_TRANSMITTED_THROUGH_SPEAKER">
<AttributesGroup streamType="AUDIO_STREAM_TTS">
<AttributesGroup streamType="AUDIO_STREAM_TTS" volumeGroup="tts">
<Attributes> <Flags value="AUDIO_FLAG_BEACON"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<!-- Routing Strategy rerouting may be removed as following media??? -->
<ProductStrategy name="STRATEGY_REROUTING">
<AttributesGroup streamType="AUDIO_STREAM_REROUTING">
<AttributesGroup streamType="AUDIO_STREAM_REROUTING" volumeGroup="rerouting">
<Attributes></Attributes>
</AttributesGroup>
</ProductStrategy>
<!-- Default product strategy has empty attributes -->
<ProductStrategy name="STRATEGY_PATCH">
<AttributesGroup streamType="AUDIO_STREAM_PATCH">
<AttributesGroup streamType="AUDIO_STREAM_PATCH" volumeGroup="patch">
<Attributes></Attributes>
</AttributesGroup>
</ProductStrategy>

@ -16,7 +16,7 @@
<!-- Volume section defines a volume curve for a given use case and device category.
It contains a list of points of this curve expressing the attenuation in Millibels for a given
volume index from 0 to 100.
<volume stream=”AUDIO_STREAM_MUSIC” deviceCategory=””>
<volume deviceCategory=””>
<point>0,-9600</point>
<point>100,0</point>
</volume>
@ -24,7 +24,7 @@ volume index from 0 to 100.
<volumeGroups>
<volumeGroup>
<stream>AUDIO_STREAM_VOICE_CALL</stream>
<name>voice_call</name>
<indexMin>1</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@ -50,7 +50,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_SYSTEM</stream>
<name>system</name>
<indexMin>0</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@ -73,7 +73,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_RING</stream>
<name>ring</name>
<indexMin>0</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_DEVICE_CATEGORY_HEADSET_VOLUME_CURVE"/>
@ -84,7 +84,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_MUSIC</stream>
<name>music</name>
<indexMin>0</indexMin>
<indexMax>25</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
@ -95,7 +95,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_ALARM</stream>
<name>alarm</name>
<indexMin>1</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_NON_MUTABLE_HEADSET_VOLUME_CURVE"/>
@ -106,7 +106,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_NOTIFICATION</stream>
<name>notification</name>
<indexMin>0</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_DEVICE_CATEGORY_HEADSET_VOLUME_CURVE"/>
@ -117,7 +117,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_BLUETOOTH_SCO</stream>
<name>bluetooth_sco</name>
<indexMin>0</indexMin>
<indexMax>15</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@ -143,7 +143,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_ENFORCED_AUDIBLE</stream>
<name>enforced_audible</name>
<indexMin>0</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@ -164,7 +164,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_DTMF</stream>
<name>dtmf</name>
<indexMin>0</indexMin>
<indexMax>15</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@ -185,7 +185,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_TTS</stream>
<name>tts</name>
<indexMin>0</indexMin>
<indexMax>15</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="SILENT_VOLUME_CURVE"/>
@ -196,7 +196,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_ACCESSIBILITY</stream>
<name>accessibility</name>
<indexMin>1</indexMin>
<indexMax>15</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_NON_MUTABLE_VOLUME_CURVE"/>
@ -207,7 +207,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_REROUTING</stream>
<name>rerouting</name>
<indexMin>0</indexMin>
<indexMax>1</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>
@ -218,7 +218,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_PATCH</stream>
<name>patch</name>
<indexMin>0</indexMin>
<indexMax>1</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>

@ -9,9 +9,9 @@ LOCAL_SRC_FILES := \
src/Engine.cpp \
src/EngineInstance.cpp \
../engine/common/src/VolumeCurve.cpp \
../engine/common/src/StreamVolumeCurves.cpp \
../engine/common/src/ProductStrategy.cpp \
../engine/common/src/EngineBase.cpp
../engine/common/src/EngineBase.cpp \
../engine/common/src/VolumeGroup.cpp
audio_policy_engine_includes_common := \
$(LOCAL_PATH)/include

@ -25,37 +25,37 @@
enforced. -->
<ProductStrategy name="STRATEGY_PHONE">
<AttributesGroup streamType="AUDIO_STREAM_VOICE_CALL">
<AttributesGroup streamType="AUDIO_STREAM_VOICE_CALL" volumeGroup="voice_call">
<Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION"/> </Attributes>
</AttributesGroup>
<AttributesGroup streamType="AUDIO_STREAM_BLUETOOTH_SCO">
<AttributesGroup streamType="AUDIO_STREAM_BLUETOOTH_SCO" volumeGroup="bluetooth_sco">
<Attributes> <Flags value="AUDIO_FLAG_SCO"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="STRATEGY_SONIFICATION">
<AttributesGroup streamType="AUDIO_STREAM_RING">
<AttributesGroup streamType="AUDIO_STREAM_RING" volumeGroup="ring">
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE"/> </Attributes>
</AttributesGroup>
<AttributesGroup streamType="AUDIO_STREAM_ALARM">
<AttributesGroup streamType="AUDIO_STREAM_ALARM" volumeGroup="alarm">
<Attributes> <Usage value="AUDIO_USAGE_ALARM"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="STRATEGY_ENFORCED_AUDIBLE">
<AttributesGroup streamType="AUDIO_STREAM_ENFORCED_AUDIBLE">
<AttributesGroup streamType="AUDIO_STREAM_ENFORCED_AUDIBLE" volumeGroup="enforced_audible">
<Attributes> <Flags value="AUDIO_FLAG_AUDIBILITY_ENFORCED"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="STRATEGY_ACCESSIBILITY">
<AttributesGroup streamType="AUDIO_STREAM_ACCESSIBILITY">
<AttributesGroup streamType="AUDIO_STREAM_ACCESSIBILITY" volumeGroup="accessibility">
<Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="STRATEGY_SONIFICATION_RESPECTFUL">
<AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION">
<AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION" volumeGroup="notification">
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/> </Attributes>
@ -65,20 +65,20 @@
</ProductStrategy>
<ProductStrategy name="STRATEGY_MEDIA">
<AttributesGroup streamType="AUDIO_STREAM_MUSIC">
<AttributesGroup streamType="AUDIO_STREAM_MUSIC" volumeGroup="music">
<Attributes> <Usage value="AUDIO_USAGE_MEDIA"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_GAME"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_ASSISTANT"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/> </Attributes>
<Attributes></Attributes>
</AttributesGroup>
<AttributesGroup streamType="AUDIO_STREAM_SYSTEM">
<AttributesGroup streamType="AUDIO_STREAM_SYSTEM" volumeGroup="system">
<Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="STRATEGY_DTMF">
<AttributesGroup streamType="AUDIO_STREAM_DTMF">
<AttributesGroup streamType="AUDIO_STREAM_DTMF" volumeGroup="dtmf">
<Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
@ -86,21 +86,21 @@
<!-- Used to identify the volume of audio streams exclusively transmitted through the speaker
(TTS) of the device -->
<ProductStrategy name="STRATEGY_TRANSMITTED_THROUGH_SPEAKER">
<AttributesGroup streamType="AUDIO_STREAM_TTS">
<AttributesGroup streamType="AUDIO_STREAM_TTS" volumeGroup="tts">
<Attributes> <Flags value="AUDIO_FLAG_BEACON"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<!-- Routing Strategy rerouting may be removed as following media??? -->
<ProductStrategy name="STRATEGY_REROUTING">
<AttributesGroup streamType="AUDIO_STREAM_REROUTING">
<AttributesGroup streamType="AUDIO_STREAM_REROUTING" volumeGroup="rerouting">
<Attributes></Attributes>
</AttributesGroup>
</ProductStrategy>
<!-- Default product strategy has empty attributes -->
<ProductStrategy name="STRATEGY_PATCH">
<AttributesGroup streamType="AUDIO_STREAM_PATCH">
<AttributesGroup streamType="AUDIO_STREAM_PATCH" volumeGroup="patch">
<Attributes></Attributes>
</AttributesGroup>
</ProductStrategy>

@ -16,7 +16,7 @@
<!-- Volume section defines a volume curve for a given use case and device category.
It contains a list of points of this curve expressing the attenuation in Millibels for a given
volume index from 0 to 100.
<volume stream=”AUDIO_STREAM_MUSIC” deviceCategory=””>
<volume deviceCategory=””>
<point>0,-9600</point>
<point>100,0</point>
</volume>
@ -24,7 +24,7 @@ volume index from 0 to 100.
<volumeGroups>
<volumeGroup>
<stream>AUDIO_STREAM_VOICE_CALL</stream>
<name>voice_call</name>
<indexMin>1</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@ -50,7 +50,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_SYSTEM</stream>
<name>system</name>
<indexMin>0</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@ -73,7 +73,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_RING</stream>
<name>ring</name>
<indexMin>0</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_DEVICE_CATEGORY_HEADSET_VOLUME_CURVE"/>
@ -84,7 +84,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_MUSIC</stream>
<name>music</name>
<indexMin>0</indexMin>
<indexMax>25</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
@ -95,7 +95,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_ALARM</stream>
<name>alarm</name>
<indexMin>1</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_NON_MUTABLE_HEADSET_VOLUME_CURVE"/>
@ -106,7 +106,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_NOTIFICATION</stream>
<name>notification</name>
<indexMin>0</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_DEVICE_CATEGORY_HEADSET_VOLUME_CURVE"/>
@ -117,7 +117,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_BLUETOOTH_SCO</stream>
<name>bluetooth_sco</name>
<indexMin>0</indexMin>
<indexMax>15</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@ -143,7 +143,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_ENFORCED_AUDIBLE</stream>
<name>enforced_audible</name>
<indexMin>0</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@ -164,7 +164,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_DTMF</stream>
<name>dtmf</name>
<indexMin>0</indexMin>
<indexMax>15</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@ -185,7 +185,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_TTS</stream>
<name>tts</name>
<indexMin>0</indexMin>
<indexMax>15</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="SILENT_VOLUME_CURVE"/>
@ -196,7 +196,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_ACCESSIBILITY</stream>
<name>accessibility</name>
<indexMin>1</indexMin>
<indexMax>15</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_NON_MUTABLE_VOLUME_CURVE"/>
@ -207,7 +207,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_REROUTING</stream>
<name>rerouting</name>
<indexMin>0</indexMin>
<indexMax>1</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>
@ -218,7 +218,7 @@ volume index from 0 to 100.
</volumeGroup>
<volumeGroup>
<stream>AUDIO_STREAM_PATCH</stream>
<name>patch</name>
<indexMin>0</indexMin>
<indexMax>1</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>

@ -377,7 +377,7 @@ audio_policy_dev_state_t AudioPolicyManager::getDeviceConnectionState(audio_devi
(strlen(device_address) != 0)/*matchAddress*/);
if (devDesc == 0) {
ALOGW("getDeviceConnectionState() undeclared device, type %08x, address: %s",
ALOGV("getDeviceConnectionState() undeclared device, type %08x, address: %s",
device, device_address);
return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
}
@ -2373,16 +2373,13 @@ void AudioPolicyManager::closeAllInputs() {
}
}
void AudioPolicyManager::initStreamVolume(audio_stream_type_t stream,
int indexMin,
int indexMax)
void AudioPolicyManager::initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax)
{
ALOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
if (indexMin < 0 || indexMax < 0) {
ALOGE("%s for stream %d: invalid min %d or max %d", __func__, stream , indexMin, indexMax);
return;
}
// @todo: our proposal now use XML to store Indexes Min & Max
getVolumeCurves(stream).initVolume(indexMin, indexMax);
// initialize other private stream volumes which follow this one

@ -143,9 +143,17 @@ public:
virtual status_t stopInput(audio_port_handle_t portId);
virtual void releaseInput(audio_port_handle_t portId);
virtual void closeAllInputs();
virtual void initStreamVolume(audio_stream_type_t stream,
int indexMin,
int indexMax);
/**
* @brief initStreamVolume: even if the engine volume files provides min and max, keep this
* api for compatibility reason.
* AudioServer will get the min and max and may overwrite them if:
* -using property (highest priority)
* -not defined (-1 by convention), case when still using apm volume tables XML files
* @param stream to be considered
* @param indexMin to set
* @param indexMax to set
*/
virtual void initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax);
virtual status_t setStreamVolumeIndex(audio_stream_type_t stream,
int index,
audio_devices_t device);

Loading…
Cancel
Save