ParameterManagerWrapper.cpp revision 20f06f996337c9bf79d0b112083f6427a122ebab
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 19#include "ParameterManagerWrapper.h" 20#include "audio_policy_criteria_conf.h" 21#include <ParameterMgrPlatformConnector.h> 22#include <SelectionCriterionTypeInterface.h> 23#include <SelectionCriterionInterface.h> 24#include <convert.h> 25#include <algorithm> 26#include <cutils/config_utils.h> 27#include <cutils/misc.h> 28#include <fstream> 29#include <limits> 30#include <sstream> 31#include <string> 32#include <vector> 33#include <stdint.h> 34#include <cmath> 35#include <utils/Log.h> 36 37using std::string; 38using std::map; 39using std::vector; 40 41/// PFW related definitions 42// Logger 43class ParameterMgrPlatformConnectorLogger : public CParameterMgrPlatformConnector::ILogger 44{ 45public: 46 ParameterMgrPlatformConnectorLogger() {} 47 48 virtual void log(bool isWarning, const string &log) 49 { 50 const static string format("policy-parameter-manager: "); 51 52 if (isWarning) { 53 ALOGW("%s %s", format.c_str(), log.c_str()); 54 } else { 55 ALOGD("%s %s", format.c_str(), log.c_str()); 56 } 57 } 58}; 59 60namespace android 61{ 62 63using utilities::convertTo; 64 65namespace audio_policy 66{ 67const char *const ParameterManagerWrapper::mPolicyPfwDefaultConfFileName = 68 "/etc/parameter-framework/ParameterFrameworkConfigurationPolicy.xml"; 69 70template <> 71struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionInterface> {}; 72template <> 73struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionTypeInterface> {}; 74 75ParameterManagerWrapper::ParameterManagerWrapper() 76 : mPfwConnectorLogger(new ParameterMgrPlatformConnectorLogger) 77{ 78 // Connector 79 mPfwConnector = new CParameterMgrPlatformConnector(mPolicyPfwDefaultConfFileName); 80 81 // Logger 82 mPfwConnector->setLogger(mPfwConnectorLogger); 83 84 // Load criteria file 85 if ((loadAudioPolicyCriteriaConfig(gAudioPolicyCriteriaVendorConfFilePath) != NO_ERROR) && 86 (loadAudioPolicyCriteriaConfig(gAudioPolicyCriteriaConfFilePath) != NO_ERROR)) { 87 ALOGE("%s: Neither vendor conf file (%s) nor system conf file (%s) could be found", 88 __FUNCTION__, gAudioPolicyCriteriaVendorConfFilePath, 89 gAudioPolicyCriteriaConfFilePath); 90 } 91 ALOGD("%s: ParameterManagerWrapper instantiated!", __FUNCTION__); 92} 93 94ParameterManagerWrapper::~ParameterManagerWrapper() 95{ 96 // Unset logger 97 mPfwConnector->setLogger(NULL); 98 // Remove logger 99 delete mPfwConnectorLogger; 100 // Remove connector 101 delete mPfwConnector; 102} 103 104status_t ParameterManagerWrapper::start() 105{ 106 ALOGD("%s: in", __FUNCTION__); 107 /// Start PFW 108 std::string error; 109 if (!mPfwConnector->start(error)) { 110 ALOGE("%s: Policy PFW start error: %s", __FUNCTION__, error.c_str()); 111 return NO_INIT; 112 } 113 ALOGD("%s: Policy PFW successfully started!", __FUNCTION__); 114 return NO_ERROR; 115} 116 117 118void ParameterManagerWrapper::addCriterionType(const string &typeName, bool isInclusive) 119{ 120 ALOG_ASSERT(mPolicyCriterionTypes.find(typeName) == mPolicyCriterionTypes.end(), 121 "CriterionType " << typeName << " already added"); 122 ALOGD("%s: Adding new criterionType %s", __FUNCTION__, typeName.c_str()); 123 124 mPolicyCriterionTypes[typeName] = mPfwConnector->createSelectionCriterionType(isInclusive); 125} 126 127void ParameterManagerWrapper::addCriterionTypeValuePair( 128 const string &typeName, 129 uint32_t numericValue, 130 const string &literalValue) 131{ 132 ALOG_ASSERT(mPolicyCriterionTypes.find(typeName) != mPolicyCriterionTypes.end(), 133 "CriterionType " << typeName.c_str() << "not found"); 134 ALOGV("%s: Adding new value pair (%d,%s) for criterionType %s", __FUNCTION__, 135 numericValue, literalValue.c_str(), typeName.c_str()); 136 ISelectionCriterionTypeInterface *criterionType = mPolicyCriterionTypes[typeName]; 137 criterionType->addValuePair(numericValue, literalValue.c_str()); 138} 139 140void ParameterManagerWrapper::loadCriterionType(cnode *root, bool isInclusive) 141{ 142 ALOG_ASSERT(root != NULL, "error in parsing file"); 143 cnode *node; 144 for (node = root->first_child; node != NULL; node = node->next) { 145 146 ALOG_ASSERT(node != NULL, "error in parsing file"); 147 const char *typeName = node->name; 148 char *valueNames = (char *)node->value; 149 150 addCriterionType(typeName, isInclusive); 151 152 uint32_t index = 0; 153 char *ctx; 154 char *valueName = strtok_r(valueNames, ",", &ctx); 155 while (valueName != NULL) { 156 if (strlen(valueName) != 0) { 157 158 // Conf file may use or not pair, if no pair, use incremental index, else 159 // use provided index. 160 if (strchr(valueName, ':') != NULL) { 161 162 char *first = strtok(valueName, ":"); 163 char *second = strtok(NULL, ":"); 164 ALOG_ASSERT((first != NULL) && (strlen(first) != 0) && 165 (second != NULL) && (strlen(second) != 0), 166 "invalid value pair"); 167 168 if (!convertTo<string, uint32_t>(first, index)) { 169 ALOGE("%s: Invalid index(%s) found", __FUNCTION__, first); 170 } 171 addCriterionTypeValuePair(typeName, index, second); 172 } else { 173 174 uint32_t pfwIndex = isInclusive ? 1 << index : index; 175 addCriterionTypeValuePair(typeName, pfwIndex, valueName); 176 index += 1; 177 } 178 } 179 valueName = strtok_r(NULL, ",", &ctx); 180 } 181 } 182} 183 184void 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 194void 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 204void 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 221template <typename T> 222T *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 " << name << " not found"); 227 return it->second; 228} 229 230template <typename T> 231const 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 " << name << " not found"); 236 return it->second; 237} 238 239void 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 253void ParameterManagerWrapper::addCriterion(const string &name, const string &typeName, 254 const string &defaultLiteralValue) 255{ 256 ALOG_ASSERT(mPolicyCriteria.find(criterionName) == mPolicyCriteria.end(), 257 "Route Criterion " << criterionName << " already added"); 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 274void 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 " << criterionName << " already added"); 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 292void 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 307status_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 330bool ParameterManagerWrapper::isStarted() 331{ 332 return mPfwConnector && mPfwConnector->isStarted(); 333} 334 335status_t ParameterManagerWrapper::setPhoneState(audio_mode_t mode) 336{ 337 ISelectionCriterionInterface *criterion = mPolicyCriteria[gPhoneStateCriterionTag]; 338 if (!isValueValidForCriterion(criterion, static_cast<int>(mode))) { 339 return BAD_VALUE; 340 } 341 criterion->setCriterionState((int)(mode)); 342 applyPlatformConfiguration(); 343 return NO_ERROR; 344} 345 346audio_mode_t ParameterManagerWrapper::getPhoneState() const 347{ 348 const ISelectionCriterionInterface *criterion = 349 getElement<ISelectionCriterionInterface>(gPhoneStateCriterionTag, mPolicyCriteria); 350 return static_cast<audio_mode_t>(criterion->getCriterionState()); 351} 352 353status_t ParameterManagerWrapper::setForceUse(audio_policy_force_use_t usage, 354 audio_policy_forced_cfg_t config) 355{ 356 // @todo: return an error on a unsupported value 357 if (usage > AUDIO_POLICY_FORCE_USE_CNT) { 358 return BAD_VALUE; 359 } 360 361 ISelectionCriterionInterface *criterion = mPolicyCriteria[gForceUseCriterionTag[usage]]; 362 if (!isValueValidForCriterion(criterion, static_cast<int>(config))) { 363 return BAD_VALUE; 364 } 365 criterion->setCriterionState((int)config); 366 applyPlatformConfiguration(); 367 return NO_ERROR; 368} 369 370audio_policy_forced_cfg_t ParameterManagerWrapper::getForceUse(audio_policy_force_use_t usage) const 371{ 372 // @todo: return an error on a unsupported value 373 if (usage > AUDIO_POLICY_FORCE_USE_CNT) { 374 return AUDIO_POLICY_FORCE_NONE; 375 } 376 const ISelectionCriterionInterface *criterion = 377 getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria); 378 return static_cast<audio_policy_forced_cfg_t>(criterion->getCriterionState()); 379} 380 381bool ParameterManagerWrapper::isValueValidForCriterion(ISelectionCriterionInterface *criterion, 382 int valueToCheck) 383{ 384 const ISelectionCriterionTypeInterface *interface = criterion->getCriterionType(); 385 string literalValue; 386 return interface->getLiteralValue(valueToCheck, literalValue); 387} 388 389status_t ParameterManagerWrapper::setDeviceConnectionState(audio_devices_t devices, 390 audio_policy_dev_state_t state, 391 const char */*deviceAddres*/) 392{ 393 ISelectionCriterionInterface *criterion = NULL; 394 395 if (audio_is_output_devices(devices)) { 396 criterion = mPolicyCriteria[gOutputDeviceCriterionTag]; 397 } else if (devices & AUDIO_DEVICE_BIT_IN) { 398 criterion = mPolicyCriteria[gInputDeviceCriterionTag]; 399 } else { 400 return BAD_TYPE; 401 } 402 if (criterion == NULL) { 403 ALOGE("%s: no criterion found for devices", __FUNCTION__); 404 return DEAD_OBJECT; 405 } 406 407 int32_t previousDevices = criterion->getCriterionState(); 408 switch (state) 409 { 410 case AUDIO_POLICY_DEVICE_STATE_AVAILABLE: 411 criterion->setCriterionState(previousDevices |= devices); 412 break; 413 414 case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE: 415 if (devices & AUDIO_DEVICE_BIT_IN) { 416 devices &= ~AUDIO_DEVICE_BIT_IN; 417 } 418 criterion->setCriterionState(previousDevices &= ~devices); 419 break; 420 421 default: 422 return BAD_VALUE; 423 } 424 applyPlatformConfiguration(); 425 return NO_ERROR; 426} 427 428void ParameterManagerWrapper::applyPlatformConfiguration() 429{ 430 mPfwConnector->applyConfigurations(); 431} 432 433} // namespace audio_policy 434} // namespace android 435