summaryrefslogtreecommitdiffstats
path: root/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp')
-rwxr-xr-xservices/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp435
1 files changed, 435 insertions, 0 deletions
diff --git a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
new file mode 100755
index 0000000..cfe49d4
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2015 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/PFWWrapper"
+
+#include "ParameterManagerWrapper.h"
+#include "audio_policy_criteria_conf.h"
+#include <ParameterMgrPlatformConnector.h>
+#include <SelectionCriterionTypeInterface.h>
+#include <SelectionCriterionInterface.h>
+#include <convert.h>
+#include <algorithm>
+#include <cutils/config_utils.h>
+#include <cutils/misc.h>
+#include <fstream>
+#include <limits>
+#include <sstream>
+#include <string>
+#include <vector>
+#include <stdint.h>
+#include <cmath>
+#include <utils/Log.h>
+
+using std::string;
+using std::map;
+using std::vector;
+
+/// PFW related definitions
+// Logger
+class ParameterMgrPlatformConnectorLogger : public CParameterMgrPlatformConnector::ILogger
+{
+public:
+ ParameterMgrPlatformConnectorLogger() {}
+
+ virtual void log(bool isWarning, const string &log)
+ {
+ const static string format("policy-parameter-manager: ");
+
+ if (isWarning) {
+ ALOGW("%s %s", format.c_str(), log.c_str());
+ } else {
+ ALOGD("%s %s", format.c_str(), log.c_str());
+ }
+ }
+};
+
+namespace android
+{
+
+using utilities::convertTo;
+
+namespace audio_policy
+{
+const char *const ParameterManagerWrapper::mPolicyPfwDefaultConfFileName =
+ "/etc/parameter-framework/ParameterFrameworkConfigurationPolicy.xml";
+
+template <>
+struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionInterface> {};
+template <>
+struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionTypeInterface> {};
+
+ParameterManagerWrapper::ParameterManagerWrapper()
+ : mPfwConnectorLogger(new ParameterMgrPlatformConnectorLogger)
+{
+ // Connector
+ mPfwConnector = new CParameterMgrPlatformConnector(mPolicyPfwDefaultConfFileName);
+
+ // Logger
+ mPfwConnector->setLogger(mPfwConnectorLogger);
+
+ // Load criteria file
+ if ((loadAudioPolicyCriteriaConfig(gAudioPolicyCriteriaVendorConfFilePath) != NO_ERROR) &&
+ (loadAudioPolicyCriteriaConfig(gAudioPolicyCriteriaConfFilePath) != NO_ERROR)) {
+ ALOGE("%s: Neither vendor conf file (%s) nor system conf file (%s) could be found",
+ __FUNCTION__, gAudioPolicyCriteriaVendorConfFilePath,
+ gAudioPolicyCriteriaConfFilePath);
+ }
+ ALOGD("%s: ParameterManagerWrapper instantiated!", __FUNCTION__);
+}
+
+ParameterManagerWrapper::~ParameterManagerWrapper()
+{
+ // Unset logger
+ mPfwConnector->setLogger(NULL);
+ // Remove logger
+ delete mPfwConnectorLogger;
+ // Remove connector
+ delete mPfwConnector;
+}
+
+status_t ParameterManagerWrapper::start()
+{
+ ALOGD("%s: in", __FUNCTION__);
+ /// Start PFW
+ std::string error;
+ if (!mPfwConnector->start(error)) {
+ ALOGE("%s: Policy PFW start error: %s", __FUNCTION__, error.c_str());
+ return NO_INIT;
+ }
+ ALOGD("%s: Policy PFW successfully started!", __FUNCTION__);
+ return NO_ERROR;
+}
+
+
+void ParameterManagerWrapper::addCriterionType(const string &typeName, bool isInclusive)
+{
+ ALOG_ASSERT(mPolicyCriterionTypes.find(typeName) == mPolicyCriterionTypes.end(),
+ "CriterionType " << typeName << " already added");
+ ALOGD("%s: Adding new criterionType %s", __FUNCTION__, typeName.c_str());
+
+ mPolicyCriterionTypes[typeName] = mPfwConnector->createSelectionCriterionType(isInclusive);
+}
+
+void ParameterManagerWrapper::addCriterionTypeValuePair(
+ const string &typeName,
+ uint32_t numericValue,
+ const string &literalValue)
+{
+ ALOG_ASSERT(mPolicyCriterionTypes.find(typeName) != mPolicyCriterionTypes.end(),
+ "CriterionType " << typeName.c_str() << "not found");
+ ALOGV("%s: Adding new value pair (%d,%s) for criterionType %s", __FUNCTION__,
+ numericValue, literalValue.c_str(), typeName.c_str());
+ ISelectionCriterionTypeInterface *criterionType = mPolicyCriterionTypes[typeName];
+ criterionType->addValuePair(numericValue, literalValue.c_str());
+}
+
+void ParameterManagerWrapper::loadCriterionType(cnode *root, bool isInclusive)
+{
+ ALOG_ASSERT(root != NULL, "error in parsing file");
+ cnode *node;
+ for (node = root->first_child; node != NULL; node = node->next) {
+
+ ALOG_ASSERT(node != NULL, "error in parsing file");
+ const char *typeName = node->name;
+ char *valueNames = strndup(node->value, strlen(node->value));
+
+ addCriterionType(typeName, isInclusive);
+
+ uint32_t index = 0;
+ char *ctx;
+ char *valueName = strtok_r(valueNames, ",", &ctx);
+ while (valueName != NULL) {
+ if (strlen(valueName) != 0) {
+
+ // Conf file may use or not pair, if no pair, use incremental index, else
+ // use provided index.
+ if (strchr(valueName, ':') != NULL) {
+
+ char *first = strtok(valueName, ":");
+ char *second = strtok(NULL, ":");
+ ALOG_ASSERT((first != NULL) && (strlen(first) != 0) &&
+ (second != NULL) && (strlen(second) != 0),
+ "invalid value pair");
+
+ if (!convertTo<string, uint32_t>(first, index)) {
+ ALOGE("%s: Invalid index(%s) found", __FUNCTION__, first);
+ }
+ addCriterionTypeValuePair(typeName, index, second);
+ } else {
+
+ uint32_t pfwIndex = isInclusive ? 1 << index : index;
+ addCriterionTypeValuePair(typeName, pfwIndex, valueName);
+ index += 1;
+ }
+ }
+ valueName = strtok_r(NULL, ",", &ctx);
+ }
+ free(valueNames);
+ }
+}
+
+void ParameterManagerWrapper::loadInclusiveCriterionType(cnode *root)
+{
+ ALOG_ASSERT(root != NULL, "error in parsing file");
+ cnode *node = config_find(root, gInclusiveCriterionTypeTag.c_str());
+ if (node == NULL) {
+ return;
+ }
+ loadCriterionType(node, true);
+}
+
+void ParameterManagerWrapper::loadExclusiveCriterionType(cnode *root)
+{
+ ALOG_ASSERT(root != NULL, "error in parsing file");
+ cnode *node = config_find(root, gExclusiveCriterionTypeTag.c_str());
+ if (node == NULL) {
+ return;
+ }
+ loadCriterionType(node, false);
+}
+
+void ParameterManagerWrapper::parseChildren(cnode *root, string &defaultValue, string &type)
+{
+ ALOG_ASSERT(root != NULL, "error in parsing file");
+ cnode *node;
+ for (node = root->first_child; node != NULL; node = node->next) {
+ ALOG_ASSERT(node != NULL, "error in parsing file");
+
+ if (string(node->name) == gDefaultTag) {
+ defaultValue = node->value;
+ } else if (string(node->name) == gTypeTag) {
+ type = node->value;
+ } else {
+ ALOGE("%s: Unrecognized %s %s node", __FUNCTION__, node->name, node->value);
+ }
+ }
+}
+
+template <typename T>
+T *ParameterManagerWrapper::getElement(const string &name, std::map<string, T *> &elementsMap)
+{
+ parameterManagerElementSupported<T>();
+ typename std::map<string, T *>::iterator it = elementsMap.find(name);
+ ALOG_ASSERT(it != elementsMap.end(), "Element " << name << " not found");
+ return it->second;
+}
+
+template <typename T>
+const T *ParameterManagerWrapper::getElement(const string &name, const std::map<string, T *> &elementsMap) const
+{
+ parameterManagerElementSupported<T>();
+ typename std::map<string, T *>::const_iterator it = elementsMap.find(name);
+ ALOG_ASSERT(it != elementsMap.end(), "Element " << name << " not found");
+ return it->second;
+}
+
+void ParameterManagerWrapper::loadCriteria(cnode *root)
+{
+ ALOG_ASSERT(root != NULL, "error in parsing file");
+ cnode *node = config_find(root, gCriterionTag.c_str());
+
+ if (node == NULL) {
+ ALOGW("%s: no inclusive criteria found", __FUNCTION__);
+ return;
+ }
+ for (node = node->first_child; node != NULL; node = node->next) {
+ loadCriterion(node);
+ }
+}
+
+void ParameterManagerWrapper::addCriterion(const string &name, const string &typeName,
+ const string &defaultLiteralValue)
+{
+ ALOG_ASSERT(mPolicyCriteria.find(criterionName) == mPolicyCriteria.end(),
+ "Route Criterion " << criterionName << " already added");
+
+ ISelectionCriterionTypeInterface *criterionType =
+ getElement<ISelectionCriterionTypeInterface>(typeName, mPolicyCriterionTypes);
+
+ ISelectionCriterionInterface *criterion =
+ mPfwConnector->createSelectionCriterion(name, criterionType);
+
+ mPolicyCriteria[name] = criterion;
+ int numericalValue = 0;
+ if (!criterionType->getNumericalValue(defaultLiteralValue.c_str(), numericalValue)) {
+ ALOGE("%s; trying to apply invalid default literal value (%s)", __FUNCTION__,
+ defaultLiteralValue.c_str());
+ }
+ criterion->setCriterionState(numericalValue);
+}
+
+void ParameterManagerWrapper::loadCriterion(cnode *root)
+{
+ ALOG_ASSERT(root != NULL, "error in parsing file");
+ const char *criterionName = root->name;
+
+ ALOG_ASSERT(mPolicyCriteria.find(criterionName) == mPolicyCriteria.end(),
+ "Criterion " << criterionName << " already added");
+
+ string paramKeyName = "";
+ string path = "";
+ string typeName = "";
+ string defaultValue = "";
+
+ parseChildren(root, defaultValue, typeName);
+
+ addCriterion(criterionName, typeName, defaultValue);
+}
+
+void ParameterManagerWrapper::loadConfig(cnode *root)
+{
+ ALOG_ASSERT(root != NULL, "error in parsing file");
+ cnode *node = config_find(root, gPolicyConfTag.c_str());
+ if (node == NULL) {
+ ALOGW("%s: Could not find node for pfw", __FUNCTION__);
+ return;
+ }
+ ALOGD("%s: Loading conf for pfw", __FUNCTION__);
+ loadInclusiveCriterionType(node);
+ loadExclusiveCriterionType(node);
+ loadCriteria(node);
+}
+
+
+status_t ParameterManagerWrapper::loadAudioPolicyCriteriaConfig(const char *path)
+{
+ ALOG_ASSERT(path != NULL, "error in parsing file: empty path");
+ cnode *root;
+ char *data;
+ ALOGD("%s", __FUNCTION__);
+ data = (char *)load_file(path, NULL);
+ if (data == NULL) {
+ return -ENODEV;
+ }
+ root = config_node("", "");
+ ALOG_ASSERT(root != NULL, "Unable to allocate a configuration node");
+ config_load(root, data);
+
+ loadConfig(root);
+
+ config_free(root);
+ free(root);
+ free(data);
+ ALOGD("%s: loaded", __FUNCTION__);
+ return NO_ERROR;
+}
+
+bool ParameterManagerWrapper::isStarted()
+{
+ return mPfwConnector && mPfwConnector->isStarted();
+}
+
+status_t ParameterManagerWrapper::setPhoneState(audio_mode_t mode)
+{
+ ISelectionCriterionInterface *criterion = mPolicyCriteria[gPhoneStateCriterionTag];
+ if (!isValueValidForCriterion(criterion, static_cast<int>(mode))) {
+ return BAD_VALUE;
+ }
+ criterion->setCriterionState((int)(mode));
+ applyPlatformConfiguration();
+ return NO_ERROR;
+}
+
+audio_mode_t ParameterManagerWrapper::getPhoneState() const
+{
+ const ISelectionCriterionInterface *criterion =
+ getElement<ISelectionCriterionInterface>(gPhoneStateCriterionTag, mPolicyCriteria);
+ return static_cast<audio_mode_t>(criterion->getCriterionState());
+}
+
+status_t ParameterManagerWrapper::setForceUse(audio_policy_force_use_t usage,
+ audio_policy_forced_cfg_t config)
+{
+ // @todo: return an error on a unsupported value
+ if (usage > AUDIO_POLICY_FORCE_USE_CNT) {
+ return BAD_VALUE;
+ }
+
+ ISelectionCriterionInterface *criterion = mPolicyCriteria[gForceUseCriterionTag[usage]];
+ if (!isValueValidForCriterion(criterion, static_cast<int>(config))) {
+ return BAD_VALUE;
+ }
+ criterion->setCriterionState((int)config);
+ applyPlatformConfiguration();
+ return NO_ERROR;
+}
+
+audio_policy_forced_cfg_t ParameterManagerWrapper::getForceUse(audio_policy_force_use_t usage) const
+{
+ // @todo: return an error on a unsupported value
+ if (usage > AUDIO_POLICY_FORCE_USE_CNT) {
+ return AUDIO_POLICY_FORCE_NONE;
+ }
+ const ISelectionCriterionInterface *criterion =
+ getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
+ return static_cast<audio_policy_forced_cfg_t>(criterion->getCriterionState());
+}
+
+bool ParameterManagerWrapper::isValueValidForCriterion(ISelectionCriterionInterface *criterion,
+ int valueToCheck)
+{
+ const ISelectionCriterionTypeInterface *interface = criterion->getCriterionType();
+ string literalValue;
+ return interface->getLiteralValue(valueToCheck, literalValue);
+}
+
+status_t ParameterManagerWrapper::setDeviceConnectionState(audio_devices_t devices,
+ audio_policy_dev_state_t state,
+ const char */*deviceAddres*/)
+{
+ ISelectionCriterionInterface *criterion = NULL;
+
+ if (audio_is_output_devices(devices)) {
+ criterion = mPolicyCriteria[gOutputDeviceCriterionTag];
+ } else if (devices & AUDIO_DEVICE_BIT_IN) {
+ criterion = mPolicyCriteria[gInputDeviceCriterionTag];
+ } else {
+ return BAD_TYPE;
+ }
+ if (criterion == NULL) {
+ ALOGE("%s: no criterion found for devices", __FUNCTION__);
+ return DEAD_OBJECT;
+ }
+
+ int32_t previousDevices = criterion->getCriterionState();
+ switch (state)
+ {
+ case AUDIO_POLICY_DEVICE_STATE_AVAILABLE:
+ criterion->setCriterionState(previousDevices |= devices);
+ break;
+
+ case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE:
+ if (devices & AUDIO_DEVICE_BIT_IN) {
+ devices &= ~AUDIO_DEVICE_BIT_IN;
+ }
+ criterion->setCriterionState(previousDevices &= ~devices);
+ break;
+
+ default:
+ return BAD_VALUE;
+ }
+ applyPlatformConfiguration();
+ return NO_ERROR;
+}
+
+void ParameterManagerWrapper::applyPlatformConfiguration()
+{
+ mPfwConnector->applyConfigurations();
+}
+
+} // namespace audio_policy
+} // namespace android