Home | History | Annotate | Download | only in wrapper
      1 /*
      2  * Copyright (C) 2015 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/PFWWrapper"
     18 //#define LOG_NDEBUG 0
     19 
     20 #include "ParameterManagerWrapper.h"
     21 #include "audio_policy_criteria_conf.h"
     22 #include <ParameterMgrPlatformConnector.h>
     23 #include <SelectionCriterionTypeInterface.h>
     24 #include <SelectionCriterionInterface.h>
     25 #include <media/convert.h>
     26 #include <algorithm>
     27 #include <cutils/config_utils.h>
     28 #include <cutils/misc.h>
     29 #include <fstream>
     30 #include <limits>
     31 #include <sstream>
     32 #include <string>
     33 #include <vector>
     34 #include <stdint.h>
     35 #include <cmath>
     36 #include <utils/Log.h>
     37 
     38 using std::string;
     39 using std::map;
     40 using std::vector;
     41 
     42 /// PFW related definitions
     43 // Logger
     44 class ParameterMgrPlatformConnectorLogger : public CParameterMgrPlatformConnector::ILogger
     45 {
     46 public:
     47     ParameterMgrPlatformConnectorLogger() {}
     48 
     49     virtual void info(const string &log)
     50     {
     51         ALOGV("policy-parameter-manager: %s", log.c_str());
     52     }
     53     virtual void warning(const string &log)
     54     {
     55         ALOGW("policy-parameter-manager: %s", log.c_str());
     56     }
     57 };
     58 
     59 namespace android
     60 {
     61 
     62 using utilities::convertTo;
     63 
     64 namespace audio_policy
     65 {
     66 const char *const ParameterManagerWrapper::mPolicyPfwDefaultConfFileName =
     67     "/etc/parameter-framework/ParameterFrameworkConfigurationPolicy.xml";
     68 
     69 template <>
     70 struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionInterface> {};
     71 template <>
     72 struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionTypeInterface> {};
     73 
     74 ParameterManagerWrapper::ParameterManagerWrapper()
     75     : mPfwConnectorLogger(new ParameterMgrPlatformConnectorLogger)
     76 {
     77     // Connector
     78     mPfwConnector = new CParameterMgrPlatformConnector(mPolicyPfwDefaultConfFileName);
     79 
     80     // Logger
     81     mPfwConnector->setLogger(mPfwConnectorLogger);
     82 
     83     // Load criteria file
     84     if ((loadAudioPolicyCriteriaConfig(gAudioPolicyCriteriaVendorConfFilePath) != NO_ERROR) &&
     85         (loadAudioPolicyCriteriaConfig(gAudioPolicyCriteriaConfFilePath) != NO_ERROR)) {
     86         ALOGE("%s: Neither vendor conf file (%s) nor system conf file (%s) could be found",
     87               __FUNCTION__, gAudioPolicyCriteriaVendorConfFilePath,
     88               gAudioPolicyCriteriaConfFilePath);
     89     }
     90 }
     91 
     92 ParameterManagerWrapper::~ParameterManagerWrapper()
     93 {
     94     // Unset logger
     95     mPfwConnector->setLogger(NULL);
     96     // Remove logger
     97     delete mPfwConnectorLogger;
     98     // Remove connector
     99     delete mPfwConnector;
    100 }
    101 
    102 status_t ParameterManagerWrapper::start()
    103 {
    104     ALOGD("%s: in", __FUNCTION__);
    105     /// Start PFW
    106     std::string error;
    107     if (!mPfwConnector->start(error)) {
    108         ALOGE("%s: Policy PFW start error: %s", __FUNCTION__, error.c_str());
    109         return NO_INIT;
    110     }
    111     ALOGD("%s: Policy PFW successfully started!", __FUNCTION__);
    112     return NO_ERROR;
    113 }
    114 
    115 
    116 void ParameterManagerWrapper::addCriterionType(const string &typeName, bool isInclusive)
    117 {
    118     ALOG_ASSERT(mPolicyCriterionTypes.find(typeName) == mPolicyCriterionTypes.end(),
    119                       "CriterionType %s already added", typeName.c_str());
    120     ALOGD("%s: Adding new criterionType %s", __FUNCTION__, typeName.c_str());
    121 
    122     mPolicyCriterionTypes[typeName] = mPfwConnector->createSelectionCriterionType(isInclusive);
    123 }
    124 
    125 void ParameterManagerWrapper::addCriterionTypeValuePair(
    126     const string &typeName,
    127     uint32_t numericValue,
    128     const string &literalValue)
    129 {
    130     ALOG_ASSERT(mPolicyCriterionTypes.find(typeName) != mPolicyCriterionTypes.end(),
    131                       "CriterionType %s not found", typeName.c_str());
    132     ALOGV("%s: Adding new value pair (%d,%s) for criterionType %s", __FUNCTION__,
    133           numericValue, literalValue.c_str(), typeName.c_str());
    134     ISelectionCriterionTypeInterface *criterionType = mPolicyCriterionTypes[typeName];
    135     std::string error;
    136     criterionType->addValuePair(numericValue, literalValue, error);
    137 }
    138 
    139 void ParameterManagerWrapper::loadCriterionType(cnode *root, bool isInclusive)
    140 {
    141     ALOG_ASSERT(root != NULL, "error in parsing file");
    142     cnode *node;
    143     for (node = root->first_child; node != NULL; node = node->next) {
    144 
    145         ALOG_ASSERT(node != NULL, "error in parsing file");
    146         const char *typeName = node->name;
    147         char *valueNames = strndup(node->value, strlen(node->value));
    148 
    149         addCriterionType(typeName, isInclusive);
    150 
    151         uint32_t index = 0;
    152         char *ctx;
    153         char *valueName = strtok_r(valueNames, ",", &ctx);
    154         while (valueName != NULL) {
    155             if (strlen(valueName) != 0) {
    156 
    157                 // Conf file may use or not pair, if no pair, use incremental index, else
    158                 // use provided index.
    159                 if (strchr(valueName, ':') != NULL) {
    160 
    161                     char *first = strtok(valueName, ":");
    162                     char *second = strtok(NULL, ":");
    163                     ALOG_ASSERT((first != NULL) && (strlen(first) != 0) &&
    164                                       (second != NULL) && (strlen(second) != 0),
    165                                       "invalid value pair");
    166 
    167                     if (!convertTo<string, uint32_t>(first, index)) {
    168                         ALOGE("%s: Invalid index(%s) found", __FUNCTION__, first);
    169                     }
    170                     addCriterionTypeValuePair(typeName, index, second);
    171                 } else {
    172 
    173                     uint32_t pfwIndex = isInclusive ? 1 << index : index;
    174                     addCriterionTypeValuePair(typeName, pfwIndex, valueName);
    175                     index += 1;
    176                 }
    177             }
    178             valueName = strtok_r(NULL, ",", &ctx);
    179         }
    180         free(valueNames);
    181     }
    182 }
    183 
    184 void ParameterManagerWrapper::loadInclusiveCriterionType(cnode *root)
    185 {
    186     ALOG_ASSERT(root != NULL, "error in parsing file");
    187     cnode *node = config_find(root, gInclusiveCriterionTypeTag.c_str());
    188     if (node == NULL) {
    189         return;
    190     }
    191     loadCriterionType(node, true);
    192 }
    193 
    194 void ParameterManagerWrapper::loadExclusiveCriterionType(cnode *root)
    195 {
    196     ALOG_ASSERT(root != NULL, "error in parsing file");
    197     cnode *node = config_find(root, gExclusiveCriterionTypeTag.c_str());
    198     if (node == NULL) {
    199         return;
    200     }
    201     loadCriterionType(node, false);
    202 }
    203 
    204 void ParameterManagerWrapper::parseChildren(cnode *root, string &defaultValue, string &type)
    205 {
    206     ALOG_ASSERT(root != NULL, "error in parsing file");
    207     cnode *node;
    208     for (node = root->first_child; node != NULL; node = node->next) {
    209         ALOG_ASSERT(node != NULL, "error in parsing file");
    210 
    211         if (string(node->name) == gDefaultTag) {
    212             defaultValue = node->value;
    213         } else if (string(node->name) == gTypeTag) {
    214             type = node->value;
    215         } else {
    216              ALOGE("%s: Unrecognized %s %s node", __FUNCTION__, node->name, node->value);
    217         }
    218     }
    219 }
    220 
    221 template <typename T>
    222 T *ParameterManagerWrapper::getElement(const string &name, std::map<string, T *> &elementsMap)
    223 {
    224     parameterManagerElementSupported<T>();
    225     typename std::map<string, T *>::iterator it = elementsMap.find(name);
    226     ALOG_ASSERT(it != elementsMap.end(), "Element %s not found", name.c_str());
    227     return it != elementsMap.end() ? it->second : NULL;
    228 }
    229 
    230 template <typename T>
    231 const T *ParameterManagerWrapper::getElement(const string &name, const std::map<string, T *> &elementsMap) const
    232 {
    233     parameterManagerElementSupported<T>();
    234     typename std::map<string, T *>::const_iterator it = elementsMap.find(name);
    235     ALOG_ASSERT(it != elementsMap.end(), "Element %s not found", name.c_str());
    236     return it != elementsMap.end() ? it->second : NULL;
    237 }
    238 
    239 void ParameterManagerWrapper::loadCriteria(cnode *root)
    240 {
    241     ALOG_ASSERT(root != NULL, "error in parsing file");
    242     cnode *node = config_find(root, gCriterionTag.c_str());
    243 
    244     if (node == NULL) {
    245         ALOGW("%s: no inclusive criteria found", __FUNCTION__);
    246         return;
    247     }
    248     for (node = node->first_child; node != NULL; node = node->next) {
    249         loadCriterion(node);
    250     }
    251 }
    252 
    253 void ParameterManagerWrapper::addCriterion(const string &name, const string &typeName,
    254                               const string &defaultLiteralValue)
    255 {
    256     ALOG_ASSERT(mPolicyCriteria.find(name) == mPolicyCriteria.end(),
    257                 "Route Criterion %s already added", name.c_str());
    258 
    259     ISelectionCriterionTypeInterface *criterionType =
    260             getElement<ISelectionCriterionTypeInterface>(typeName, mPolicyCriterionTypes);
    261 
    262     ISelectionCriterionInterface *criterion =
    263             mPfwConnector->createSelectionCriterion(name, criterionType);
    264 
    265     mPolicyCriteria[name] = criterion;
    266     int numericalValue = 0;
    267     if (!criterionType->getNumericalValue(defaultLiteralValue.c_str(),  numericalValue)) {
    268         ALOGE("%s; trying to apply invalid default literal value (%s)", __FUNCTION__,
    269               defaultLiteralValue.c_str());
    270     }
    271     criterion->setCriterionState(numericalValue);
    272 }
    273 
    274 void ParameterManagerWrapper::loadCriterion(cnode *root)
    275 {
    276     ALOG_ASSERT(root != NULL, "error in parsing file");
    277     const char *criterionName = root->name;
    278 
    279     ALOG_ASSERT(mPolicyCriteria.find(criterionName) == mPolicyCriteria.end(),
    280                       "Criterion %s already added", criterionName);
    281 
    282     string paramKeyName = "";
    283     string path = "";
    284     string typeName = "";
    285     string defaultValue = "";
    286 
    287     parseChildren(root, defaultValue, typeName);
    288 
    289     addCriterion(criterionName, typeName, defaultValue);
    290 }
    291 
    292 void ParameterManagerWrapper::loadConfig(cnode *root)
    293 {
    294     ALOG_ASSERT(root != NULL, "error in parsing file");
    295     cnode *node = config_find(root, gPolicyConfTag.c_str());
    296     if (node == NULL) {
    297         ALOGW("%s: Could not find node for pfw", __FUNCTION__);
    298         return;
    299     }
    300     ALOGD("%s: Loading conf for pfw", __FUNCTION__);
    301     loadInclusiveCriterionType(node);
    302     loadExclusiveCriterionType(node);
    303     loadCriteria(node);
    304 }
    305 
    306 
    307 status_t ParameterManagerWrapper::loadAudioPolicyCriteriaConfig(const char *path)
    308 {
    309     ALOG_ASSERT(path != NULL, "error in parsing file: empty path");
    310     cnode *root;
    311     char *data;
    312     ALOGD("%s", __FUNCTION__);
    313     data = (char *)load_file(path, NULL);
    314     if (data == NULL) {
    315         return -ENODEV;
    316     }
    317     root = config_node("", "");
    318     ALOG_ASSERT(root != NULL, "Unable to allocate a configuration node");
    319     config_load(root, data);
    320 
    321     loadConfig(root);
    322 
    323     config_free(root);
    324     free(root);
    325     free(data);
    326     ALOGD("%s: loaded", __FUNCTION__);
    327     return NO_ERROR;
    328 }
    329 
    330 bool ParameterManagerWrapper::isStarted()
    331 {
    332     return mPfwConnector && mPfwConnector->isStarted();
    333 }
    334 
    335 status_t ParameterManagerWrapper::setPhoneState(audio_mode_t mode)
    336 {
    337     ISelectionCriterionInterface *criterion =
    338             getElement<ISelectionCriterionInterface>(gPhoneStateCriterionTag, mPolicyCriteria);
    339     if (criterion == NULL) {
    340         ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionTag.c_str());
    341         return BAD_VALUE;
    342     }
    343     if (!isValueValidForCriterion(criterion, static_cast<int>(mode))) {
    344         return BAD_VALUE;
    345     }
    346     criterion->setCriterionState((int)(mode));
    347     applyPlatformConfiguration();
    348     return NO_ERROR;
    349 }
    350 
    351 audio_mode_t ParameterManagerWrapper::getPhoneState() const
    352 {
    353     const ISelectionCriterionInterface *criterion =
    354             getElement<ISelectionCriterionInterface>(gPhoneStateCriterionTag, mPolicyCriteria);
    355     if (criterion == NULL) {
    356         ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionTag.c_str());
    357         return AUDIO_MODE_NORMAL;
    358     }
    359     return static_cast<audio_mode_t>(criterion->getCriterionState());
    360 }
    361 
    362 status_t ParameterManagerWrapper::setForceUse(audio_policy_force_use_t usage,
    363                                               audio_policy_forced_cfg_t config)
    364 {
    365     // @todo: return an error on a unsupported value
    366     if (usage > AUDIO_POLICY_FORCE_USE_CNT) {
    367         return BAD_VALUE;
    368     }
    369 
    370     ISelectionCriterionInterface *criterion =
    371             getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
    372     if (criterion == NULL) {
    373         ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage].c_str());
    374         return BAD_VALUE;
    375     }
    376     if (!isValueValidForCriterion(criterion, static_cast<int>(config))) {
    377         return BAD_VALUE;
    378     }
    379     criterion->setCriterionState((int)config);
    380     applyPlatformConfiguration();
    381     return NO_ERROR;
    382 }
    383 
    384 audio_policy_forced_cfg_t ParameterManagerWrapper::getForceUse(audio_policy_force_use_t usage) const
    385 {
    386     // @todo: return an error on a unsupported value
    387     if (usage > AUDIO_POLICY_FORCE_USE_CNT) {
    388         return AUDIO_POLICY_FORCE_NONE;
    389     }
    390     const ISelectionCriterionInterface *criterion =
    391             getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
    392     if (criterion == NULL) {
    393         ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage].c_str());
    394         return AUDIO_POLICY_FORCE_NONE;
    395     }
    396     return static_cast<audio_policy_forced_cfg_t>(criterion->getCriterionState());
    397 }
    398 
    399 bool ParameterManagerWrapper::isValueValidForCriterion(ISelectionCriterionInterface *criterion,
    400                                                        int valueToCheck)
    401 {
    402     const ISelectionCriterionTypeInterface *interface = criterion->getCriterionType();
    403     string literalValue;
    404     return interface->getLiteralValue(valueToCheck, literalValue);
    405 }
    406 
    407 status_t ParameterManagerWrapper::setAvailableInputDevices(audio_devices_t inputDevices)
    408 {
    409     ISelectionCriterionInterface *criterion =
    410             getElement<ISelectionCriterionInterface>(gInputDeviceCriterionTag, mPolicyCriteria);
    411     if (criterion == NULL) {
    412         ALOGE("%s: no criterion found for %s", __FUNCTION__, gInputDeviceCriterionTag.c_str());
    413         return DEAD_OBJECT;
    414     }
    415     criterion->setCriterionState(inputDevices & ~AUDIO_DEVICE_BIT_IN);
    416     applyPlatformConfiguration();
    417     return NO_ERROR;
    418 }
    419 
    420 status_t ParameterManagerWrapper::setAvailableOutputDevices(audio_devices_t outputDevices)
    421 {
    422     ISelectionCriterionInterface *criterion =
    423             getElement<ISelectionCriterionInterface>(gOutputDeviceCriterionTag, mPolicyCriteria);
    424     if (criterion == NULL) {
    425         ALOGE("%s: no criterion found for %s", __FUNCTION__, gOutputDeviceCriterionTag.c_str());
    426         return DEAD_OBJECT;
    427     }
    428     criterion->setCriterionState(outputDevices);
    429     applyPlatformConfiguration();
    430     return NO_ERROR;
    431 }
    432 
    433 void ParameterManagerWrapper::applyPlatformConfiguration()
    434 {
    435     mPfwConnector->applyConfigurations();
    436 }
    437 
    438 } // namespace audio_policy
    439 } // namespace android
    440