• 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 <ParameterMgrPlatformConnector.h>
22 #include <SelectionCriterionTypeInterface.h>
23 #include <SelectionCriterionInterface.h>
24 #include <media/convert.h>
25 #include <algorithm>
26 #include <cutils/bitops.h>
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 <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 const char *const ParameterManagerWrapper::mPolicyPfwDefaultConfFileName =
67     "/etc/parameter-framework/ParameterFrameworkConfigurationPolicy.xml";
68 const char *const ParameterManagerWrapper::mPolicyPfwVendorConfFileName =
69     "/vendor/etc/parameter-framework/ParameterFrameworkConfigurationPolicy.xml";
70 
71 static const char *const gInputDeviceCriterionName = "AvailableInputDevices";
72 static const char *const gOutputDeviceCriterionName = "AvailableOutputDevices";
73 static const char *const gPhoneStateCriterionName = "TelephonyMode";
74 static const char *const gOutputDeviceAddressCriterionName = "AvailableOutputDevicesAddresses";
75 static 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  */
80 static 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 
92 template <>
93 struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionInterface> {};
94 template <>
95 struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionTypeInterface> {};
96 
ParameterManagerWrapper(bool enableSchemaVerification,const std::string & schemaUri)97 ParameterManagerWrapper::ParameterManagerWrapper(bool enableSchemaVerification,
98                                                  const std::string &schemaUri)
99     : mPfwConnectorLogger(new ParameterMgrPlatformConnectorLogger)
100 {
101     // Connector
102     if (access(mPolicyPfwVendorConfFileName, R_OK) == 0) {
103         mPfwConnector = new CParameterMgrPlatformConnector(mPolicyPfwVendorConfFileName);
104     } else {
105         mPfwConnector = new CParameterMgrPlatformConnector(mPolicyPfwDefaultConfFileName);
106     }
107 
108     // Logger
109     mPfwConnector->setLogger(mPfwConnectorLogger);
110 
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     }
119 }
120 
addCriterion(const std::string & name,bool isInclusive,ValuePairs pairs,const std::string & defaultValue)121 status_t ParameterManagerWrapper::addCriterion(const std::string &name, bool isInclusive,
122                                                ValuePairs pairs, const std::string &defaultValue)
123 {
124     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;
129         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         }
145     }
146     ALOG_ASSERT(mPolicyCriteria.find(name) == mPolicyCriteria.end(),
147                 "%s: Criterion %s already added", __FUNCTION__, name.c_str());
148 
149     auto criterion = mPfwConnector->createSelectionCriterion(name, criterionType);
150     mPolicyCriteria[name] = criterion;
151 
152     if (not defaultValue.empty()) {
153         uint64_t numericalValue = 0;
154         if (not criterionType->getNumericalValue(defaultValue.c_str(), numericalValue)) {
155             ALOGE("%s; trying to apply invalid default literal value (%s)", __FUNCTION__,
156                   defaultValue.c_str());
157         }
158         criterion->setCriterionState(numericalValue);
159     }
160     return NO_ERROR;
161 }
162 
~ParameterManagerWrapper()163 ParameterManagerWrapper::~ParameterManagerWrapper()
164 {
165     // Unset logger
166     mPfwConnector->setLogger(NULL);
167     // Remove logger
168     delete mPfwConnectorLogger;
169     // Remove connector
170     delete mPfwConnector;
171 }
172 
start(std::string & error)173 status_t ParameterManagerWrapper::start(std::string &error)
174 {
175     ALOGD("%s: in", __FUNCTION__);
176     /// Start PFW
177     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 
185 template <typename T>
getElement(const string & name,std::map<string,T * > & elementsMap)186 T *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);
190     ALOG_ASSERT(it != elementsMap.end(), "Element %s not found", name.c_str());
191     return it != elementsMap.end() ? it->second : NULL;
192 }
193 
194 template <typename T>
getElement(const string & name,const std::map<string,T * > & elementsMap) const195 const 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);
199     ALOG_ASSERT(it != elementsMap.end(), "Element %s not found", name.c_str());
200     return it != elementsMap.end() ? it->second : NULL;
201 }
202 
isStarted()203 bool ParameterManagerWrapper::isStarted()
204 {
205     return mPfwConnector && mPfwConnector->isStarted();
206 }
207 
setPhoneState(audio_mode_t mode)208 status_t ParameterManagerWrapper::setPhoneState(audio_mode_t mode)
209 {
210     ISelectionCriterionInterface *criterion =
211             getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
212     if (criterion == NULL) {
213         ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
214         return BAD_VALUE;
215     }
216     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 
getPhoneState() const224 audio_mode_t ParameterManagerWrapper::getPhoneState() const
225 {
226     const ISelectionCriterionInterface *criterion =
227             getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
228     if (criterion == NULL) {
229         ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
230         return AUDIO_MODE_NORMAL;
231     }
232     return static_cast<audio_mode_t>(criterion->getCriterionState());
233 }
234 
setForceUse(audio_policy_force_use_t usage,audio_policy_forced_cfg_t config)235 status_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 
243     ISelectionCriterionInterface *criterion =
244             getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
245     if (criterion == NULL) {
246         ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
247         return BAD_VALUE;
248     }
249     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 
getForceUse(audio_policy_force_use_t usage) const257 audio_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);
265     if (criterion == NULL) {
266         ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
267         return AUDIO_POLICY_FORCE_NONE;
268     }
269     return static_cast<audio_policy_forced_cfg_t>(criterion->getCriterionState());
270 }
271 
isValueValidForCriterion(ISelectionCriterionInterface * criterion,int valueToCheck)272 bool 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 
setDeviceConnectionState(audio_devices_t type,const std::string & address,audio_policy_dev_state_t state)280 status_t ParameterManagerWrapper::setDeviceConnectionState(
281         audio_devices_t type, const std::string &address, audio_policy_dev_state_t state)
282 {
283     std::string criterionName = audio_is_output_device(type) ?
284                 gOutputDeviceAddressCriterionName : gInputDeviceAddressCriterionName;
285 
286     ALOGV("%s: device with address %s %s", __FUNCTION__, address.c_str(),
287           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();
297     uint64_t deviceAddressId;
298     if (not criterionType->getNumericalValue(address.c_str(), deviceAddressId)) {
299         ALOGW("%s: unknown device address reported (%s) for criterion %s", __FUNCTION__,
300               address.c_str(), criterionName.c_str());
301         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 
setAvailableInputDevices(const DeviceTypeSet & types)314 status_t ParameterManagerWrapper::setAvailableInputDevices(const DeviceTypeSet &types)
315 {
316     ISelectionCriterionInterface *criterion =
317             getElement<ISelectionCriterionInterface>(gInputDeviceCriterionName, mPolicyCriteria);
318     if (criterion == NULL) {
319         ALOGE("%s: no criterion found for %s", __func__, gInputDeviceCriterionName);
320         return DEAD_OBJECT;
321     }
322     criterion->setCriterionState(convertDeviceTypesToCriterionValue(types));
323     applyPlatformConfiguration();
324     return NO_ERROR;
325 }
326 
setAvailableOutputDevices(const DeviceTypeSet & types)327 status_t ParameterManagerWrapper::setAvailableOutputDevices(const DeviceTypeSet &types)
328 {
329     ISelectionCriterionInterface *criterion =
330             getElement<ISelectionCriterionInterface>(gOutputDeviceCriterionName, mPolicyCriteria);
331     if (criterion == NULL) {
332         ALOGE("%s: no criterion found for %s", __func__, gOutputDeviceCriterionName);
333         return DEAD_OBJECT;
334     }
335     criterion->setCriterionState(convertDeviceTypesToCriterionValue(types));
336     applyPlatformConfiguration();
337     return NO_ERROR;
338 }
339 
applyPlatformConfiguration()340 void ParameterManagerWrapper::applyPlatformConfiguration()
341 {
342     mPfwConnector->applyConfigurations();
343 }
344 
convertDeviceTypeToCriterionValue(audio_devices_t type) const345 uint64_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 
convertDeviceTypesToCriterionValue(const DeviceTypeSet & types) const364 uint64_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 
convertDeviceCriterionValueToDeviceTypes(uint64_t criterionValue,bool isOut) const373 DeviceTypeSet 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 
385 } // namespace audio_policy
386 } // namespace android
387