• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <ParameterMgrFullConnector.h>
22 #include <ParameterMgrPlatformConnector.h>
23 #include <SelectionCriterionTypeInterface.h>
24 #include <SelectionCriterionInterface.h>
25 #include <media/convert.h>
26 #include <algorithm>
27 #include <cutils/bitops.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 <cinttypes>
36 #include <cmath>
37 #include <utils/Log.h>
38 
39 using std::string;
40 using std::map;
41 using std::vector;
42 
43 /// PFW related definitions
44 // Logger
45 class ParameterMgrPlatformConnectorLogger : public CParameterMgrPlatformConnector::ILogger
46 {
47 public:
ParameterMgrPlatformConnectorLogger()48     ParameterMgrPlatformConnectorLogger() {}
49 
info(const string & log)50     virtual void info(const string &log)
51     {
52         ALOGV("policy-parameter-manager: %s", log.c_str());
53     }
warning(const string & log)54     virtual void warning(const string &log)
55     {
56         ALOGW("policy-parameter-manager: %s", log.c_str());
57     }
58 };
59 
60 namespace android {
61 
62 using utilities::convertTo;
63 
64 namespace audio_policy {
65 
66 #ifdef ENABLE_CAP_AIDL_HYBRID_MODE
67 // Legacy XML from vendor partition used when disabling AIDL CAP configuration (HIDL or Hybrid)
68 const char *const ParameterManagerWrapper::mVendorPolicyPfwConfFileName =
69     "/vendor/etc/parameter-framework/ParameterFrameworkConfigurationPolicy.xml";
70 #endif
71 const char *const ParameterManagerWrapper::mPolicyPfwConfFileName =
72     "/etc/parameter-framework/ParameterFrameworkConfigurationCap.xml";
73 
74 template <>
75 struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionInterface> {};
76 template <>
77 struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionTypeInterface> {};
78 
ParameterManagerWrapper(bool useLegacyConfigurationFile,bool enableSchemaVerification,const std::string & schemaUri)79 ParameterManagerWrapper::ParameterManagerWrapper(bool useLegacyConfigurationFile,
80         bool enableSchemaVerification, const std::string &schemaUri)
81     : mPfwConnectorLogger(new ParameterMgrPlatformConnectorLogger)
82 {
83     std::string policyPfwConfFileName;
84 #ifdef ENABLE_CAP_AIDL_HYBRID_MODE
85     // Connector
86     if (useLegacyConfigurationFile && access(mVendorPolicyPfwConfFileName, R_OK) == 0) {
87         policyPfwConfFileName = mVendorPolicyPfwConfFileName;
88     }
89 #endif
90     if (!useLegacyConfigurationFile && access(mPolicyPfwConfFileName, R_OK) == 0) {
91         policyPfwConfFileName = mPolicyPfwConfFileName;
92     }
93     if (policyPfwConfFileName.empty()) {
94         // bailing out
95         ALOGE("%s: failed to find Cap config file, cannot init Cap.", __func__);
96         return;
97     }
98     mPfwConnector = new CParameterMgrFullConnector(policyPfwConfFileName);
99     // Logger
100     mPfwConnector->setLogger(mPfwConnectorLogger);
101 
102     // Schema validation
103     std::string error;
104     bool ret = mPfwConnector->setValidateSchemasOnStart(enableSchemaVerification, error);
105     ALOGE_IF(!ret, "Failed to activate schema validation: %s", error.c_str());
106     if (enableSchemaVerification && ret && !schemaUri.empty()) {
107         ALOGE("Schema verification activated with schema URI: %s", schemaUri.c_str());
108         mPfwConnector->setSchemaUri(schemaUri);
109     }
110 }
111 
addCriterion(const std::string & name,bool isInclusive,ValuePairs pairs,const std::string & defaultValue)112 status_t ParameterManagerWrapper::addCriterion(const std::string &name, bool isInclusive,
113                                                ValuePairs pairs, const std::string &defaultValue)
114 {
115     if (mPfwConnector == nullptr) {
116         ALOGE("%s: failed, Cap not initialized", __func__);
117         return NO_INIT;
118     }
119     ALOG_ASSERT(not isStarted(), "%s failed since PFW is already started", __func__);
120     auto criterionType = mPfwConnector->createSelectionCriterionType(isInclusive);
121 
122     for (auto pair : pairs) {
123         std::string error;
124         ALOGV("%s: Adding pair %" PRIu64", %s for criterionType %s", __func__, std::get<0>(pair),
125               std::get<2>(pair).c_str(), name.c_str());
126         criterionType->addValuePair(std::get<0>(pair), std::get<2>(pair), error);
127 
128         if (name == capEngineConfig::gOutputDeviceCriterionName) {
129             ALOGV("%s: Adding mOutputDeviceToCriterionTypeMap 0x%X %" PRIu64" for criterionType %s",
130                   __func__, std::get<1>(pair), std::get<0>(pair), name.c_str());
131             audio_devices_t androidType = static_cast<audio_devices_t>(std::get<1>(pair));
132             mOutputDeviceToCriterionTypeMap[androidType] = std::get<0>(pair);
133         }
134         if (name == capEngineConfig::gInputDeviceCriterionName) {
135             ALOGV("%s: Adding mInputDeviceToCriterionTypeMap 0x%X %" PRIu64" for criterionType %s",
136                   __func__, std::get<1>(pair), std::get<0>(pair), name.c_str());
137             audio_devices_t androidType = static_cast<audio_devices_t>(std::get<1>(pair));
138             mInputDeviceToCriterionTypeMap[androidType] = std::get<0>(pair);
139         }
140     }
141     ALOG_ASSERT(mPolicyCriteria.find(name) == mPolicyCriteria.end(),
142                 "%s: Criterion %s already added", __FUNCTION__, name.c_str());
143 
144     auto criterion = mPfwConnector->createSelectionCriterion(name, criterionType);
145     mPolicyCriteria[name] = criterion;
146 
147     if (not defaultValue.empty()) {
148         uint64_t numericalValue = 0;
149         if (not criterionType->getNumericalValue(defaultValue.c_str(), numericalValue)) {
150             ALOGE("%s; trying to apply invalid default literal value (%s)", __FUNCTION__,
151                   defaultValue.c_str());
152         }
153         criterion->setCriterionState(numericalValue);
154     }
155     return NO_ERROR;
156 }
157 
~ParameterManagerWrapper()158 ParameterManagerWrapper::~ParameterManagerWrapper()
159 {
160     // Unset logger
161     if (mPfwConnector != nullptr) {
162         mPfwConnector->setLogger(NULL);
163     }
164     // Remove logger
165     delete mPfwConnectorLogger;
166     // Remove connector
167     delete mPfwConnector;
168 }
169 
start(std::string & error)170 status_t ParameterManagerWrapper::start(std::string &error)
171 {
172     ALOGD("%s: in", __FUNCTION__);
173     /// Start PFW
174     if (mPfwConnector == nullptr || !mPfwConnector->start(error)) {
175         ALOGE("%s: Policy PFW failed (error:  %s)", __func__,
176               mPfwConnector == nullptr ? "invalid connector" : error.c_str());
177         return NO_INIT;
178     }
179     ALOGD("%s: Policy PFW succeeded!", __FUNCTION__);
180     return NO_ERROR;
181 }
182 
183 template <typename T>
getElement(const string & name,std::map<string,T * > & elementsMap)184 T *ParameterManagerWrapper::getElement(const string &name, std::map<string, T *> &elementsMap)
185 {
186     parameterManagerElementSupported<T>();
187     typename std::map<string, T *>::iterator it = elementsMap.find(name);
188     ALOG_ASSERT(it != elementsMap.end(), "Element %s not found", name.c_str());
189     return it != elementsMap.end() ? it->second : NULL;
190 }
191 
192 template <typename T>
getElement(const string & name,const std::map<string,T * > & elementsMap) const193 const T *ParameterManagerWrapper::getElement(const string &name, const std::map<string, T *> &elementsMap) const
194 {
195     parameterManagerElementSupported<T>();
196     typename std::map<string, T *>::const_iterator it = elementsMap.find(name);
197     ALOG_ASSERT(it != elementsMap.end(), "Element %s not found", name.c_str());
198     return it != elementsMap.end() ? it->second : NULL;
199 }
200 
isStarted() const201 bool ParameterManagerWrapper::isStarted() const
202 {
203     return mPfwConnector && mPfwConnector->isStarted();
204 }
205 
setPhoneState(audio_mode_t mode)206 status_t ParameterManagerWrapper::setPhoneState(audio_mode_t mode)
207 {
208     if (!isStarted()) {
209         ALOGE("%s: failed, Cap not initialized", __func__);
210         return NO_INIT;
211     }
212     ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
213             capEngineConfig::gPhoneStateCriterionName, mPolicyCriteria);
214     if (criterion == NULL) {
215         ALOGE("%s: no criterion found for %s", __FUNCTION__,
216               capEngineConfig::gPhoneStateCriterionName);
217         return BAD_VALUE;
218     }
219     if (!isValueValidForCriterion(criterion, static_cast<int>(mode))) {
220         return BAD_VALUE;
221     }
222     criterion->setCriterionState((int)(mode));
223     applyPlatformConfiguration();
224     return NO_ERROR;
225 }
226 
getPhoneState() const227 audio_mode_t ParameterManagerWrapper::getPhoneState() const
228 {
229     if (!isStarted()) {
230         ALOGE("%s: failed, Cap not initialized", __func__);
231         return AUDIO_MODE_NORMAL;
232     }
233     const ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
234             capEngineConfig::gPhoneStateCriterionName, mPolicyCriteria);
235     if (criterion == NULL) {
236         ALOGE("%s: no criterion found for %s", __func__, capEngineConfig::gPhoneStateCriterionName);
237         return AUDIO_MODE_NORMAL;
238     }
239     return static_cast<audio_mode_t>(criterion->getCriterionState());
240 }
241 
setForceUse(audio_policy_force_use_t usage,audio_policy_forced_cfg_t config)242 status_t ParameterManagerWrapper::setForceUse(audio_policy_force_use_t usage,
243                                               audio_policy_forced_cfg_t config)
244 {
245     // @todo: return an error on a unsupported value
246     if (usage > AUDIO_POLICY_FORCE_USE_CNT) {
247         return BAD_VALUE;
248     }
249     if (!isStarted()) {
250         ALOGE("%s: failed, Cap not initialized", __func__);
251         return NO_INIT;
252     }
253     ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
254             capEngineConfig::gForceUseCriterionTag[usage], mPolicyCriteria);
255     if (criterion == NULL) {
256         ALOGE("%s: no criterion found for %s", __func__,
257               capEngineConfig::gForceUseCriterionTag[usage]);
258         return BAD_VALUE;
259     }
260     if (!isValueValidForCriterion(criterion, static_cast<int>(config))) {
261         return BAD_VALUE;
262     }
263     criterion->setCriterionState((int)config);
264     applyPlatformConfiguration();
265     return NO_ERROR;
266 }
267 
getForceUse(audio_policy_force_use_t usage) const268 audio_policy_forced_cfg_t ParameterManagerWrapper::getForceUse(audio_policy_force_use_t usage) const
269 {
270     // @todo: return an error on a unsupported value
271     if (usage > AUDIO_POLICY_FORCE_USE_CNT) {
272         return AUDIO_POLICY_FORCE_NONE;
273     }
274     if (!isStarted()) {
275         ALOGE("%s: failed, Cap not initialized", __func__);
276         return AUDIO_POLICY_FORCE_NONE;
277     }
278     const ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
279             capEngineConfig::gForceUseCriterionTag[usage], mPolicyCriteria);
280     if (criterion == NULL) {
281         ALOGE("%s: no criterion found for %s", __func__,
282               capEngineConfig::gForceUseCriterionTag[usage]);
283         return AUDIO_POLICY_FORCE_NONE;
284     }
285     return static_cast<audio_policy_forced_cfg_t>(criterion->getCriterionState());
286 }
287 
isValueValidForCriterion(ISelectionCriterionInterface * criterion,int valueToCheck)288 bool ParameterManagerWrapper::isValueValidForCriterion(ISelectionCriterionInterface *criterion,
289                                                        int valueToCheck)
290 {
291     const ISelectionCriterionTypeInterface *interface = criterion->getCriterionType();
292     string literalValue;
293     return interface->getLiteralValue(valueToCheck, literalValue);
294 }
295 
setDeviceConnectionState(audio_devices_t type,const std::string & address,audio_policy_dev_state_t state)296 status_t ParameterManagerWrapper::setDeviceConnectionState(
297         audio_devices_t type, const std::string &address, audio_policy_dev_state_t state)
298 {
299     if (!isStarted()) {
300         ALOGE("%s: failed, Cap not initialized", __func__);
301         return NO_INIT;
302     }
303     std::string criterionName = audio_is_output_device(type) ?
304             capEngineConfig::gOutputDeviceAddressCriterionName :
305             capEngineConfig::gInputDeviceAddressCriterionName;
306     ALOGV("%s: device with address %s %s", __FUNCTION__, address.c_str(),
307           state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE? "disconnected" : "connected");
308     ISelectionCriterionInterface *criterion =
309             getElement<ISelectionCriterionInterface>(criterionName, mPolicyCriteria);
310 
311     if (criterion == NULL) {
312         ALOGE("%s: no criterion found for %s", __func__, criterionName.c_str());
313         return DEAD_OBJECT;
314     }
315 
316     auto criterionType = criterion->getCriterionType();
317     uint64_t deviceAddressId;
318     if (not criterionType->getNumericalValue(address.c_str(), deviceAddressId)) {
319         ALOGW("%s: unknown device address reported (%s) for criterion %s", __func__,
320               address.c_str(), criterionName.c_str());
321         return BAD_TYPE;
322     }
323     int currentValueMask = criterion->getCriterionState();
324     if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
325         currentValueMask |= deviceAddressId;
326     }
327     else {
328         currentValueMask &= ~deviceAddressId;
329     }
330     criterion->setCriterionState(currentValueMask);
331     return NO_ERROR;
332 }
333 
setAvailableInputDevices(const DeviceTypeSet & types)334 status_t ParameterManagerWrapper::setAvailableInputDevices(const DeviceTypeSet &types) {
335     if (!isStarted()) {
336         ALOGE("%s: failed, Cap not initialized", __func__);
337         return NO_INIT;
338     }
339     ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
340             capEngineConfig::gInputDeviceCriterionName, mPolicyCriteria);
341     if (criterion == NULL) {
342         ALOGE("%s: no criterion found for %s", __func__,
343               capEngineConfig::gInputDeviceCriterionName);
344         return DEAD_OBJECT;
345     }
346     criterion->setCriterionState(convertDeviceTypesToCriterionValue(types));
347     applyPlatformConfiguration();
348     return NO_ERROR;
349 }
350 
setAvailableOutputDevices(const DeviceTypeSet & types)351 status_t ParameterManagerWrapper::setAvailableOutputDevices(const DeviceTypeSet &types) {
352     if (!isStarted()) {
353         ALOGE("%s: failed, Cap not initialized", __func__);
354         return NO_INIT;
355     }
356     ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
357             capEngineConfig::gOutputDeviceCriterionName, mPolicyCriteria);
358     if (criterion == NULL) {
359         ALOGE("%s: no criterion found for %s", __func__,
360               capEngineConfig::gOutputDeviceCriterionName);
361         return DEAD_OBJECT;
362     }
363     criterion->setCriterionState(convertDeviceTypesToCriterionValue(types));
364     applyPlatformConfiguration();
365     return NO_ERROR;
366 }
367 
applyPlatformConfiguration()368 void ParameterManagerWrapper::applyPlatformConfiguration()
369 {
370     if (!isStarted()) {
371         ALOGE("%s: failed, Cap not initialized", __func__);
372         return;
373     }
374     mPfwConnector->applyConfigurations();
375 }
376 
convertDeviceTypeToCriterionValue(audio_devices_t type) const377 uint64_t ParameterManagerWrapper::convertDeviceTypeToCriterionValue(audio_devices_t type) const {
378     bool isOut = audio_is_output_devices(type);
379     const auto &adapters = isOut ? mOutputDeviceToCriterionTypeMap : mInputDeviceToCriterionTypeMap;
380     const auto &adapter = adapters.find(type);
381     if (adapter != adapters.end()) {
382         ALOGV("%s: multibit device %d converted to criterion %" PRIu64, __func__, type,
383               adapter->second);
384         return adapter->second;
385     }
386     ALOGE("%s: failed to find map for multibit device %d", __func__, type);
387     return 0;
388 }
389 
convertDeviceTypesToCriterionValue(const DeviceTypeSet & types) const390 uint64_t ParameterManagerWrapper::convertDeviceTypesToCriterionValue(
391         const DeviceTypeSet &types) const {
392     uint64_t criterionValue = 0;
393     for (const auto &type : types) {
394         criterionValue += convertDeviceTypeToCriterionValue(type);
395     }
396     return criterionValue;
397 }
398 
convertDeviceCriterionValueToDeviceTypes(uint64_t criterionValue,bool isOut) const399 DeviceTypeSet ParameterManagerWrapper::convertDeviceCriterionValueToDeviceTypes(
400         uint64_t criterionValue, bool isOut) const {
401     DeviceTypeSet deviceTypes;
402     const auto &adapters = isOut ? mOutputDeviceToCriterionTypeMap : mInputDeviceToCriterionTypeMap;
403     for (const auto &adapter : adapters) {
404         if ((adapter.second & criterionValue) == adapter.second) {
405             deviceTypes.insert(adapter.first);
406         }
407     }
408     return deviceTypes;
409 }
410 
createDomain(const std::string & domain)411 void ParameterManagerWrapper::createDomain(const std::string &domain)
412 {
413     if (!isStarted()) {
414         ALOGE("%s: failed, Cap not initialized", __func__);
415         return;
416     }
417     std::string error;
418     bool ret = mPfwConnector->createDomain(domain, error);
419     if (!ret) {
420         ALOGD("%s: failed for %s (error=%s)", __func__, domain.c_str(),
421         error.c_str());
422     }
423 }
424 
addConfigurableElementToDomain(const std::string & domain,const std::string & elementPath)425 void ParameterManagerWrapper::addConfigurableElementToDomain(const std::string &domain,
426         const std::string &elementPath)
427 {
428     if (!isStarted()) {
429         ALOGE("%s: failed, Cap not initialized", __func__);
430         return;
431     }
432     std::string error;
433     bool ret = mPfwConnector->addConfigurableElementToDomain(domain, elementPath, error);
434     ALOGE_IF(!ret, "%s: failed for %s for domain %s (error=%s)",
435               __func__, elementPath.c_str(), domain.c_str(), error.c_str());
436 }
437 
createConfiguration(const std::string & domain,const std::string & configurationName)438 void ParameterManagerWrapper::createConfiguration(const std::string &domain,
439         const std::string &configurationName)
440 {
441     if (!isStarted()) {
442         ALOGE("%s: failed, Cap not initialized", __func__);
443         return;
444     }
445     std::string error;
446     bool ret = mPfwConnector->createConfiguration(domain, configurationName, error);
447     ALOGE_IF(!ret, "%s: failed for %s for domain %s (error=%s)",
448               __func__, configurationName.c_str(), domain.c_str(), error.c_str());
449 }
450 
setApplicationRule(const std::string & domain,const std::string & configurationName,const std::string & rule)451 void ParameterManagerWrapper::setApplicationRule(
452         const std::string &domain, const std::string &configurationName, const std::string &rule)
453 {
454     if (!isStarted()) {
455         ALOGE("%s: failed, Cap not initialized", __func__);
456         return;
457     }
458     std::string error;
459     bool ret = mPfwConnector->setApplicationRule(domain, configurationName, rule, error);
460     ALOGE_IF(!ret, "%s: failed for %s for domain %s and configuration %s (error=%s)",
461               __func__, rule.c_str(), domain.c_str(), configurationName.c_str(), error.c_str());
462 }
463 
accessConfigurationValue(const std::string & domain,const std::string & configurationName,const std::string & elementPath,std::string & value)464 void ParameterManagerWrapper::accessConfigurationValue(const std::string &domain,
465         const std::string &configurationName, const std::string &elementPath,
466         std::string &value)
467 {
468     if (!isStarted()) {
469         ALOGE("%s: failed, Cap not initialized", __func__);
470         return;
471     }
472     std::string error;
473     bool ret = mPfwConnector->accessConfigurationValue(domain, configurationName, elementPath,
474             value, /*set=*/ true, error);
475     ALOGE_IF(!ret, "%s: failed to set value %s for parameter %s on domain %s and configuration %s "
476           "(error=%s)", __func__, value.c_str(), elementPath.c_str(),  domain.c_str(),
477           configurationName.c_str(), error.c_str());
478 }
479 
setConfiguration(const android::capEngineConfig::ParsingResult & capSettings)480 status_t ParameterManagerWrapper::setConfiguration(
481         const android::capEngineConfig::ParsingResult& capSettings)
482 {
483     if (!isStarted()) {
484         return NO_INIT;
485     }
486     std::string error;
487     if (!mPfwConnector->setTuningMode(/* bOn= */ true, error)) {
488         ALOGD("%s: failed (error=%s)", __func__, error.c_str());
489         return DEAD_OBJECT;
490     }
491     for (auto &domain: capSettings.parsedConfig->capConfigurableDomains) {
492         createDomain(domain.name);
493         for (const auto &configurableElementValue : domain.settings[0].configurableElementValues) {
494             addConfigurableElementToDomain(domain.name,
495                     configurableElementValue.configurableElement.path);
496         }
497         for (const auto &configuration : domain.configurations) {
498             createConfiguration(domain.name, configuration.name);
499             setApplicationRule(domain.name, configuration.name, configuration.rule);
500         }
501         for (const auto &setting : domain.settings) {
502             for (const auto &configurableElementValue : setting.configurableElementValues) {
503                 std::string value = configurableElementValue.value;
504                 accessConfigurationValue(domain.name, setting.configurationName,
505                         configurableElementValue.configurableElement.path, value);
506             }
507 
508         }
509     }
510     mPfwConnector->setTuningMode(/* bOn= */ false, error);
511     return OK;
512 }
513 
514 } // namespace audio_policy
515 } // namespace android
516