diff --git a/media/libaudioclient/AudioAttributes.cpp b/media/libaudioclient/AudioAttributes.cpp index 0f327cf3b6..1ee6930fbc 100644 --- a/media/libaudioclient/AudioAttributes.cpp +++ b/media/libaudioclient/AudioAttributes.cpp @@ -43,7 +43,7 @@ status_t AudioAttributes::readFromParcel(const Parcel *parcel) strcpy(mAttributes.tags, ""); } mStreamType = static_cast(parcel->readInt32()); - mGroupId = parcel->readUint32(); + mGroupId = static_cast(parcel->readUint32()); return NO_ERROR; } @@ -60,7 +60,7 @@ status_t AudioAttributes::writeToParcel(Parcel *parcel) const parcel->writeUtf8AsUtf16(mAttributes.tags); } parcel->writeInt32(static_cast(mStreamType)); - parcel->writeUint32(mGroupId); + parcel->writeUint32(static_cast(mGroupId)); return NO_ERROR; } diff --git a/media/libaudioclient/include/media/AudioAttributes.h b/media/libaudioclient/include/media/AudioAttributes.h index edf26ebe7c..0a35e9e89d 100644 --- a/media/libaudioclient/include/media/AudioAttributes.h +++ b/media/libaudioclient/include/media/AudioAttributes.h @@ -17,6 +17,7 @@ #pragma once +#include #include #include #include @@ -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 diff --git a/media/libaudioclient/include/media/AudioCommonTypes.h b/media/libaudioclient/include/media/AudioCommonTypes.h index 5188da1fd3..8e446ea48c 100644 --- a/media/libaudioclient/include/media/AudioCommonTypes.h +++ b/media/libaudioclient/include/media/AudioCommonTypes.h @@ -27,7 +27,7 @@ enum product_strategy_t : uint32_t; const product_strategy_t PRODUCT_STRATEGY_NONE = static_cast(-1); using AttributesVector = std::vector; -using StreamTypes = std::vector; +using StreamTypeVector = std::vector; 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(-1); + } // namespace android diff --git a/services/audiopolicy/common/include/Volume.h b/services/audiopolicy/common/include/Volume.h index a3b6b36fd2..48b5271932 100644 --- a/services/audiopolicy/common/include/Volume.h +++ b/services/audiopolicy/common/include/Volume.h @@ -21,6 +21,7 @@ #include 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 diff --git a/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h b/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h index 93022fb2a0..d408446f62 100644 --- a/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h +++ b/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h @@ -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 getAttributes() const = 0; + virtual std::vector getStreamTypes() const = 0; virtual void dump(String8 *dst, int spaces = 0, bool curvePoints = false) const = 0; }; diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp index e0b233d18c..ec7ff572da 100644 --- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp @@ -341,7 +341,7 @@ sp 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; } diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h index bc027e2a3f..35d86ee665 100644 --- a/services/audiopolicy/engine/common/include/EngineBase.h +++ b/services/audiopolicy/engine/common/include/EngineBase.h @@ -19,7 +19,7 @@ #include #include #include -#include +#include 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 diff --git a/services/audiopolicy/engine/common/include/ProductStrategy.h b/services/audiopolicy/engine/common/include/ProductStrategy.h index 72505b29aa..767a8ed583 100644 --- a/services/audiopolicy/engine/common/include/ProductStrategy.h +++ b/services/audiopolicy/engine/common/include/ProductStrategy.h @@ -16,6 +16,8 @@ #pragma once +#include "VolumeGroup.h" + #include #include #include @@ -38,7 +40,7 @@ class ProductStrategy : public virtual RefBase, private HandleGenerator > { 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 diff --git a/services/audiopolicy/engine/common/include/StreamVolumeCurves.h b/services/audiopolicy/engine/common/include/StreamVolumeCurves.h deleted file mode 100644 index 5b0b7d6272..0000000000 --- a/services/audiopolicy/engine/common/include/StreamVolumeCurves.h +++ /dev/null @@ -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 -#include - -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 mCurves; -}; - -} // namespace android diff --git a/services/audiopolicy/engine/common/include/VolumeCurve.h b/services/audiopolicy/engine/common/include/VolumeCurve.h index 0ec63e19fc..54314e3a03 100644 --- a/services/audiopolicy/engine/common/include/VolumeCurve.h +++ b/services/audiopolicy/engine/common/include/VolumeCurve.h @@ -18,7 +18,9 @@ #include "IVolumeCurves.h" #include +#include #include +#include #include #include #include @@ -71,18 +73,11 @@ class VolumeCurves : public KeyedVector >, { 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 diff --git a/services/audiopolicy/engine/common/include/VolumeGroup.h b/services/audiopolicy/engine/common/include/VolumeGroup.h new file mode 100644 index 0000000000..c34b4062ff --- /dev/null +++ b/services/audiopolicy/engine/common/include/VolumeGroup.h @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +class VolumeGroup : public virtual RefBase, private HandleGenerator +{ +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 &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 > +{ +public: + void dump(String8 *dst, int spaces = 0) const; +}; + +} // namespace android diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp index 6e2ab4cdfa..4d7c4a05bb 100644 --- a/services/audiopolicy/engine/common/src/EngineBase.cpp +++ b/services/audiopolicy/engine/common/src/EngineBase.cpp @@ -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 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 = 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 curve = new VolumeCurve(deviceCategory); + sp 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(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 diff --git a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h index f1642c5e3c..fede0d93de 100644 --- a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h +++ b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h @@ -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, ""}} } }, diff --git a/services/audiopolicy/engine/common/src/ProductStrategy.cpp b/services/audiopolicy/engine/common/src/ProductStrategy.cpp index 71607d1be4..16e6690a58 100644 --- a/services/audiopolicy/engine/common/src/ProductStrategy.cpp +++ b/services/audiopolicy/engine/common/src/ProductStrategy.cpp @@ -44,7 +44,7 @@ std::vector ProductStrategy::listAudioAttributes() con { std::vector 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, ""); diff --git a/services/audiopolicy/engine/common/src/StreamVolumeCurves.cpp b/services/audiopolicy/engine/common/src/StreamVolumeCurves.cpp deleted file mode 100644 index fe3b0007b6..0000000000 --- a/services/audiopolicy/engine/common/src/StreamVolumeCurves.cpp +++ /dev/null @@ -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 - -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 diff --git a/services/audiopolicy/engine/common/src/VolumeCurve.cpp b/services/audiopolicy/engine/common/src/VolumeCurve.cpp index be2ca730ef..c352578d5c 100644 --- a/services/audiopolicy/engine/common/src/VolumeCurve.cpp +++ b/services/audiopolicy/engine/common/src/VolumeCurve.cpp @@ -19,13 +19,17 @@ #include "VolumeCurve.h" #include "TypeConverter.h" +#include 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); } } diff --git a/services/audiopolicy/engine/common/src/VolumeGroup.cpp b/services/audiopolicy/engine/common/src/VolumeGroup.cpp new file mode 100644 index 0000000000..e1898070cb --- /dev/null +++ b/services/audiopolicy/engine/common/src/VolumeGroup.cpp @@ -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 +#include +#include +#include + +#include + + +namespace android { + +// +// VolumeGroup implementation +// +VolumeGroup::VolumeGroup(const std::string &name, int indexMin, int indexMax) : + mName(name), mId(static_cast(HandleGenerator::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 &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 + diff --git a/services/audiopolicy/engine/config/include/EngineConfig.h b/services/audiopolicy/engine/config/include/EngineConfig.h index a188115fff..7f5ed5eb9d 100644 --- a/services/audiopolicy/engine/config/include/EngineConfig.h +++ b/services/audiopolicy/engine/config/include/EngineConfig.h @@ -40,6 +40,7 @@ using StreamVector = std::vector; struct AttributesGroup { std::string name; audio_stream_type_t stream; + std::string volumeGroup; AttributesVector attributesVect; }; @@ -59,7 +60,6 @@ using VolumeCurves = std::vector; struct VolumeGroup { std::string name; - std::string stream; int indexMin; int indexMax; VolumeCurves volumeCurves; diff --git a/services/audiopolicy/engine/config/src/EngineConfig.cpp b/services/audiopolicy/engine/config/src/EngineConfig.cpp index 00fbac411b..1ad773939a 100644 --- a/services/audiopolicy/engine/config/src/EngineConfig.cpp +++ b/services/audiopolicy/engine/config/src/EngineConfig.cpp @@ -59,6 +59,7 @@ struct AttributesGroupTraits : public BaseSerializerTraits { 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; -using xmlCharUnique = std::unique_ptr; - std::string getXmlAttribute(const xmlNode *cur, const char *attribute) { xmlCharUnique charPtr(xmlGetProp(cur, reinterpret_cast(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(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(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(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; } diff --git a/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h b/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h index c9e9507705..07acd2e5a7 100644 --- a/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h +++ b/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h @@ -32,7 +32,7 @@ namespace android { using DeviceStrategyMap = std::map; using StrategyVector = std::vector; - +using VolumeGroupVector = std::vector; /** * 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; diff --git a/services/audiopolicy/engineconfigurable/Android.mk b/services/audiopolicy/engineconfigurable/Android.mk index 2b7e4c8dbc..4eff6e64d6 100644 --- a/services/audiopolicy/engineconfigurable/Android.mk +++ b/services/audiopolicy/engineconfigurable/Android.mk @@ -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 diff --git a/services/audiopolicy/engineconfigurable/config/example/Android.mk b/services/audiopolicy/engineconfigurable/config/example/Android.mk index ef476f765c..45419f04b1 100644 --- a/services/audiopolicy/engineconfigurable/config/example/Android.mk +++ b/services/audiopolicy/engineconfigurable/config/example/Android.mk @@ -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)) diff --git a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_configuration.xml b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_configuration.xml index e2fb02b140..28a140a957 100644 --- a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_configuration.xml +++ b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_configuration.xml @@ -19,6 +19,7 @@ + diff --git a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml index 543a2f0971..c487da9e24 100644 --- a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml +++ b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml @@ -31,7 +31,7 @@ limitations under the License. --> - + @@ -39,14 +39,14 @@ limitations under the License. - + - + @@ -70,21 +70,21 @@ limitations under the License. ( type == CAR_AUDIO_TYPE_RADIO ) ) --> - + - + - + @@ -96,7 +96,7 @@ limitations under the License. - + @@ -112,7 +112,7 @@ limitations under the License. - + @@ -121,29 +121,31 @@ limitations under the License. - + - + + + - + - + - + @@ -152,10 +154,17 @@ limitations under the License. - + - + + + + + + diff --git a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml new file mode 100644 index 0000000000..b326b50de3 --- /dev/null +++ b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml @@ -0,0 +1,192 @@ + + + + + + + + + oem_traffic_anouncement + 0 + 40 + + 0,-4200 + 33,-2800 + 66,-1400 + 100,0 + + + 0,-4200 + 33,-2800 + 66,-1400 + 100,0 + + + 0,-4200 + 33,-2800 + 66,-1400 + 100,0 + + + 0,-4200 + 33,-2800 + 66,-1400 + 100,0 + + + + + + oem_adas_2 + 0 + 40 + + 0,-4200 + 33,-2800 + 66,-1400 + 100,0 + + + 0,-4200 + 33,-2800 + 66,-1400 + 100,0 + + + + oem_adas_3 + 0 + 40 + + 0,-2400 + 33,-1600 + 66,-800 + 100,0 + + + 0,-2400 + 33,-1600 + 66,-800 + 100,0 + + + + + + media_car_audio_type_3 + 0 + 40 + + 0,-4200 + 33,-2800 + 66,-1400 + 100,0 + + + + media_car_audio_type_7 + 0 + 40 + + 0,-2400 + 33,-1600 + 66,-800 + 100,0 + + + + media + 0 + 40 + + 0,-2400 + 33,-1600 + 66,-800 + 100,0 + + + + + speech + 1 + 40 + + 0,-4200 + 33,-2800 + 66,-1400 + 100,0 + + + + + system + 0 + 40 + + 0,-4200 + 33,-2800 + 66,-1400 + 100,0 + + + + + phone + 1 + 40 + + 0,-4200 + 33,-2800 + 66,-1400 + 100,0 + + + + + ring + 0 + 40 + + 0,-4200 + 33,-2800 + 66,-1400 + 100,0 + + + + + tts + 0 + 15 + + 0,-0 + 100,0 + + + + diff --git a/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_product_strategies.xml b/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_product_strategies.xml index f72e37916d..939874353a 100644 --- a/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_product_strategies.xml +++ b/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_product_strategies.xml @@ -25,37 +25,37 @@ enforced. --> - + - + - + - + - + - + - + @@ -65,20 +65,20 @@ - + - + - + @@ -86,21 +86,21 @@ - + - + - + diff --git a/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_stream_volumes.xml b/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_stream_volumes.xml index 73bde1fb7e..707a18471c 100644 --- a/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_stream_volumes.xml +++ b/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_stream_volumes.xml @@ -16,7 +16,7 @@ - + - + - + - + - + - + - + @@ -65,20 +65,20 @@ - + - + - + @@ -86,21 +86,21 @@ - + - + - + diff --git a/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_stream_volumes.xml b/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_stream_volumes.xml index 73bde1fb7e..707a18471c 100644 --- a/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_stream_volumes.xml +++ b/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_stream_volumes.xml @@ -16,7 +16,7 @@