blob: 099d55d04f7fc25e6aafa46996a7526662c4c280 [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>
Francois Gaffiea12de212021-10-22 10:54:33 +020026#include <cutils/bitops.h>
François Gaffie20f06f92015-03-24 09:01:14 +010027#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>
Francois Gaffiea12de212021-10-22 10:54:33 +020035#include <cinttypes>
François Gaffie20f06f92015-03-24 09:01:14 +010036#include <cmath>
37#include <utils/Log.h>
38
39using std::string;
40using std::map;
41using std::vector;
42
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
François Gaffieab1837a2019-10-15 10:48:50 +020097ParameterManagerWrapper::ParameterManagerWrapper(bool enableSchemaVerification,
98 const std::string &schemaUri)
François Gaffie20f06f92015-03-24 09:01:14 +010099 : mPfwConnectorLogger(new ParameterMgrPlatformConnectorLogger)
100{
101 // Connector
Mingwei Shic41dc112017-07-26 10:02:40 +0800102 if (access(mPolicyPfwVendorConfFileName, R_OK) == 0) {
103 mPfwConnector = new CParameterMgrPlatformConnector(mPolicyPfwVendorConfFileName);
104 } else {
105 mPfwConnector = new CParameterMgrPlatformConnector(mPolicyPfwDefaultConfFileName);
106 }
François Gaffie20f06f92015-03-24 09:01:14 +0100107
108 // Logger
109 mPfwConnector->setLogger(mPfwConnectorLogger);
François Gaffieab1837a2019-10-15 10:48:50 +0200110
111 // Schema validation
112 std::string error;
113 bool ret = mPfwConnector->setValidateSchemasOnStart(enableSchemaVerification, error);
114 ALOGE_IF(!ret, "Failed to activate schema validation: %s", error.c_str());
115 if (enableSchemaVerification && ret && !schemaUri.empty()) {
116 ALOGE("Schema verification activated with schema URI: %s", schemaUri.c_str());
117 mPfwConnector->setSchemaUri(schemaUri);
118 }
François Gaffie20f06f92015-03-24 09:01:14 +0100119}
120
François Gaffie7188f1a2018-11-02 14:35:42 +0100121status_t ParameterManagerWrapper::addCriterion(const std::string &name, bool isInclusive,
122 ValuePairs pairs, const std::string &defaultValue)
François Gaffiea56b5c22018-02-21 18:04:39 +0100123{
François Gaffie7188f1a2018-11-02 14:35:42 +0100124 ALOG_ASSERT(not isStarted(), "Cannot add a criterion if PFW is already started");
125 auto criterionType = mPfwConnector->createSelectionCriterionType(isInclusive);
126
127 for (auto pair : pairs) {
128 std::string error;
Francois Gaffiea12de212021-10-22 10:54:33 +0200129 ALOGV("%s: Adding pair %" PRIu64", %s for criterionType %s", __func__, std::get<0>(pair),
130 std::get<2>(pair).c_str(), name.c_str());
131 criterionType->addValuePair(std::get<0>(pair), std::get<2>(pair), error);
132
133 if (name == gOutputDeviceCriterionName) {
134 ALOGV("%s: Adding mOutputDeviceToCriterionTypeMap %d %" PRIu64" for criterionType %s",
135 __func__, std::get<1>(pair), std::get<0>(pair), name.c_str());
136 audio_devices_t androidType = static_cast<audio_devices_t>(std::get<1>(pair));
137 mOutputDeviceToCriterionTypeMap[androidType] = std::get<0>(pair);
138 }
139 if (name == gInputDeviceCriterionName) {
140 ALOGV("%s: Adding mInputDeviceToCriterionTypeMap %d %" PRIu64" for criterionType %s",
141 __func__, std::get<1>(pair), std::get<0>(pair), name.c_str());
142 audio_devices_t androidType = static_cast<audio_devices_t>(std::get<1>(pair));
143 mInputDeviceToCriterionTypeMap[androidType] = std::get<0>(pair);
144 }
François Gaffiea56b5c22018-02-21 18:04:39 +0100145 }
François Gaffie7188f1a2018-11-02 14:35:42 +0100146 ALOG_ASSERT(mPolicyCriteria.find(name) == mPolicyCriteria.end(),
147 "%s: Criterion %s already added", __FUNCTION__, name.c_str());
François Gaffiea56b5c22018-02-21 18:04:39 +0100148
François Gaffie7188f1a2018-11-02 14:35:42 +0100149 auto criterion = mPfwConnector->createSelectionCriterion(name, criterionType);
150 mPolicyCriteria[name] = criterion;
François Gaffiea56b5c22018-02-21 18:04:39 +0100151
François Gaffie7188f1a2018-11-02 14:35:42 +0100152 if (not defaultValue.empty()) {
Francois Gaffiea12de212021-10-22 10:54:33 +0200153 uint64_t numericalValue = 0;
François Gaffie7188f1a2018-11-02 14:35:42 +0100154 if (not criterionType->getNumericalValue(defaultValue.c_str(), numericalValue)) {
155 ALOGE("%s; trying to apply invalid default literal value (%s)", __FUNCTION__,
156 defaultValue.c_str());
François Gaffiea56b5c22018-02-21 18:04:39 +0100157 }
François Gaffie7188f1a2018-11-02 14:35:42 +0100158 criterion->setCriterionState(numericalValue);
François Gaffiea56b5c22018-02-21 18:04:39 +0100159 }
François Gaffie7188f1a2018-11-02 14:35:42 +0100160 return NO_ERROR;
François Gaffiea56b5c22018-02-21 18:04:39 +0100161}
162
François Gaffie20f06f92015-03-24 09:01:14 +0100163ParameterManagerWrapper::~ParameterManagerWrapper()
164{
165 // Unset logger
166 mPfwConnector->setLogger(NULL);
167 // Remove logger
168 delete mPfwConnectorLogger;
169 // Remove connector
170 delete mPfwConnector;
171}
172
François Gaffieab1837a2019-10-15 10:48:50 +0200173status_t ParameterManagerWrapper::start(std::string &error)
François Gaffie20f06f92015-03-24 09:01:14 +0100174{
175 ALOGD("%s: in", __FUNCTION__);
176 /// Start PFW
François Gaffie20f06f92015-03-24 09:01:14 +0100177 if (!mPfwConnector->start(error)) {
178 ALOGE("%s: Policy PFW start error: %s", __FUNCTION__, error.c_str());
179 return NO_INIT;
180 }
181 ALOGD("%s: Policy PFW successfully started!", __FUNCTION__);
182 return NO_ERROR;
183}
184
François Gaffie20f06f92015-03-24 09:01:14 +0100185template <typename T>
186T *ParameterManagerWrapper::getElement(const string &name, std::map<string, T *> &elementsMap)
187{
188 parameterManagerElementSupported<T>();
189 typename std::map<string, T *>::iterator it = elementsMap.find(name);
François Gaffie814ce802016-01-18 11:23:47 +0100190 ALOG_ASSERT(it != elementsMap.end(), "Element %s not found", name.c_str());
191 return it != elementsMap.end() ? it->second : NULL;
François Gaffie20f06f92015-03-24 09:01:14 +0100192}
193
194template <typename T>
195const T *ParameterManagerWrapper::getElement(const string &name, const std::map<string, T *> &elementsMap) const
196{
197 parameterManagerElementSupported<T>();
198 typename std::map<string, T *>::const_iterator it = elementsMap.find(name);
François Gaffie814ce802016-01-18 11:23:47 +0100199 ALOG_ASSERT(it != elementsMap.end(), "Element %s not found", name.c_str());
200 return it != elementsMap.end() ? it->second : NULL;
François Gaffie20f06f92015-03-24 09:01:14 +0100201}
202
François Gaffie20f06f92015-03-24 09:01:14 +0100203bool ParameterManagerWrapper::isStarted()
204{
205 return mPfwConnector && mPfwConnector->isStarted();
206}
207
208status_t ParameterManagerWrapper::setPhoneState(audio_mode_t mode)
209{
François Gaffie814ce802016-01-18 11:23:47 +0100210 ISelectionCriterionInterface *criterion =
François Gaffiea56b5c22018-02-21 18:04:39 +0100211 getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
François Gaffie814ce802016-01-18 11:23:47 +0100212 if (criterion == NULL) {
François Gaffiea56b5c22018-02-21 18:04:39 +0100213 ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
François Gaffie814ce802016-01-18 11:23:47 +0100214 return BAD_VALUE;
215 }
François Gaffie20f06f92015-03-24 09:01:14 +0100216 if (!isValueValidForCriterion(criterion, static_cast<int>(mode))) {
217 return BAD_VALUE;
218 }
219 criterion->setCriterionState((int)(mode));
220 applyPlatformConfiguration();
221 return NO_ERROR;
222}
223
224audio_mode_t ParameterManagerWrapper::getPhoneState() const
225{
226 const ISelectionCriterionInterface *criterion =
François Gaffiea56b5c22018-02-21 18:04:39 +0100227 getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
François Gaffie814ce802016-01-18 11:23:47 +0100228 if (criterion == NULL) {
François Gaffiea56b5c22018-02-21 18:04:39 +0100229 ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
François Gaffie814ce802016-01-18 11:23:47 +0100230 return AUDIO_MODE_NORMAL;
231 }
François Gaffie20f06f92015-03-24 09:01:14 +0100232 return static_cast<audio_mode_t>(criterion->getCriterionState());
233}
234
235status_t ParameterManagerWrapper::setForceUse(audio_policy_force_use_t usage,
236 audio_policy_forced_cfg_t config)
237{
238 // @todo: return an error on a unsupported value
239 if (usage > AUDIO_POLICY_FORCE_USE_CNT) {
240 return BAD_VALUE;
241 }
242
François Gaffie814ce802016-01-18 11:23:47 +0100243 ISelectionCriterionInterface *criterion =
244 getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
245 if (criterion == NULL) {
François Gaffiea56b5c22018-02-21 18:04:39 +0100246 ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
François Gaffie814ce802016-01-18 11:23:47 +0100247 return BAD_VALUE;
248 }
François Gaffie20f06f92015-03-24 09:01:14 +0100249 if (!isValueValidForCriterion(criterion, static_cast<int>(config))) {
250 return BAD_VALUE;
251 }
252 criterion->setCriterionState((int)config);
253 applyPlatformConfiguration();
254 return NO_ERROR;
255}
256
257audio_policy_forced_cfg_t ParameterManagerWrapper::getForceUse(audio_policy_force_use_t usage) const
258{
259 // @todo: return an error on a unsupported value
260 if (usage > AUDIO_POLICY_FORCE_USE_CNT) {
261 return AUDIO_POLICY_FORCE_NONE;
262 }
263 const ISelectionCriterionInterface *criterion =
264 getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
François Gaffie814ce802016-01-18 11:23:47 +0100265 if (criterion == NULL) {
François Gaffiea56b5c22018-02-21 18:04:39 +0100266 ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
François Gaffie814ce802016-01-18 11:23:47 +0100267 return AUDIO_POLICY_FORCE_NONE;
268 }
François Gaffie20f06f92015-03-24 09:01:14 +0100269 return static_cast<audio_policy_forced_cfg_t>(criterion->getCriterionState());
270}
271
272bool ParameterManagerWrapper::isValueValidForCriterion(ISelectionCriterionInterface *criterion,
273 int valueToCheck)
274{
275 const ISelectionCriterionTypeInterface *interface = criterion->getCriterionType();
276 string literalValue;
277 return interface->getLiteralValue(valueToCheck, literalValue);
278}
279
François Gaffieab1837a2019-10-15 10:48:50 +0200280status_t ParameterManagerWrapper::setDeviceConnectionState(
Francois Gaffiea12de212021-10-22 10:54:33 +0200281 audio_devices_t type, const std::string &address, audio_policy_dev_state_t state)
François Gaffiea56b5c22018-02-21 18:04:39 +0100282{
François Gaffieab1837a2019-10-15 10:48:50 +0200283 std::string criterionName = audio_is_output_device(type) ?
François Gaffiea56b5c22018-02-21 18:04:39 +0100284 gOutputDeviceAddressCriterionName : gInputDeviceAddressCriterionName;
285
François Gaffieab1837a2019-10-15 10:48:50 +0200286 ALOGV("%s: device with address %s %s", __FUNCTION__, address.c_str(),
François Gaffiea56b5c22018-02-21 18:04:39 +0100287 state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE? "disconnected" : "connected");
288 ISelectionCriterionInterface *criterion =
289 getElement<ISelectionCriterionInterface>(criterionName, mPolicyCriteria);
290
291 if (criterion == NULL) {
292 ALOGE("%s: no criterion found for %s", __FUNCTION__, criterionName.c_str());
293 return DEAD_OBJECT;
294 }
295
296 auto criterionType = criterion->getCriterionType();
Francois Gaffiea12de212021-10-22 10:54:33 +0200297 uint64_t deviceAddressId;
François Gaffieab1837a2019-10-15 10:48:50 +0200298 if (not criterionType->getNumericalValue(address.c_str(), deviceAddressId)) {
François Gaffie376740f2020-01-16 09:08:04 +0100299 ALOGW("%s: unknown device address reported (%s) for criterion %s", __FUNCTION__,
300 address.c_str(), criterionName.c_str());
François Gaffiea56b5c22018-02-21 18:04:39 +0100301 return BAD_TYPE;
302 }
303 int currentValueMask = criterion->getCriterionState();
304 if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
305 currentValueMask |= deviceAddressId;
306 }
307 else {
308 currentValueMask &= ~deviceAddressId;
309 }
310 criterion->setCriterionState(currentValueMask);
311 return NO_ERROR;
312}
313
Francois Gaffiea12de212021-10-22 10:54:33 +0200314status_t ParameterManagerWrapper::setAvailableInputDevices(const DeviceTypeSet &types)
François Gaffie20f06f92015-03-24 09:01:14 +0100315{
François Gaffie814ce802016-01-18 11:23:47 +0100316 ISelectionCriterionInterface *criterion =
François Gaffiea56b5c22018-02-21 18:04:39 +0100317 getElement<ISelectionCriterionInterface>(gInputDeviceCriterionName, mPolicyCriteria);
François Gaffie20f06f92015-03-24 09:01:14 +0100318 if (criterion == NULL) {
Francois Gaffiea12de212021-10-22 10:54:33 +0200319 ALOGE("%s: no criterion found for %s", __func__, gInputDeviceCriterionName);
François Gaffie20f06f92015-03-24 09:01:14 +0100320 return DEAD_OBJECT;
321 }
Francois Gaffiea12de212021-10-22 10:54:33 +0200322 criterion->setCriterionState(convertDeviceTypesToCriterionValue(types));
François Gaffiea3e696d2015-12-18 09:38:43 +0100323 applyPlatformConfiguration();
324 return NO_ERROR;
325}
François Gaffie20f06f92015-03-24 09:01:14 +0100326
Francois Gaffiea12de212021-10-22 10:54:33 +0200327status_t ParameterManagerWrapper::setAvailableOutputDevices(const DeviceTypeSet &types)
François Gaffiea3e696d2015-12-18 09:38:43 +0100328{
François Gaffie814ce802016-01-18 11:23:47 +0100329 ISelectionCriterionInterface *criterion =
François Gaffiea56b5c22018-02-21 18:04:39 +0100330 getElement<ISelectionCriterionInterface>(gOutputDeviceCriterionName, mPolicyCriteria);
François Gaffiea3e696d2015-12-18 09:38:43 +0100331 if (criterion == NULL) {
Francois Gaffiea12de212021-10-22 10:54:33 +0200332 ALOGE("%s: no criterion found for %s", __func__, gOutputDeviceCriterionName);
François Gaffiea3e696d2015-12-18 09:38:43 +0100333 return DEAD_OBJECT;
François Gaffie20f06f92015-03-24 09:01:14 +0100334 }
Francois Gaffiea12de212021-10-22 10:54:33 +0200335 criterion->setCriterionState(convertDeviceTypesToCriterionValue(types));
François Gaffie20f06f92015-03-24 09:01:14 +0100336 applyPlatformConfiguration();
337 return NO_ERROR;
338}
339
340void ParameterManagerWrapper::applyPlatformConfiguration()
341{
342 mPfwConnector->applyConfigurations();
343}
344
Francois Gaffiea12de212021-10-22 10:54:33 +0200345uint64_t ParameterManagerWrapper::convertDeviceTypeToCriterionValue(audio_devices_t type) const {
346 bool isOut = audio_is_output_devices(type);
347 uint32_t typeMask = isOut ? type : (type & ~AUDIO_DEVICE_BIT_IN);
348
349 const auto &adapters = isOut ? mOutputDeviceToCriterionTypeMap : mInputDeviceToCriterionTypeMap;
350 // Only multibit devices need adaptation.
351 if (popcount(typeMask) > 1) {
352 const auto &adapter = adapters.find(type);
353 if (adapter != adapters.end()) {
354 ALOGV("%s: multibit device %d converted to criterion %" PRIu64, __func__, type,
355 adapter->second);
356 return adapter->second;
357 }
358 ALOGE("%s: failed to find map for multibit device %d", __func__, type);
359 return 0;
360 }
361 return typeMask;
362}
363
364uint64_t ParameterManagerWrapper::convertDeviceTypesToCriterionValue(
365 const DeviceTypeSet &types) const {
366 uint64_t criterionValue = 0;
367 for (const auto &type : types) {
368 criterionValue += convertDeviceTypeToCriterionValue(type);
369 }
370 return criterionValue;
371}
372
373DeviceTypeSet ParameterManagerWrapper::convertDeviceCriterionValueToDeviceTypes(
374 uint64_t criterionValue, bool isOut) const {
375 DeviceTypeSet deviceTypes;
376 const auto &adapters = isOut ? mOutputDeviceToCriterionTypeMap : mInputDeviceToCriterionTypeMap;
377 for (const auto &adapter : adapters) {
378 if ((adapter.second & criterionValue) == adapter.second) {
379 deviceTypes.insert(adapter.first);
380 }
381 }
382 return deviceTypes;
383}
384
François Gaffie20f06f92015-03-24 09:01:14 +0100385} // namespace audio_policy
386} // namespace android