Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "APM::AudioPolicyEngine/ProductStrategy"
     18 //#define LOG_NDEBUG 0
     19 
     20 #include "ProductStrategy.h"
     21 
     22 #include <media/TypeConverter.h>
     23 #include <utils/String8.h>
     24 #include <cstdint>
     25 #include <string>
     26 
     27 #include <log/log.h>
     28 
     29 
     30 namespace android {
     31 
     32 ProductStrategy::ProductStrategy(const std::string &name) :
     33     mName(name),
     34     mId(static_cast<product_strategy_t>(HandleGenerator<uint32_t>::getNextHandle()))
     35 {
     36 }
     37 
     38 void ProductStrategy::addAttributes(const AudioAttributes &audioAttributes)
     39 {
     40     mAttributesVector.push_back(audioAttributes);
     41 }
     42 
     43 std::vector<android::AudioAttributes> ProductStrategy::listAudioAttributes() const
     44 {
     45     std::vector<android::AudioAttributes> androidAa;
     46     for (const auto &attr : mAttributesVector) {
     47         androidAa.push_back({attr.mVolumeGroup, attr.mStream, attr.mAttributes});
     48     }
     49     return androidAa;
     50 }
     51 
     52 AttributesVector ProductStrategy::getAudioAttributes() const
     53 {
     54     AttributesVector attrVector;
     55     for (const auto &attrGroup : mAttributesVector) {
     56         attrVector.push_back(attrGroup.mAttributes);
     57     }
     58     if (not attrVector.empty()) {
     59         return attrVector;
     60     }
     61     return { AUDIO_ATTRIBUTES_INITIALIZER };
     62 }
     63 
     64 bool ProductStrategy::matches(const audio_attributes_t attr) const
     65 {
     66     return std::find_if(begin(mAttributesVector), end(mAttributesVector),
     67                         [&attr](const auto &supportedAttr) {
     68         return AudioProductStrategy::attributesMatches(supportedAttr.mAttributes, attr);
     69     }) != end(mAttributesVector);
     70 }
     71 
     72 audio_stream_type_t ProductStrategy::getStreamTypeForAttributes(
     73         const audio_attributes_t &attr) const
     74 {
     75     const auto iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
     76                                    [&attr](const auto &supportedAttr) {
     77         return AudioProductStrategy::attributesMatches(supportedAttr.mAttributes, attr); });
     78     return iter != end(mAttributesVector) ? iter->mStream : AUDIO_STREAM_DEFAULT;
     79 }
     80 
     81 audio_attributes_t ProductStrategy::getAttributesForStreamType(audio_stream_type_t streamType) const
     82 {
     83     const auto iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
     84                                    [&streamType](const auto &supportedAttr) {
     85         return supportedAttr.mStream == streamType; });
     86     return iter != end(mAttributesVector) ? iter->mAttributes : AUDIO_ATTRIBUTES_INITIALIZER;
     87 }
     88 
     89 bool ProductStrategy::isDefault() const
     90 {
     91     return std::find_if(begin(mAttributesVector), end(mAttributesVector), [](const auto &attr) {
     92         return attr.mAttributes == defaultAttr; }) != end(mAttributesVector);
     93 }
     94 
     95 StreamTypeVector ProductStrategy::getSupportedStreams() const
     96 {
     97     StreamTypeVector streams;
     98     for (const auto &supportedAttr : mAttributesVector) {
     99         if (std::find(begin(streams), end(streams), supportedAttr.mStream) == end(streams) &&
    100                 supportedAttr.mStream != AUDIO_STREAM_DEFAULT) {
    101             streams.push_back(supportedAttr.mStream);
    102         }
    103     }
    104     return streams;
    105 }
    106 
    107 bool ProductStrategy::supportStreamType(const audio_stream_type_t &streamType) const
    108 {
    109     return std::find_if(begin(mAttributesVector), end(mAttributesVector),
    110                         [&streamType](const auto &supportedAttr) {
    111         return supportedAttr.mStream == streamType; }) != end(mAttributesVector);
    112 }
    113 
    114 volume_group_t ProductStrategy::getVolumeGroupForAttributes(const audio_attributes_t &attr) const
    115 {
    116     for (const auto &supportedAttr : mAttributesVector) {
    117         if (AudioProductStrategy::attributesMatches(supportedAttr.mAttributes, attr)) {
    118             return supportedAttr.mVolumeGroup;
    119         }
    120     }
    121     return VOLUME_GROUP_NONE;
    122 }
    123 
    124 volume_group_t ProductStrategy::getVolumeGroupForStreamType(audio_stream_type_t stream) const
    125 {
    126     for (const auto &supportedAttr : mAttributesVector) {
    127         if (supportedAttr.mStream == stream) {
    128             return supportedAttr.mVolumeGroup;
    129         }
    130     }
    131     return VOLUME_GROUP_NONE;
    132 }
    133 
    134 volume_group_t ProductStrategy::getDefaultVolumeGroup() const
    135 {
    136     const auto &iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
    137                                     [](const auto &attr) {return attr.mAttributes == defaultAttr;});
    138     return iter != end(mAttributesVector) ? iter->mVolumeGroup : VOLUME_GROUP_NONE;
    139 }
    140 
    141 void ProductStrategy::dump(String8 *dst, int spaces) const
    142 {
    143     dst->appendFormat("\n%*s-%s (id: %d)\n", spaces, "", mName.c_str(), mId);
    144     std::string deviceLiteral;
    145     if (!OutputDeviceConverter::toString(mApplicableDevices, deviceLiteral)) {
    146         ALOGE("%s: failed to convert device %d", __FUNCTION__, mApplicableDevices);
    147     }
    148     dst->appendFormat("%*sSelected Device: {type:%s, @:%s}\n", spaces + 2, "",
    149                        deviceLiteral.c_str(), mDeviceAddress.c_str());
    150 
    151     for (const auto &attr : mAttributesVector) {
    152         dst->appendFormat("%*sGroup: %d stream: %s\n", spaces + 3, "", attr.mVolumeGroup,
    153                           android::toString(attr.mStream).c_str());
    154         dst->appendFormat("%*s Attributes: ", spaces + 3, "");
    155         std::string attStr =
    156                 attr.mAttributes == defaultAttr ? "{ Any }" : android::toString(attr.mAttributes);
    157         dst->appendFormat("%s\n", attStr.c_str());
    158     }
    159 }
    160 
    161 product_strategy_t ProductStrategyMap::getProductStrategyForAttributes(
    162         const audio_attributes_t &attr) const
    163 {
    164     for (const auto &iter : *this) {
    165         if (iter.second->matches(attr)) {
    166             return iter.second->getId();
    167         }
    168     }
    169     ALOGV("%s: No matching product strategy for attributes %s, return default", __FUNCTION__,
    170           toString(attr).c_str());
    171     return getDefault();
    172 }
    173 
    174 audio_attributes_t ProductStrategyMap::getAttributesForStreamType(audio_stream_type_t stream) const
    175 {
    176     for (const auto &iter : *this) {
    177         const auto strategy = iter.second;
    178         if (strategy->supportStreamType(stream)) {
    179             return strategy->getAttributesForStreamType(stream);
    180         }
    181     }
    182     ALOGV("%s: No product strategy for stream %s, using default", __FUNCTION__,
    183           toString(stream).c_str());
    184     return {};
    185 }
    186 
    187 audio_stream_type_t ProductStrategyMap::getStreamTypeForAttributes(
    188         const audio_attributes_t &attr) const
    189 {
    190     for (const auto &iter : *this) {
    191         audio_stream_type_t stream = iter.second->getStreamTypeForAttributes(attr);
    192         if (stream != AUDIO_STREAM_DEFAULT) {
    193             return stream;
    194         }
    195     }
    196     ALOGV("%s: No product strategy for attributes %s, using default (aka MUSIC)", __FUNCTION__,
    197           toString(attr).c_str());
    198     return  AUDIO_STREAM_MUSIC;
    199 }
    200 
    201 product_strategy_t ProductStrategyMap::getDefault() const
    202 {
    203     if (mDefaultStrategy != PRODUCT_STRATEGY_NONE) {
    204         return mDefaultStrategy;
    205     }
    206     for (const auto &iter : *this) {
    207         if (iter.second->isDefault()) {
    208             ALOGV("%s: using default %s", __FUNCTION__, iter.second->getName().c_str());
    209             return iter.second->getId();
    210         }
    211     }
    212     ALOGE("%s: No default product strategy defined", __FUNCTION__);
    213     return PRODUCT_STRATEGY_NONE;
    214 }
    215 
    216 audio_attributes_t ProductStrategyMap::getAttributesForProductStrategy(
    217         product_strategy_t strategy) const
    218 {
    219     if (find(strategy) == end()) {
    220         ALOGE("Invalid %d strategy requested", strategy);
    221         return AUDIO_ATTRIBUTES_INITIALIZER;
    222     }
    223     return at(strategy)->getAudioAttributes()[0];
    224 }
    225 
    226 product_strategy_t ProductStrategyMap::getProductStrategyForStream(audio_stream_type_t stream) const
    227 {
    228     for (const auto &iter : *this) {
    229         if (iter.second->supportStreamType(stream)) {
    230             return iter.second->getId();
    231         }
    232     }
    233     ALOGV("%s: No product strategy for stream %d, using default", __FUNCTION__, stream);
    234     return getDefault();
    235 }
    236 
    237 
    238 audio_devices_t ProductStrategyMap::getDeviceTypesForProductStrategy(
    239         product_strategy_t strategy) const
    240 {
    241     if (find(strategy) == end()) {
    242         ALOGE("Invalid %d strategy requested, returning device for default strategy", strategy);
    243         product_strategy_t defaultStrategy = getDefault();
    244         if (defaultStrategy == PRODUCT_STRATEGY_NONE) {
    245             return AUDIO_DEVICE_NONE;
    246         }
    247         return at(getDefault())->getDeviceTypes();
    248     }
    249     return at(strategy)->getDeviceTypes();
    250 }
    251 
    252 std::string ProductStrategyMap::getDeviceAddressForProductStrategy(product_strategy_t psId) const
    253 {
    254     if (find(psId) == end()) {
    255         ALOGE("Invalid %d strategy requested, returning device for default strategy", psId);
    256         product_strategy_t defaultStrategy = getDefault();
    257         if (defaultStrategy == PRODUCT_STRATEGY_NONE) {
    258             return {};
    259         }
    260         return at(getDefault())->getDeviceAddress();
    261     }
    262     return at(psId)->getDeviceAddress();
    263 }
    264 
    265 volume_group_t ProductStrategyMap::getVolumeGroupForAttributes(const audio_attributes_t &attr) const
    266 {
    267     for (const auto &iter : *this) {
    268         volume_group_t group = iter.second->getVolumeGroupForAttributes(attr);
    269         if (group != VOLUME_GROUP_NONE) {
    270             return group;
    271         }
    272     }
    273     return getDefaultVolumeGroup();
    274 }
    275 
    276 volume_group_t ProductStrategyMap::getVolumeGroupForStreamType(audio_stream_type_t stream) const
    277 {
    278     for (const auto &iter : *this) {
    279         volume_group_t group = iter.second->getVolumeGroupForStreamType(stream);
    280         if (group != VOLUME_GROUP_NONE) {
    281             return group;
    282         }
    283     }
    284     ALOGW("%s: no volume group for %s, using default", __func__, toString(stream).c_str());
    285     return getDefaultVolumeGroup();
    286 }
    287 
    288 volume_group_t ProductStrategyMap::getDefaultVolumeGroup() const
    289 {
    290     product_strategy_t defaultStrategy = getDefault();
    291     if (defaultStrategy == PRODUCT_STRATEGY_NONE) {
    292         return VOLUME_GROUP_NONE;
    293     }
    294     return at(defaultStrategy)->getDefaultVolumeGroup();
    295 }
    296 
    297 void ProductStrategyMap::initialize()
    298 {
    299     mDefaultStrategy = getDefault();
    300     ALOG_ASSERT(mDefaultStrategy != PRODUCT_STRATEGY_NONE, "No default product strategy found");
    301 }
    302 
    303 void ProductStrategyMap::dump(String8 *dst, int spaces) const
    304 {
    305     dst->appendFormat("%*sProduct Strategies dump:", spaces, "");
    306     for (const auto &iter : *this) {
    307         iter.second->dump(dst, spaces + 2);
    308     }
    309 }
    310 
    311 }
    312 
    313