blob: 09faa4c4487da0fff1c3252665136082961df62a [file] [log] [blame]
François Gaffie20f06f92015-03-24 09:01:14 +01001/*
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"
François Gaffie814ce802016-01-18 11:23:47 +010018//#define LOG_NDEBUG 0
François Gaffie20f06f92015-03-24 09:01:14 +010019
20#include "ParameterManagerWrapper.h"
François Gaffiea56b5c22018-02-21 18:04:39 +010021#include "ParameterManagerWrapperConfig.h"
François Gaffie20f06f92015-03-24 09:01:14 +010022#include <ParameterMgrPlatformConnector.h>
23#include <SelectionCriterionTypeInterface.h>
24#include <SelectionCriterionInterface.h>
Mikhail Naganov913d06c2016-11-01 12:49:22 -070025#include <media/convert.h>
François Gaffie20f06f92015-03-24 09:01:14 +010026#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
38using std::string;
39using std::map;
40using std::vector;
François Gaffiea56b5c22018-02-21 18:04:39 +010041using CriterionTypes = std::map<std::string, ISelectionCriterionTypeInterface *>;
François Gaffie20f06f92015-03-24 09:01:14 +010042
43/// PFW related definitions
44// Logger
45class ParameterMgrPlatformConnectorLogger : public CParameterMgrPlatformConnector::ILogger
46{
47public:
48 ParameterMgrPlatformConnectorLogger() {}
49
François Gaffiec1391f92015-12-10 09:43:48 +010050 virtual void info(const string &log)
François Gaffie20f06f92015-03-24 09:01:14 +010051 {
Liu Changcheng30cf41f2016-12-07 18:58:19 +080052 ALOGV("policy-parameter-manager: %s", log.c_str());
François Gaffiec1391f92015-12-10 09:43:48 +010053 }
54 virtual void warning(const string &log)
55 {
56 ALOGW("policy-parameter-manager: %s", log.c_str());
François Gaffie20f06f92015-03-24 09:01:14 +010057 }
58};
59
François Gaffief19cf792018-05-30 17:22:17 +020060namespace android {
François Gaffie20f06f92015-03-24 09:01:14 +010061
62using utilities::convertTo;
63
François Gaffief19cf792018-05-30 17:22:17 +020064namespace audio_policy {
65
François Gaffie20f06f92015-03-24 09:01:14 +010066const char *const ParameterManagerWrapper::mPolicyPfwDefaultConfFileName =
67 "/etc/parameter-framework/ParameterFrameworkConfigurationPolicy.xml";
Mingwei Shic41dc112017-07-26 10:02:40 +080068const char *const ParameterManagerWrapper::mPolicyPfwVendorConfFileName =
69 "/vendor/etc/parameter-framework/ParameterFrameworkConfigurationPolicy.xml";
François Gaffie20f06f92015-03-24 09:01:14 +010070
François Gaffiea56b5c22018-02-21 18:04:39 +010071static const char *const gInputDeviceCriterionName = "AvailableInputDevices";
72static const char *const gOutputDeviceCriterionName = "AvailableOutputDevices";
73static const char *const gPhoneStateCriterionName = "TelephonyMode";
74static const char *const gOutputDeviceAddressCriterionName = "AvailableOutputDevicesAddresses";
75static const char *const gInputDeviceAddressCriterionName = "AvailableInputDevicesAddresses";
76
77/**
78 * Order MUST be align with defintiion of audio_policy_force_use_t within audio_policy.h
79 */
80static const char *const gForceUseCriterionTag[AUDIO_POLICY_FORCE_USE_CNT] =
81{
82 [AUDIO_POLICY_FORCE_FOR_COMMUNICATION] = "ForceUseForCommunication",
83 [AUDIO_POLICY_FORCE_FOR_MEDIA] = "ForceUseForMedia",
84 [AUDIO_POLICY_FORCE_FOR_RECORD] = "ForceUseForRecord",
85 [AUDIO_POLICY_FORCE_FOR_DOCK] = "ForceUseForDock",
86 [AUDIO_POLICY_FORCE_FOR_SYSTEM] = "ForceUseForSystem",
87 [AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] = "ForceUseForHdmiSystemAudio",
88 [AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND] = "ForceUseForEncodedSurround",
89 [AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING] = "ForceUseForVibrateRinging"
90};
91
François Gaffie20f06f92015-03-24 09:01:14 +010092template <>
93struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionInterface> {};
94template <>
95struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionTypeInterface> {};
96
97ParameterManagerWrapper::ParameterManagerWrapper()
98 : mPfwConnectorLogger(new ParameterMgrPlatformConnectorLogger)
99{
100 // Connector
Mingwei Shic41dc112017-07-26 10:02:40 +0800101 if (access(mPolicyPfwVendorConfFileName, R_OK) == 0) {
102 mPfwConnector = new CParameterMgrPlatformConnector(mPolicyPfwVendorConfFileName);
103 } else {
104 mPfwConnector = new CParameterMgrPlatformConnector(mPolicyPfwDefaultConfFileName);
105 }
François Gaffie20f06f92015-03-24 09:01:14 +0100106
107 // Logger
108 mPfwConnector->setLogger(mPfwConnectorLogger);
109
François Gaffiea56b5c22018-02-21 18:04:39 +0100110 status_t loadResult = loadConfig();
111 if (loadResult < 0) {
112 ALOGE("Policy Wrapper configuration is partially invalid.");
François Gaffie20f06f92015-03-24 09:01:14 +0100113 }
François Gaffie20f06f92015-03-24 09:01:14 +0100114}
115
François Gaffiea56b5c22018-02-21 18:04:39 +0100116status_t ParameterManagerWrapper::loadConfig()
117{
118 auto result = wrapper_config::parse();
119 if (result.parsedConfig == nullptr) {
120 return -ENOENT;
121 }
122 ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement);
123
124 CriterionTypes criterionTypes;
125 for (auto criterionType : result.parsedConfig->criterionTypes) {
126 ALOG_ASSERT(criterionTypes.find(criterionType.name) == criterionTypes.end(),
127 "CriterionType %s already added", criterionType.name.c_str());
128 ALOGV("%s: Adding new criterionType %s", __FUNCTION__, criterionType.name.c_str());
129
130 auto criterionTypePfw =
131 mPfwConnector->createSelectionCriterionType(criterionType.isInclusive);
132
133 for (auto pair : criterionType.valuePairs) {
134 std::string error;
135 ALOGV("%s: Adding pair %d,%s for criterionType %s", __FUNCTION__, pair.first,
136 pair.second.c_str(), criterionType.name.c_str());
137 criterionTypePfw->addValuePair(pair.first, pair.second, error);
138 }
139 criterionTypes[criterionType.name] = criterionTypePfw;
140 }
141
142 for (auto criterion : result.parsedConfig->criteria) {
143 ALOG_ASSERT(mPolicyCriteria.find(criterion.name) == mPolicyCriteria.end(),
144 "%s: Criterion %s already added", __FUNCTION__, criterion.name.c_str());
145
146 auto criterionType =
147 getElement<ISelectionCriterionTypeInterface>(criterion.typeName, criterionTypes);
148 ALOG_ASSERT(criterionType != nullptr, "No %s Criterion type found for criterion %s",
149 criterion.typeName.c_str(), criterion.name.c_str());
150
151 auto criterionPfw = mPfwConnector->createSelectionCriterion(criterion.name, criterionType);
152 mPolicyCriteria[criterion.name] = criterionPfw;
153
154 if (not criterion.defaultLiteralValue.empty()) {
155 int numericalValue = 0;
156 if (not criterionType->getNumericalValue(criterion.defaultLiteralValue.c_str(),
157 numericalValue)) {
158 ALOGE("%s; trying to apply invalid default literal value (%s)", __FUNCTION__,
159 criterion.defaultLiteralValue.c_str());
160 continue;
161 }
162 criterionPfw->setCriterionState(numericalValue);
163 }
164 }
165 return result.nbSkippedElement == 0? NO_ERROR : BAD_VALUE;
166}
167
François Gaffie20f06f92015-03-24 09:01:14 +0100168ParameterManagerWrapper::~ParameterManagerWrapper()
169{
170 // Unset logger
171 mPfwConnector->setLogger(NULL);
172 // Remove logger
173 delete mPfwConnectorLogger;
174 // Remove connector
175 delete mPfwConnector;
176}
177
178status_t ParameterManagerWrapper::start()
179{
180 ALOGD("%s: in", __FUNCTION__);
181 /// Start PFW
182 std::string error;
183 if (!mPfwConnector->start(error)) {
184 ALOGE("%s: Policy PFW start error: %s", __FUNCTION__, error.c_str());
185 return NO_INIT;
186 }
187 ALOGD("%s: Policy PFW successfully started!", __FUNCTION__);
188 return NO_ERROR;
189}
190
François Gaffie20f06f92015-03-24 09:01:14 +0100191template <typename T>
192T *ParameterManagerWrapper::getElement(const string &name, std::map<string, T *> &elementsMap)
193{
194 parameterManagerElementSupported<T>();
195 typename std::map<string, T *>::iterator it = elementsMap.find(name);
François Gaffie814ce802016-01-18 11:23:47 +0100196 ALOG_ASSERT(it != elementsMap.end(), "Element %s not found", name.c_str());
197 return it != elementsMap.end() ? it->second : NULL;
François Gaffie20f06f92015-03-24 09:01:14 +0100198}
199
200template <typename T>
201const T *ParameterManagerWrapper::getElement(const string &name, const std::map<string, T *> &elementsMap) const
202{
203 parameterManagerElementSupported<T>();
204 typename std::map<string, T *>::const_iterator it = elementsMap.find(name);
François Gaffie814ce802016-01-18 11:23:47 +0100205 ALOG_ASSERT(it != elementsMap.end(), "Element %s not found", name.c_str());
206 return it != elementsMap.end() ? it->second : NULL;
François Gaffie20f06f92015-03-24 09:01:14 +0100207}
208
François Gaffie20f06f92015-03-24 09:01:14 +0100209bool ParameterManagerWrapper::isStarted()
210{
211 return mPfwConnector && mPfwConnector->isStarted();
212}
213
214status_t ParameterManagerWrapper::setPhoneState(audio_mode_t mode)
215{
François Gaffie814ce802016-01-18 11:23:47 +0100216 ISelectionCriterionInterface *criterion =
François Gaffiea56b5c22018-02-21 18:04:39 +0100217 getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
François Gaffie814ce802016-01-18 11:23:47 +0100218 if (criterion == NULL) {
François Gaffiea56b5c22018-02-21 18:04:39 +0100219 ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
François Gaffie814ce802016-01-18 11:23:47 +0100220 return BAD_VALUE;
221 }
François Gaffie20f06f92015-03-24 09:01:14 +0100222 if (!isValueValidForCriterion(criterion, static_cast<int>(mode))) {
223 return BAD_VALUE;
224 }
225 criterion->setCriterionState((int)(mode));
226 applyPlatformConfiguration();
227 return NO_ERROR;
228}
229
230audio_mode_t ParameterManagerWrapper::getPhoneState() const
231{
232 const ISelectionCriterionInterface *criterion =
François Gaffiea56b5c22018-02-21 18:04:39 +0100233 getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
François Gaffie814ce802016-01-18 11:23:47 +0100234 if (criterion == NULL) {
François Gaffiea56b5c22018-02-21 18:04:39 +0100235 ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
François Gaffie814ce802016-01-18 11:23:47 +0100236 return AUDIO_MODE_NORMAL;
237 }
François Gaffie20f06f92015-03-24 09:01:14 +0100238 return static_cast<audio_mode_t>(criterion->getCriterionState());
239}
240
241status_t ParameterManagerWrapper::setForceUse(audio_policy_force_use_t usage,
242 audio_policy_forced_cfg_t config)
243{
244 // @todo: return an error on a unsupported value
245 if (usage > AUDIO_POLICY_FORCE_USE_CNT) {
246 return BAD_VALUE;
247 }
248
François Gaffie814ce802016-01-18 11:23:47 +0100249 ISelectionCriterionInterface *criterion =
250 getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
251 if (criterion == NULL) {
François Gaffiea56b5c22018-02-21 18:04:39 +0100252 ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
François Gaffie814ce802016-01-18 11:23:47 +0100253 return BAD_VALUE;
254 }
François Gaffie20f06f92015-03-24 09:01:14 +0100255 if (!isValueValidForCriterion(criterion, static_cast<int>(config))) {
256 return BAD_VALUE;
257 }
258 criterion->setCriterionState((int)config);
259 applyPlatformConfiguration();
260 return NO_ERROR;
261}
262
263audio_policy_forced_cfg_t ParameterManagerWrapper::getForceUse(audio_policy_force_use_t usage) const
264{
265 // @todo: return an error on a unsupported value
266 if (usage > AUDIO_POLICY_FORCE_USE_CNT) {
267 return AUDIO_POLICY_FORCE_NONE;
268 }
269 const ISelectionCriterionInterface *criterion =
270 getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
François Gaffie814ce802016-01-18 11:23:47 +0100271 if (criterion == NULL) {
François Gaffiea56b5c22018-02-21 18:04:39 +0100272 ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
François Gaffie814ce802016-01-18 11:23:47 +0100273 return AUDIO_POLICY_FORCE_NONE;
274 }
François Gaffie20f06f92015-03-24 09:01:14 +0100275 return static_cast<audio_policy_forced_cfg_t>(criterion->getCriterionState());
276}
277
278bool ParameterManagerWrapper::isValueValidForCriterion(ISelectionCriterionInterface *criterion,
279 int valueToCheck)
280{
281 const ISelectionCriterionTypeInterface *interface = criterion->getCriterionType();
282 string literalValue;
283 return interface->getLiteralValue(valueToCheck, literalValue);
284}
285
François Gaffiea56b5c22018-02-21 18:04:39 +0100286status_t ParameterManagerWrapper::setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
287 audio_policy_dev_state_t state)
288{
289 std::string criterionName = audio_is_output_device(devDesc->type()) ?
290 gOutputDeviceAddressCriterionName : gInputDeviceAddressCriterionName;
291
292 ALOGV("%s: device with address %s %s", __FUNCTION__, devDesc->mAddress.string(),
293 state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE? "disconnected" : "connected");
294 ISelectionCriterionInterface *criterion =
295 getElement<ISelectionCriterionInterface>(criterionName, mPolicyCriteria);
296
297 if (criterion == NULL) {
298 ALOGE("%s: no criterion found for %s", __FUNCTION__, criterionName.c_str());
299 return DEAD_OBJECT;
300 }
301
302 auto criterionType = criterion->getCriterionType();
303 int deviceAddressId;
Francois Gaffie716e1432019-01-14 16:58:59 +0100304 if (not criterionType->getNumericalValue(devDesc->address().string(), deviceAddressId)) {
305 ALOGW("%s: unknown device address reported (%s)", __FUNCTION__, devDesc->address().c_str());
François Gaffiea56b5c22018-02-21 18:04:39 +0100306 return BAD_TYPE;
307 }
308 int currentValueMask = criterion->getCriterionState();
309 if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
310 currentValueMask |= deviceAddressId;
311 }
312 else {
313 currentValueMask &= ~deviceAddressId;
314 }
315 criterion->setCriterionState(currentValueMask);
316 return NO_ERROR;
317}
318
François Gaffiea3e696d2015-12-18 09:38:43 +0100319status_t ParameterManagerWrapper::setAvailableInputDevices(audio_devices_t inputDevices)
François Gaffie20f06f92015-03-24 09:01:14 +0100320{
François Gaffie814ce802016-01-18 11:23:47 +0100321 ISelectionCriterionInterface *criterion =
François Gaffiea56b5c22018-02-21 18:04:39 +0100322 getElement<ISelectionCriterionInterface>(gInputDeviceCriterionName, mPolicyCriteria);
François Gaffie20f06f92015-03-24 09:01:14 +0100323 if (criterion == NULL) {
François Gaffiea56b5c22018-02-21 18:04:39 +0100324 ALOGE("%s: no criterion found for %s", __FUNCTION__, gInputDeviceCriterionName);
François Gaffie20f06f92015-03-24 09:01:14 +0100325 return DEAD_OBJECT;
326 }
François Gaffiea3e696d2015-12-18 09:38:43 +0100327 criterion->setCriterionState(inputDevices & ~AUDIO_DEVICE_BIT_IN);
328 applyPlatformConfiguration();
329 return NO_ERROR;
330}
François Gaffie20f06f92015-03-24 09:01:14 +0100331
François Gaffiea3e696d2015-12-18 09:38:43 +0100332status_t ParameterManagerWrapper::setAvailableOutputDevices(audio_devices_t outputDevices)
333{
François Gaffie814ce802016-01-18 11:23:47 +0100334 ISelectionCriterionInterface *criterion =
François Gaffiea56b5c22018-02-21 18:04:39 +0100335 getElement<ISelectionCriterionInterface>(gOutputDeviceCriterionName, mPolicyCriteria);
François Gaffiea3e696d2015-12-18 09:38:43 +0100336 if (criterion == NULL) {
François Gaffiea56b5c22018-02-21 18:04:39 +0100337 ALOGE("%s: no criterion found for %s", __FUNCTION__, gOutputDeviceCriterionName);
François Gaffiea3e696d2015-12-18 09:38:43 +0100338 return DEAD_OBJECT;
François Gaffie20f06f92015-03-24 09:01:14 +0100339 }
François Gaffiea3e696d2015-12-18 09:38:43 +0100340 criterion->setCriterionState(outputDevices);
François Gaffie20f06f92015-03-24 09:01:14 +0100341 applyPlatformConfiguration();
342 return NO_ERROR;
343}
344
345void ParameterManagerWrapper::applyPlatformConfiguration()
346{
347 mPfwConnector->applyConfigurations();
348}
349
350} // namespace audio_policy
351} // namespace android