blob: 63990ac85b5a027b936584931368a4b7c36b0b22 [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 Gaffie20f06f92015-03-24 09:01:14 +010021#include <ParameterMgrPlatformConnector.h>
22#include <SelectionCriterionTypeInterface.h>
23#include <SelectionCriterionInterface.h>
Mikhail Naganov913d06c2016-11-01 12:49:22 -070024#include <media/convert.h>
François Gaffie20f06f92015-03-24 09:01:14 +010025#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
François Gaffiec1391f92015-12-10 09:43:48 +010048 virtual void info(const string &log)
François Gaffie20f06f92015-03-24 09:01:14 +010049 {
Liu Changcheng30cf41f2016-12-07 18:58:19 +080050 ALOGV("policy-parameter-manager: %s", log.c_str());
François Gaffiec1391f92015-12-10 09:43:48 +010051 }
52 virtual void warning(const string &log)
53 {
54 ALOGW("policy-parameter-manager: %s", log.c_str());
François Gaffie20f06f92015-03-24 09:01:14 +010055 }
56};
57
François Gaffief19cf792018-05-30 17:22:17 +020058namespace android {
François Gaffie20f06f92015-03-24 09:01:14 +010059
60using utilities::convertTo;
61
François Gaffief19cf792018-05-30 17:22:17 +020062namespace audio_policy {
63
François Gaffie20f06f92015-03-24 09:01:14 +010064const char *const ParameterManagerWrapper::mPolicyPfwDefaultConfFileName =
65 "/etc/parameter-framework/ParameterFrameworkConfigurationPolicy.xml";
Mingwei Shic41dc112017-07-26 10:02:40 +080066const char *const ParameterManagerWrapper::mPolicyPfwVendorConfFileName =
67 "/vendor/etc/parameter-framework/ParameterFrameworkConfigurationPolicy.xml";
François Gaffie20f06f92015-03-24 09:01:14 +010068
François Gaffiea56b5c22018-02-21 18:04:39 +010069static const char *const gInputDeviceCriterionName = "AvailableInputDevices";
70static const char *const gOutputDeviceCriterionName = "AvailableOutputDevices";
71static const char *const gPhoneStateCriterionName = "TelephonyMode";
72static const char *const gOutputDeviceAddressCriterionName = "AvailableOutputDevicesAddresses";
73static const char *const gInputDeviceAddressCriterionName = "AvailableInputDevicesAddresses";
74
75/**
76 * Order MUST be align with defintiion of audio_policy_force_use_t within audio_policy.h
77 */
78static const char *const gForceUseCriterionTag[AUDIO_POLICY_FORCE_USE_CNT] =
79{
80 [AUDIO_POLICY_FORCE_FOR_COMMUNICATION] = "ForceUseForCommunication",
81 [AUDIO_POLICY_FORCE_FOR_MEDIA] = "ForceUseForMedia",
82 [AUDIO_POLICY_FORCE_FOR_RECORD] = "ForceUseForRecord",
83 [AUDIO_POLICY_FORCE_FOR_DOCK] = "ForceUseForDock",
84 [AUDIO_POLICY_FORCE_FOR_SYSTEM] = "ForceUseForSystem",
85 [AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] = "ForceUseForHdmiSystemAudio",
86 [AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND] = "ForceUseForEncodedSurround",
87 [AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING] = "ForceUseForVibrateRinging"
88};
89
François Gaffie20f06f92015-03-24 09:01:14 +010090template <>
91struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionInterface> {};
92template <>
93struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionTypeInterface> {};
94
François Gaffieab1837a2019-10-15 10:48:50 +020095ParameterManagerWrapper::ParameterManagerWrapper(bool enableSchemaVerification,
96 const std::string &schemaUri)
François Gaffie20f06f92015-03-24 09:01:14 +010097 : mPfwConnectorLogger(new ParameterMgrPlatformConnectorLogger)
98{
99 // Connector
Mingwei Shic41dc112017-07-26 10:02:40 +0800100 if (access(mPolicyPfwVendorConfFileName, R_OK) == 0) {
101 mPfwConnector = new CParameterMgrPlatformConnector(mPolicyPfwVendorConfFileName);
102 } else {
103 mPfwConnector = new CParameterMgrPlatformConnector(mPolicyPfwDefaultConfFileName);
104 }
François Gaffie20f06f92015-03-24 09:01:14 +0100105
106 // Logger
107 mPfwConnector->setLogger(mPfwConnectorLogger);
François Gaffieab1837a2019-10-15 10:48:50 +0200108
109 // Schema validation
110 std::string error;
111 bool ret = mPfwConnector->setValidateSchemasOnStart(enableSchemaVerification, error);
112 ALOGE_IF(!ret, "Failed to activate schema validation: %s", error.c_str());
113 if (enableSchemaVerification && ret && !schemaUri.empty()) {
114 ALOGE("Schema verification activated with schema URI: %s", schemaUri.c_str());
115 mPfwConnector->setSchemaUri(schemaUri);
116 }
François Gaffie20f06f92015-03-24 09:01:14 +0100117}
118
François Gaffie7188f1a2018-11-02 14:35:42 +0100119status_t ParameterManagerWrapper::addCriterion(const std::string &name, bool isInclusive,
120 ValuePairs pairs, const std::string &defaultValue)
François Gaffiea56b5c22018-02-21 18:04:39 +0100121{
François Gaffie7188f1a2018-11-02 14:35:42 +0100122 ALOG_ASSERT(not isStarted(), "Cannot add a criterion if PFW is already started");
123 auto criterionType = mPfwConnector->createSelectionCriterionType(isInclusive);
124
125 for (auto pair : pairs) {
126 std::string error;
127 ALOGV("%s: Adding pair %d,%s for criterionType %s", __FUNCTION__, pair.first,
128 pair.second.c_str(), name.c_str());
129 criterionType->addValuePair(pair.first, pair.second, error);
François Gaffiea56b5c22018-02-21 18:04:39 +0100130 }
François Gaffie7188f1a2018-11-02 14:35:42 +0100131 ALOG_ASSERT(mPolicyCriteria.find(name) == mPolicyCriteria.end(),
132 "%s: Criterion %s already added", __FUNCTION__, name.c_str());
François Gaffiea56b5c22018-02-21 18:04:39 +0100133
François Gaffie7188f1a2018-11-02 14:35:42 +0100134 auto criterion = mPfwConnector->createSelectionCriterion(name, criterionType);
135 mPolicyCriteria[name] = criterion;
François Gaffiea56b5c22018-02-21 18:04:39 +0100136
François Gaffie7188f1a2018-11-02 14:35:42 +0100137 if (not defaultValue.empty()) {
138 int numericalValue = 0;
139 if (not criterionType->getNumericalValue(defaultValue.c_str(), numericalValue)) {
140 ALOGE("%s; trying to apply invalid default literal value (%s)", __FUNCTION__,
141 defaultValue.c_str());
François Gaffiea56b5c22018-02-21 18:04:39 +0100142 }
François Gaffie7188f1a2018-11-02 14:35:42 +0100143 criterion->setCriterionState(numericalValue);
François Gaffiea56b5c22018-02-21 18:04:39 +0100144 }
François Gaffie7188f1a2018-11-02 14:35:42 +0100145 return NO_ERROR;
François Gaffiea56b5c22018-02-21 18:04:39 +0100146}
147
François Gaffie20f06f92015-03-24 09:01:14 +0100148ParameterManagerWrapper::~ParameterManagerWrapper()
149{
150 // Unset logger
151 mPfwConnector->setLogger(NULL);
152 // Remove logger
153 delete mPfwConnectorLogger;
154 // Remove connector
155 delete mPfwConnector;
156}
157
François Gaffieab1837a2019-10-15 10:48:50 +0200158status_t ParameterManagerWrapper::start(std::string &error)
François Gaffie20f06f92015-03-24 09:01:14 +0100159{
160 ALOGD("%s: in", __FUNCTION__);
161 /// Start PFW
François Gaffie20f06f92015-03-24 09:01:14 +0100162 if (!mPfwConnector->start(error)) {
163 ALOGE("%s: Policy PFW start error: %s", __FUNCTION__, error.c_str());
164 return NO_INIT;
165 }
166 ALOGD("%s: Policy PFW successfully started!", __FUNCTION__);
167 return NO_ERROR;
168}
169
François Gaffie20f06f92015-03-24 09:01:14 +0100170template <typename T>
171T *ParameterManagerWrapper::getElement(const string &name, std::map<string, T *> &elementsMap)
172{
173 parameterManagerElementSupported<T>();
174 typename std::map<string, T *>::iterator it = elementsMap.find(name);
François Gaffie814ce802016-01-18 11:23:47 +0100175 ALOG_ASSERT(it != elementsMap.end(), "Element %s not found", name.c_str());
176 return it != elementsMap.end() ? it->second : NULL;
François Gaffie20f06f92015-03-24 09:01:14 +0100177}
178
179template <typename T>
180const T *ParameterManagerWrapper::getElement(const string &name, const std::map<string, T *> &elementsMap) const
181{
182 parameterManagerElementSupported<T>();
183 typename std::map<string, T *>::const_iterator it = elementsMap.find(name);
François Gaffie814ce802016-01-18 11:23:47 +0100184 ALOG_ASSERT(it != elementsMap.end(), "Element %s not found", name.c_str());
185 return it != elementsMap.end() ? it->second : NULL;
François Gaffie20f06f92015-03-24 09:01:14 +0100186}
187
François Gaffie20f06f92015-03-24 09:01:14 +0100188bool ParameterManagerWrapper::isStarted()
189{
190 return mPfwConnector && mPfwConnector->isStarted();
191}
192
193status_t ParameterManagerWrapper::setPhoneState(audio_mode_t mode)
194{
François Gaffie814ce802016-01-18 11:23:47 +0100195 ISelectionCriterionInterface *criterion =
François Gaffiea56b5c22018-02-21 18:04:39 +0100196 getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
François Gaffie814ce802016-01-18 11:23:47 +0100197 if (criterion == NULL) {
François Gaffiea56b5c22018-02-21 18:04:39 +0100198 ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
François Gaffie814ce802016-01-18 11:23:47 +0100199 return BAD_VALUE;
200 }
François Gaffie20f06f92015-03-24 09:01:14 +0100201 if (!isValueValidForCriterion(criterion, static_cast<int>(mode))) {
202 return BAD_VALUE;
203 }
204 criterion->setCriterionState((int)(mode));
205 applyPlatformConfiguration();
206 return NO_ERROR;
207}
208
209audio_mode_t ParameterManagerWrapper::getPhoneState() const
210{
211 const ISelectionCriterionInterface *criterion =
François Gaffiea56b5c22018-02-21 18:04:39 +0100212 getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
François Gaffie814ce802016-01-18 11:23:47 +0100213 if (criterion == NULL) {
François Gaffiea56b5c22018-02-21 18:04:39 +0100214 ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
François Gaffie814ce802016-01-18 11:23:47 +0100215 return AUDIO_MODE_NORMAL;
216 }
François Gaffie20f06f92015-03-24 09:01:14 +0100217 return static_cast<audio_mode_t>(criterion->getCriterionState());
218}
219
220status_t ParameterManagerWrapper::setForceUse(audio_policy_force_use_t usage,
221 audio_policy_forced_cfg_t config)
222{
223 // @todo: return an error on a unsupported value
224 if (usage > AUDIO_POLICY_FORCE_USE_CNT) {
225 return BAD_VALUE;
226 }
227
François Gaffie814ce802016-01-18 11:23:47 +0100228 ISelectionCriterionInterface *criterion =
229 getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
230 if (criterion == NULL) {
François Gaffiea56b5c22018-02-21 18:04:39 +0100231 ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
François Gaffie814ce802016-01-18 11:23:47 +0100232 return BAD_VALUE;
233 }
François Gaffie20f06f92015-03-24 09:01:14 +0100234 if (!isValueValidForCriterion(criterion, static_cast<int>(config))) {
235 return BAD_VALUE;
236 }
237 criterion->setCriterionState((int)config);
238 applyPlatformConfiguration();
239 return NO_ERROR;
240}
241
242audio_policy_forced_cfg_t ParameterManagerWrapper::getForceUse(audio_policy_force_use_t usage) const
243{
244 // @todo: return an error on a unsupported value
245 if (usage > AUDIO_POLICY_FORCE_USE_CNT) {
246 return AUDIO_POLICY_FORCE_NONE;
247 }
248 const ISelectionCriterionInterface *criterion =
249 getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
François Gaffie814ce802016-01-18 11:23:47 +0100250 if (criterion == NULL) {
François Gaffiea56b5c22018-02-21 18:04:39 +0100251 ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
François Gaffie814ce802016-01-18 11:23:47 +0100252 return AUDIO_POLICY_FORCE_NONE;
253 }
François Gaffie20f06f92015-03-24 09:01:14 +0100254 return static_cast<audio_policy_forced_cfg_t>(criterion->getCriterionState());
255}
256
257bool ParameterManagerWrapper::isValueValidForCriterion(ISelectionCriterionInterface *criterion,
258 int valueToCheck)
259{
260 const ISelectionCriterionTypeInterface *interface = criterion->getCriterionType();
261 string literalValue;
262 return interface->getLiteralValue(valueToCheck, literalValue);
263}
264
François Gaffieab1837a2019-10-15 10:48:50 +0200265status_t ParameterManagerWrapper::setDeviceConnectionState(
266 audio_devices_t type, const std::string address, audio_policy_dev_state_t state)
François Gaffiea56b5c22018-02-21 18:04:39 +0100267{
François Gaffieab1837a2019-10-15 10:48:50 +0200268 std::string criterionName = audio_is_output_device(type) ?
François Gaffiea56b5c22018-02-21 18:04:39 +0100269 gOutputDeviceAddressCriterionName : gInputDeviceAddressCriterionName;
270
François Gaffieab1837a2019-10-15 10:48:50 +0200271 ALOGV("%s: device with address %s %s", __FUNCTION__, address.c_str(),
François Gaffiea56b5c22018-02-21 18:04:39 +0100272 state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE? "disconnected" : "connected");
273 ISelectionCriterionInterface *criterion =
274 getElement<ISelectionCriterionInterface>(criterionName, mPolicyCriteria);
275
276 if (criterion == NULL) {
277 ALOGE("%s: no criterion found for %s", __FUNCTION__, criterionName.c_str());
278 return DEAD_OBJECT;
279 }
280
281 auto criterionType = criterion->getCriterionType();
282 int deviceAddressId;
François Gaffieab1837a2019-10-15 10:48:50 +0200283 if (not criterionType->getNumericalValue(address.c_str(), deviceAddressId)) {
François Gaffie376740f2020-01-16 09:08:04 +0100284 ALOGW("%s: unknown device address reported (%s) for criterion %s", __FUNCTION__,
285 address.c_str(), criterionName.c_str());
François Gaffiea56b5c22018-02-21 18:04:39 +0100286 return BAD_TYPE;
287 }
288 int currentValueMask = criterion->getCriterionState();
289 if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
290 currentValueMask |= deviceAddressId;
291 }
292 else {
293 currentValueMask &= ~deviceAddressId;
294 }
295 criterion->setCriterionState(currentValueMask);
296 return NO_ERROR;
297}
298
François Gaffiea3e696d2015-12-18 09:38:43 +0100299status_t ParameterManagerWrapper::setAvailableInputDevices(audio_devices_t inputDevices)
François Gaffie20f06f92015-03-24 09:01:14 +0100300{
François Gaffie814ce802016-01-18 11:23:47 +0100301 ISelectionCriterionInterface *criterion =
François Gaffiea56b5c22018-02-21 18:04:39 +0100302 getElement<ISelectionCriterionInterface>(gInputDeviceCriterionName, mPolicyCriteria);
François Gaffie20f06f92015-03-24 09:01:14 +0100303 if (criterion == NULL) {
François Gaffiea56b5c22018-02-21 18:04:39 +0100304 ALOGE("%s: no criterion found for %s", __FUNCTION__, gInputDeviceCriterionName);
François Gaffie20f06f92015-03-24 09:01:14 +0100305 return DEAD_OBJECT;
306 }
François Gaffiea3e696d2015-12-18 09:38:43 +0100307 criterion->setCriterionState(inputDevices & ~AUDIO_DEVICE_BIT_IN);
308 applyPlatformConfiguration();
309 return NO_ERROR;
310}
François Gaffie20f06f92015-03-24 09:01:14 +0100311
François Gaffiea3e696d2015-12-18 09:38:43 +0100312status_t ParameterManagerWrapper::setAvailableOutputDevices(audio_devices_t outputDevices)
313{
François Gaffie814ce802016-01-18 11:23:47 +0100314 ISelectionCriterionInterface *criterion =
François Gaffiea56b5c22018-02-21 18:04:39 +0100315 getElement<ISelectionCriterionInterface>(gOutputDeviceCriterionName, mPolicyCriteria);
François Gaffiea3e696d2015-12-18 09:38:43 +0100316 if (criterion == NULL) {
François Gaffiea56b5c22018-02-21 18:04:39 +0100317 ALOGE("%s: no criterion found for %s", __FUNCTION__, gOutputDeviceCriterionName);
François Gaffiea3e696d2015-12-18 09:38:43 +0100318 return DEAD_OBJECT;
François Gaffie20f06f92015-03-24 09:01:14 +0100319 }
François Gaffiea3e696d2015-12-18 09:38:43 +0100320 criterion->setCriterionState(outputDevices);
François Gaffie20f06f92015-03-24 09:01:14 +0100321 applyPlatformConfiguration();
322 return NO_ERROR;
323}
324
325void ParameterManagerWrapper::applyPlatformConfiguration()
326{
327 mPfwConnector->applyConfigurations();
328}
329
330} // namespace audio_policy
331} // namespace android