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