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::Serializer"
18 //#define LOG_NDEBUG 0
19
20 #include <memory>
21 #include <string>
22 #include <utility>
23
24 #include <hidl/Status.h>
25 #include <libxml/parser.h>
26 #include <libxml/xinclude.h>
27 #include <media/convert.h>
28 #include <utils/Log.h>
29 #include <utils/StrongPointer.h>
30 #include <utils/Errors.h>
31 #include <utils/RefBase.h>
32 #include "Serializer.h"
33 #include "TypeConverter.h"
34
35 namespace android {
36
37 namespace {
38
39 // TODO(mnaganov): Consider finding an alternative for using HIDL code.
40 using hardware::Return;
41 using hardware::Status;
42 using utilities::convertTo;
43
44 template<typename E, typename C>
45 struct AndroidCollectionTraits {
46 typedef sp<E> Element;
47 typedef C Collection;
48 typedef void* PtrSerializingCtx;
49
addElementToCollectionandroid::__anonaf21c8190111::AndroidCollectionTraits50 static status_t addElementToCollection(const Element &element, Collection *collection) {
51 return collection->add(element) >= 0 ? NO_ERROR : BAD_VALUE;
52 }
53 };
54
55 template<typename C>
56 struct StdCollectionTraits {
57 typedef C Collection;
58 typedef typename C::value_type Element;
59 typedef void* PtrSerializingCtx;
60
addElementToCollectionandroid::__anonaf21c8190111::StdCollectionTraits61 static status_t addElementToCollection(const Element &element, Collection *collection) {
62 auto pair = collection->insert(element);
63 return pair.second ? NO_ERROR : BAD_VALUE;
64 }
65 };
66
67 struct AudioGainTraits : public AndroidCollectionTraits<AudioGain, AudioGains>
68 {
69 static constexpr const char *tag = "gain";
70 static constexpr const char *collectionTag = "gains";
71
72 struct Attributes
73 {
74 /** gain modes supported, e.g. AUDIO_GAIN_MODE_CHANNELS. */
75 static constexpr const char *mode = "mode";
76 /** controlled channels, needed if mode AUDIO_GAIN_MODE_CHANNELS. */
77 static constexpr const char *channelMask = "channel_mask";
78 static constexpr const char *minValueMB = "minValueMB"; /**< min value in millibel. */
79 static constexpr const char *maxValueMB = "maxValueMB"; /**< max value in millibel. */
80 /** default value in millibel. */
81 static constexpr const char *defaultValueMB = "defaultValueMB";
82 static constexpr const char *stepValueMB = "stepValueMB"; /**< step value in millibel. */
83 /** needed if mode AUDIO_GAIN_MODE_RAMP. */
84 static constexpr const char *minRampMs = "minRampMs";
85 /** needed if mode AUDIO_GAIN_MODE_RAMP. */
86 static constexpr const char *maxRampMs = "maxRampMs";
87 /** needed to allow use setPortGain instead of setStreamVolume. */
88 static constexpr const char *useForVolume = "useForVolume";
89
90 };
91
92 static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext);
93 // No children
94 };
95
96 // A profile section contains a name, one audio format and the list of supported sampling rates
97 // and channel masks for this format
98 struct AudioProfileTraits : public AndroidCollectionTraits<AudioProfile, AudioProfileVector>
99 {
100 static constexpr const char *tag = "profile";
101 static constexpr const char *collectionTag = "profiles";
102
103 struct Attributes
104 {
105 static constexpr const char *samplingRates = "samplingRates";
106 static constexpr const char *format = "format";
107 static constexpr const char *channelMasks = "channelMasks";
108 };
109
110 static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext);
111 };
112
113 struct MixPortTraits : public AndroidCollectionTraits<IOProfile, IOProfileCollection>
114 {
115 static constexpr const char *tag = "mixPort";
116 static constexpr const char *collectionTag = "mixPorts";
117
118 struct Attributes
119 {
120 static constexpr const char *name = "name";
121 static constexpr const char *role = "role";
122 static constexpr const char *roleSource = "source"; /**< <attribute role source value>. */
123 static constexpr const char *flags = "flags";
124 static constexpr const char *maxOpenCount = "maxOpenCount";
125 static constexpr const char *maxActiveCount = "maxActiveCount";
126 };
127
128 static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext);
129 // Children: GainTraits
130 };
131
132 struct DevicePortTraits : public AndroidCollectionTraits<DeviceDescriptor, DeviceVector>
133 {
134 static constexpr const char *tag = "devicePort";
135 static constexpr const char *collectionTag = "devicePorts";
136
137 struct Attributes
138 {
139 /** <device tag name>: any string without space. */
140 static constexpr const char *tagName = "tagName";
141 static constexpr const char *type = "type"; /**< <device type>. */
142 static constexpr const char *role = "role"; /**< <device role: sink or source>. */
143 static constexpr const char *roleSource = "source"; /**< <attribute role source value>. */
144 /** optional: device address, char string less than 64. */
145 static constexpr const char *address = "address";
146 /** optional: the list of encoded audio formats that are known to be supported. */
147 static constexpr const char *encodedFormats = "encodedFormats";
148 };
149
150 static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext);
151 // Children: GainTraits (optional)
152 };
153
154 struct RouteTraits : public AndroidCollectionTraits<AudioRoute, AudioRouteVector>
155 {
156 static constexpr const char *tag = "route";
157 static constexpr const char *collectionTag = "routes";
158
159 struct Attributes
160 {
161 static constexpr const char *type = "type"; /**< <route type>: mix or mux. */
162 static constexpr const char *typeMix = "mix"; /**< type attribute mix value. */
163 static constexpr const char *sink = "sink"; /**< <sink: involved in this route>. */
164 /** sources: all source that can be involved in this route. */
165 static constexpr const char *sources = "sources";
166 };
167
168 typedef HwModule *PtrSerializingCtx;
169
170 static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext);
171 };
172
173 struct ModuleTraits : public AndroidCollectionTraits<HwModule, HwModuleCollection>
174 {
175 static constexpr const char *tag = "module";
176 static constexpr const char *collectionTag = "modules";
177
178 static constexpr const char *childAttachedDevicesTag = "attachedDevices";
179 static constexpr const char *childAttachedDeviceTag = "item";
180 static constexpr const char *childDefaultOutputDeviceTag = "defaultOutputDevice";
181
182 struct Attributes
183 {
184 static constexpr const char *name = "name";
185 static constexpr const char *version = "halVersion";
186 };
187
188 typedef AudioPolicyConfig *PtrSerializingCtx;
189
190 static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext);
191 // Children: mixPortTraits, devicePortTraits, and routeTraits
192 // Need to call deserialize on each child
193 };
194
195 struct GlobalConfigTraits
196 {
197 static constexpr const char *tag = "globalConfiguration";
198
199 struct Attributes
200 {
201 static constexpr const char *speakerDrcEnabled = "speaker_drc_enabled";
202 static constexpr const char *engineLibrarySuffix = "engine_library";
203 };
204
205 static status_t deserialize(const xmlNode *root, AudioPolicyConfig *config);
206 };
207
208 struct SurroundSoundTraits
209 {
210 static constexpr const char *tag = "surroundSound";
211
212 static status_t deserialize(const xmlNode *root, AudioPolicyConfig *config);
213 // Children: SurroundSoundFormatTraits
214 };
215
216 struct SurroundSoundFormatTraits : public StdCollectionTraits<AudioPolicyConfig::SurroundFormats>
217 {
218 static constexpr const char *tag = "format";
219 static constexpr const char *collectionTag = "formats";
220
221 struct Attributes
222 {
223 static constexpr const char *name = "name";
224 static constexpr const char *subformats = "subformats";
225 };
226
227 static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext);
228 };
229
230 class PolicySerializer
231 {
232 public:
PolicySerializer()233 PolicySerializer() : mVersion{std::to_string(gMajor) + "." + std::to_string(gMinor)}
234 {
235 ALOGV("%s: Version=%s Root=%s", __func__, mVersion.c_str(), rootName);
236 }
237 status_t deserialize(const char *configFile, AudioPolicyConfig *config);
238
239 private:
240 static constexpr const char *rootName = "audioPolicyConfiguration";
241 static constexpr const char *versionAttribute = "version";
242 static constexpr uint32_t gMajor = 1; /**< the major number of the policy xml format version. */
243 static constexpr uint32_t gMinor = 0; /**< the minor number of the policy xml format version. */
244
245 typedef AudioPolicyConfig Element;
246
247 const std::string mVersion;
248
249 // Children: ModulesTraits, VolumeTraits, SurroundSoundTraits (optional)
250 };
251
252 template <class T>
253 constexpr void (*xmlDeleter)(T* t);
254 template <>
255 constexpr auto xmlDeleter<xmlDoc> = xmlFreeDoc;
256 // http://b/111067277 - Add back constexpr when we switch to C++17.
257 template <>
__anonaf21c8190202(xmlChar *s) 258 auto xmlDeleter<xmlChar> = [](xmlChar *s) { xmlFree(s); };
259
260 /** @return a unique_ptr with the correct deleter for the libxml2 object. */
261 template <class T>
make_xmlUnique(T * t)262 constexpr auto make_xmlUnique(T *t) {
263 // Wrap deleter in lambda to enable empty base optimization
264 auto deleter = [](T *t) { xmlDeleter<T>(t); };
265 return std::unique_ptr<T, decltype(deleter)>{t, deleter};
266 }
267
getXmlAttribute(const xmlNode * cur,const char * attribute)268 std::string getXmlAttribute(const xmlNode *cur, const char *attribute)
269 {
270 auto xmlValue = make_xmlUnique(xmlGetProp(cur, reinterpret_cast<const xmlChar*>(attribute)));
271 if (xmlValue == nullptr) {
272 return "";
273 }
274 std::string value(reinterpret_cast<const char*>(xmlValue.get()));
275 return value;
276 }
277
278 template <class Trait>
getReference(const xmlNode * cur,const std::string & refName)279 const xmlNode* getReference(const xmlNode *cur, const std::string &refName)
280 {
281 for (; cur != NULL; cur = cur->next) {
282 if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::collectionTag))) {
283 for (const xmlNode *child = cur->children; child != NULL; child = child->next) {
284 if ((!xmlStrcmp(child->name,
285 reinterpret_cast<const xmlChar*>(Trait::referenceTag)))) {
286 std::string name = getXmlAttribute(child, Trait::Attributes::referenceName);
287 if (refName == name) {
288 return child;
289 }
290 }
291 }
292 }
293 }
294 return NULL;
295 }
296
297 template <class Trait>
deserializeCollection(const xmlNode * cur,typename Trait::Collection * collection,typename Trait::PtrSerializingCtx serializingContext)298 status_t deserializeCollection(const xmlNode *cur,
299 typename Trait::Collection *collection,
300 typename Trait::PtrSerializingCtx serializingContext)
301 {
302 for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
303 const xmlNode *child = NULL;
304 if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::collectionTag))) {
305 child = cur->xmlChildrenNode;
306 } else if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::tag))) {
307 child = cur;
308 }
309 for (; child != NULL; child = child->next) {
310 if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>(Trait::tag))) {
311 auto element = Trait::deserialize(child, serializingContext);
312 if (element.isOk()) {
313 status_t status = Trait::addElementToCollection(element, collection);
314 if (status != NO_ERROR) {
315 ALOGE("%s: could not add element to %s collection", __func__,
316 Trait::collectionTag);
317 return status;
318 }
319 } else {
320 return BAD_VALUE;
321 }
322 }
323 }
324 if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::tag))) {
325 return NO_ERROR;
326 }
327 }
328 return NO_ERROR;
329 }
330
deserialize(const xmlNode * cur,PtrSerializingCtx)331 Return<AudioGainTraits::Element> AudioGainTraits::deserialize(const xmlNode *cur,
332 PtrSerializingCtx /*serializingContext*/)
333 {
334 static uint32_t index = 0;
335 Element gain = new AudioGain(index++, true);
336
337 std::string mode = getXmlAttribute(cur, Attributes::mode);
338 if (!mode.empty()) {
339 gain->setMode(GainModeConverter::maskFromString(mode));
340 }
341
342 std::string channelsLiteral = getXmlAttribute(cur, Attributes::channelMask);
343 if (!channelsLiteral.empty()) {
344 gain->setChannelMask(channelMaskFromString(channelsLiteral));
345 }
346
347 std::string minValueMBLiteral = getXmlAttribute(cur, Attributes::minValueMB);
348 int32_t minValueMB;
349 if (!minValueMBLiteral.empty() && convertTo(minValueMBLiteral, minValueMB)) {
350 gain->setMinValueInMb(minValueMB);
351 }
352
353 std::string maxValueMBLiteral = getXmlAttribute(cur, Attributes::maxValueMB);
354 int32_t maxValueMB;
355 if (!maxValueMBLiteral.empty() && convertTo(maxValueMBLiteral, maxValueMB)) {
356 gain->setMaxValueInMb(maxValueMB);
357 }
358
359 std::string defaultValueMBLiteral = getXmlAttribute(cur, Attributes::defaultValueMB);
360 int32_t defaultValueMB;
361 if (!defaultValueMBLiteral.empty() && convertTo(defaultValueMBLiteral, defaultValueMB)) {
362 gain->setDefaultValueInMb(defaultValueMB);
363 }
364
365 std::string stepValueMBLiteral = getXmlAttribute(cur, Attributes::stepValueMB);
366 uint32_t stepValueMB;
367 if (!stepValueMBLiteral.empty() && convertTo(stepValueMBLiteral, stepValueMB)) {
368 gain->setStepValueInMb(stepValueMB);
369 }
370
371 std::string minRampMsLiteral = getXmlAttribute(cur, Attributes::minRampMs);
372 uint32_t minRampMs;
373 if (!minRampMsLiteral.empty() && convertTo(minRampMsLiteral, minRampMs)) {
374 gain->setMinRampInMs(minRampMs);
375 }
376
377 std::string maxRampMsLiteral = getXmlAttribute(cur, Attributes::maxRampMs);
378 uint32_t maxRampMs;
379 if (!maxRampMsLiteral.empty() && convertTo(maxRampMsLiteral, maxRampMs)) {
380 gain->setMaxRampInMs(maxRampMs);
381 }
382 std::string useForVolumeLiteral = getXmlAttribute(cur, Attributes::useForVolume);
383 bool useForVolume = false;
384 if (!useForVolumeLiteral.empty() && convertTo(useForVolumeLiteral, useForVolume)) {
385 gain->setUseForVolume(useForVolume);
386 }
387 ALOGV("%s: adding new gain mode %08x channel mask %08x min mB %d max mB %d UseForVolume: %d",
388 __func__, gain->getMode(), gain->getChannelMask(), gain->getMinValueInMb(),
389 gain->getMaxValueInMb(), useForVolume);
390
391 if (gain->getMode() != 0) {
392 return gain;
393 } else {
394 return Status::fromStatusT(BAD_VALUE);
395 }
396 }
397
deserialize(const xmlNode * cur,PtrSerializingCtx)398 Return<AudioProfileTraits::Element> AudioProfileTraits::deserialize(const xmlNode *cur,
399 PtrSerializingCtx /*serializingContext*/)
400 {
401 std::string samplingRates = getXmlAttribute(cur, Attributes::samplingRates);
402 std::string format = getXmlAttribute(cur, Attributes::format);
403 std::string channels = getXmlAttribute(cur, Attributes::channelMasks);
404
405 Element profile = new AudioProfile(formatFromString(format, gDynamicFormat),
406 channelMasksFromString(channels, ","),
407 samplingRatesFromString(samplingRates, ","));
408
409 profile->setDynamicFormat(profile->getFormat() == gDynamicFormat);
410 profile->setDynamicChannels(profile->getChannels().empty());
411 profile->setDynamicRate(profile->getSampleRates().empty());
412
413 return profile;
414 }
415
deserialize(const xmlNode * child,PtrSerializingCtx)416 Return<MixPortTraits::Element> MixPortTraits::deserialize(const xmlNode *child,
417 PtrSerializingCtx /*serializingContext*/)
418 {
419 std::string name = getXmlAttribute(child, Attributes::name);
420 if (name.empty()) {
421 ALOGE("%s: No %s found", __func__, Attributes::name);
422 return Status::fromStatusT(BAD_VALUE);
423 }
424 ALOGV("%s: %s %s=%s", __func__, tag, Attributes::name, name.c_str());
425 std::string role = getXmlAttribute(child, Attributes::role);
426 if (role.empty()) {
427 ALOGE("%s: No %s found", __func__, Attributes::role);
428 return Status::fromStatusT(BAD_VALUE);
429 }
430 ALOGV("%s: Role=%s", __func__, role.c_str());
431 audio_port_role_t portRole = (role == Attributes::roleSource) ?
432 AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
433
434 Element mixPort = new IOProfile(name, portRole);
435
436 AudioProfileTraits::Collection profiles;
437 status_t status = deserializeCollection<AudioProfileTraits>(child, &profiles, NULL);
438 if (status != NO_ERROR) {
439 return Status::fromStatusT(status);
440 }
441 if (profiles.empty()) {
442 profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
443 }
444 // The audio profiles are in order of listed in audio policy configuration file.
445 // Sort audio profiles accroding to the format.
446 sortAudioProfiles(profiles);
447 mixPort->setAudioProfiles(profiles);
448
449 std::string flags = getXmlAttribute(child, Attributes::flags);
450 if (!flags.empty()) {
451 // Source role
452 if (portRole == AUDIO_PORT_ROLE_SOURCE) {
453 mixPort->setFlags(OutputFlagConverter::maskFromString(flags));
454 } else {
455 // Sink role
456 mixPort->setFlags(InputFlagConverter::maskFromString(flags));
457 }
458 }
459 std::string maxOpenCount = getXmlAttribute(child, Attributes::maxOpenCount);
460 if (!maxOpenCount.empty()) {
461 convertTo(maxOpenCount, mixPort->maxOpenCount);
462 }
463 std::string maxActiveCount = getXmlAttribute(child, Attributes::maxActiveCount);
464 if (!maxActiveCount.empty()) {
465 convertTo(maxActiveCount, mixPort->maxActiveCount);
466 }
467 // Deserialize children
468 AudioGainTraits::Collection gains;
469 status = deserializeCollection<AudioGainTraits>(child, &gains, NULL);
470 if (status != NO_ERROR) {
471 return Status::fromStatusT(status);
472 }
473 mixPort->setGains(gains);
474
475 return mixPort;
476 }
477
deserialize(const xmlNode * cur,PtrSerializingCtx)478 Return<DevicePortTraits::Element> DevicePortTraits::deserialize(const xmlNode *cur,
479 PtrSerializingCtx /*serializingContext*/)
480 {
481 std::string name = getXmlAttribute(cur, Attributes::tagName);
482 if (name.empty()) {
483 ALOGE("%s: No %s found", __func__, Attributes::tagName);
484 return Status::fromStatusT(BAD_VALUE);
485 }
486 ALOGV("%s: %s %s=%s", __func__, tag, Attributes::tagName, name.c_str());
487 std::string typeName = getXmlAttribute(cur, Attributes::type);
488 if (typeName.empty()) {
489 ALOGE("%s: no type for %s", __func__, name.c_str());
490 return Status::fromStatusT(BAD_VALUE);
491 }
492 ALOGV("%s: %s %s=%s", __func__, tag, Attributes::type, typeName.c_str());
493 std::string role = getXmlAttribute(cur, Attributes::role);
494 if (role.empty()) {
495 ALOGE("%s: No %s found", __func__, Attributes::role);
496 return Status::fromStatusT(BAD_VALUE);
497 }
498 ALOGV("%s: %s %s=%s", __func__, tag, Attributes::role, role.c_str());
499 audio_port_role_t portRole = (role == Attributes::roleSource) ?
500 AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
501
502 audio_devices_t type = AUDIO_DEVICE_NONE;
503 if (!deviceFromString(typeName, type) ||
504 (!audio_is_input_device(type) && portRole == AUDIO_PORT_ROLE_SOURCE) ||
505 (!audio_is_output_devices(type) && portRole == AUDIO_PORT_ROLE_SINK)) {
506 ALOGW("%s: bad type %08x", __func__, type);
507 return Status::fromStatusT(BAD_VALUE);
508 }
509 std::string encodedFormatsLiteral = getXmlAttribute(cur, Attributes::encodedFormats);
510 ALOGV("%s: %s %s=%s", __func__, tag, Attributes::encodedFormats, encodedFormatsLiteral.c_str());
511 FormatVector encodedFormats;
512 if (!encodedFormatsLiteral.empty()) {
513 encodedFormats = formatsFromString(encodedFormatsLiteral, " ");
514 }
515 std::string address = getXmlAttribute(cur, Attributes::address);
516 Element deviceDesc = new DeviceDescriptor(type, name, address, encodedFormats);
517
518 AudioProfileTraits::Collection profiles;
519 status_t status = deserializeCollection<AudioProfileTraits>(cur, &profiles, NULL);
520 if (status != NO_ERROR) {
521 return Status::fromStatusT(status);
522 }
523 if (profiles.empty()) {
524 profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
525 }
526 // The audio profiles are in order of listed in audio policy configuration file.
527 // Sort audio profiles accroding to the format.
528 sortAudioProfiles(profiles);
529 deviceDesc->setAudioProfiles(profiles);
530
531 // Deserialize AudioGain children
532 status = deserializeCollection<AudioGainTraits>(cur, &deviceDesc->mGains, NULL);
533 if (status != NO_ERROR) {
534 return Status::fromStatusT(status);
535 }
536 ALOGV("%s: adding device tag %s type %08x address %s", __func__,
537 deviceDesc->getName().c_str(), type, deviceDesc->address().c_str());
538 return deviceDesc;
539 }
540
deserialize(const xmlNode * cur,PtrSerializingCtx ctx)541 Return<RouteTraits::Element> RouteTraits::deserialize(const xmlNode *cur, PtrSerializingCtx ctx)
542 {
543 std::string type = getXmlAttribute(cur, Attributes::type);
544 if (type.empty()) {
545 ALOGE("%s: No %s found", __func__, Attributes::type);
546 return Status::fromStatusT(BAD_VALUE);
547 }
548 audio_route_type_t routeType = (type == Attributes::typeMix) ?
549 AUDIO_ROUTE_MIX : AUDIO_ROUTE_MUX;
550
551 ALOGV("%s: %s %s=%s", __func__, tag, Attributes::type, type.c_str());
552 Element route = new AudioRoute(routeType);
553
554 std::string sinkAttr = getXmlAttribute(cur, Attributes::sink);
555 if (sinkAttr.empty()) {
556 ALOGE("%s: No %s found", __func__, Attributes::sink);
557 return Status::fromStatusT(BAD_VALUE);
558 }
559 // Convert Sink name to port pointer
560 sp<PolicyAudioPort> sink = ctx->findPortByTagName(sinkAttr);
561 if (sink == NULL) {
562 ALOGE("%s: no sink found with name=%s", __func__, sinkAttr.c_str());
563 return Status::fromStatusT(BAD_VALUE);
564 }
565 route->setSink(sink);
566
567 std::string sourcesAttr = getXmlAttribute(cur, Attributes::sources);
568 if (sourcesAttr.empty()) {
569 ALOGE("%s: No %s found", __func__, Attributes::sources);
570 return Status::fromStatusT(BAD_VALUE);
571 }
572 // Tokenize and Convert Sources name to port pointer
573 PolicyAudioPortVector sources;
574 std::unique_ptr<char[]> sourcesLiteral{strndup(
575 sourcesAttr.c_str(), strlen(sourcesAttr.c_str()))};
576 char *devTag = strtok(sourcesLiteral.get(), ",");
577 while (devTag != NULL) {
578 if (strlen(devTag) != 0) {
579 sp<PolicyAudioPort> source = ctx->findPortByTagName(devTag);
580 if (source == NULL) {
581 ALOGE("%s: no source found with name=%s", __func__, devTag);
582 return Status::fromStatusT(BAD_VALUE);
583 }
584 sources.add(source);
585 }
586 devTag = strtok(NULL, ",");
587 }
588
589 sink->addRoute(route);
590 for (size_t i = 0; i < sources.size(); i++) {
591 sp<PolicyAudioPort> source = sources.itemAt(i);
592 source->addRoute(route);
593 }
594 route->setSources(sources);
595 return route;
596 }
597
deserialize(const xmlNode * cur,PtrSerializingCtx ctx)598 Return<ModuleTraits::Element> ModuleTraits::deserialize(const xmlNode *cur, PtrSerializingCtx ctx)
599 {
600 std::string name = getXmlAttribute(cur, Attributes::name);
601 if (name.empty()) {
602 ALOGE("%s: No %s found", __func__, Attributes::name);
603 return Status::fromStatusT(BAD_VALUE);
604 }
605 uint32_t versionMajor = 0, versionMinor = 0;
606 std::string versionLiteral = getXmlAttribute(cur, Attributes::version);
607 if (!versionLiteral.empty()) {
608 sscanf(versionLiteral.c_str(), "%u.%u", &versionMajor, &versionMinor);
609 ALOGV("%s: mHalVersion = major %u minor %u", __func__,
610 versionMajor, versionMajor);
611 }
612
613 ALOGV("%s: %s %s=%s", __func__, tag, Attributes::name, name.c_str());
614
615 Element module = new HwModule(name.c_str(), versionMajor, versionMinor);
616
617 // Deserialize childrens: Audio Mix Port, Audio Device Ports (Source/Sink), Audio Routes
618 MixPortTraits::Collection mixPorts;
619 status_t status = deserializeCollection<MixPortTraits>(cur, &mixPorts, NULL);
620 if (status != NO_ERROR) {
621 return Status::fromStatusT(status);
622 }
623 module->setProfiles(mixPorts);
624
625 DevicePortTraits::Collection devicePorts;
626 status = deserializeCollection<DevicePortTraits>(cur, &devicePorts, NULL);
627 if (status != NO_ERROR) {
628 return Status::fromStatusT(status);
629 }
630 module->setDeclaredDevices(devicePorts);
631
632 RouteTraits::Collection routes;
633 status = deserializeCollection<RouteTraits>(cur, &routes, module.get());
634 if (status != NO_ERROR) {
635 return Status::fromStatusT(status);
636 }
637 module->setRoutes(routes);
638
639 for (const xmlNode *children = cur->xmlChildrenNode; children != NULL;
640 children = children->next) {
641 if (!xmlStrcmp(children->name, reinterpret_cast<const xmlChar*>(childAttachedDevicesTag))) {
642 ALOGV("%s: %s %s found", __func__, tag, childAttachedDevicesTag);
643 for (const xmlNode *child = children->xmlChildrenNode; child != NULL;
644 child = child->next) {
645 if (!xmlStrcmp(child->name,
646 reinterpret_cast<const xmlChar*>(childAttachedDeviceTag))) {
647 auto attachedDevice = make_xmlUnique(xmlNodeListGetString(
648 child->doc, child->xmlChildrenNode, 1));
649 if (attachedDevice != nullptr) {
650 ALOGV("%s: %s %s=%s", __func__, tag, childAttachedDeviceTag,
651 reinterpret_cast<const char*>(attachedDevice.get()));
652 sp<DeviceDescriptor> device = module->getDeclaredDevices().
653 getDeviceFromTagName(std::string(reinterpret_cast<const char*>(
654 attachedDevice.get())));
655 ctx->addDevice(device);
656 }
657 }
658 }
659 }
660 if (!xmlStrcmp(children->name,
661 reinterpret_cast<const xmlChar*>(childDefaultOutputDeviceTag))) {
662 auto defaultOutputDevice = make_xmlUnique(xmlNodeListGetString(
663 children->doc, children->xmlChildrenNode, 1));
664 if (defaultOutputDevice != nullptr) {
665 ALOGV("%s: %s %s=%s", __func__, tag, childDefaultOutputDeviceTag,
666 reinterpret_cast<const char*>(defaultOutputDevice.get()));
667 sp<DeviceDescriptor> device = module->getDeclaredDevices().getDeviceFromTagName(
668 std::string(reinterpret_cast<const char*>(defaultOutputDevice.get())));
669 if (device != 0 && ctx->getDefaultOutputDevice() == 0) {
670 ctx->setDefaultOutputDevice(device);
671 ALOGV("%s: default is %08x",
672 __func__, ctx->getDefaultOutputDevice()->type());
673 }
674 }
675 }
676 }
677 return module;
678 }
679
deserialize(const xmlNode * root,AudioPolicyConfig * config)680 status_t GlobalConfigTraits::deserialize(const xmlNode *root, AudioPolicyConfig *config)
681 {
682 for (const xmlNode *cur = root->xmlChildrenNode; cur != NULL; cur = cur->next) {
683 if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(tag))) {
684 std::string speakerDrcEnabled =
685 getXmlAttribute(cur, Attributes::speakerDrcEnabled);
686 bool isSpeakerDrcEnabled;
687 if (!speakerDrcEnabled.empty() &&
688 convertTo<std::string, bool>(speakerDrcEnabled, isSpeakerDrcEnabled)) {
689 config->setSpeakerDrcEnabled(isSpeakerDrcEnabled);
690 }
691 std::string engineLibrarySuffix = getXmlAttribute(cur, Attributes::engineLibrarySuffix);
692 if (!engineLibrarySuffix.empty()) {
693 config->setEngineLibraryNameSuffix(engineLibrarySuffix);
694 }
695 return NO_ERROR;
696 }
697 }
698 return NO_ERROR;
699 }
700
deserialize(const xmlNode * root,AudioPolicyConfig * config)701 status_t SurroundSoundTraits::deserialize(const xmlNode *root, AudioPolicyConfig *config)
702 {
703 config->setDefaultSurroundFormats();
704
705 for (const xmlNode *cur = root->xmlChildrenNode; cur != NULL; cur = cur->next) {
706 if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(tag))) {
707 AudioPolicyConfig::SurroundFormats formats;
708 status_t status = deserializeCollection<SurroundSoundFormatTraits>(
709 cur, &formats, nullptr);
710 if (status == NO_ERROR) {
711 config->setSurroundFormats(formats);
712 }
713 return NO_ERROR;
714 }
715 }
716 return NO_ERROR;
717 }
718
deserialize(const xmlNode * cur,PtrSerializingCtx)719 Return<SurroundSoundFormatTraits::Element> SurroundSoundFormatTraits::deserialize(
720 const xmlNode *cur, PtrSerializingCtx /*serializingContext*/)
721 {
722 std::string formatLiteral = getXmlAttribute(cur, Attributes::name);
723 if (formatLiteral.empty()) {
724 ALOGE("%s: No %s found for a surround format", __func__, Attributes::name);
725 return Status::fromStatusT(BAD_VALUE);
726 }
727 audio_format_t format = formatFromString(formatLiteral);
728 if (format == AUDIO_FORMAT_DEFAULT) {
729 ALOGE("%s: Unrecognized format %s", __func__, formatLiteral.c_str());
730 return Status::fromStatusT(BAD_VALUE);
731 }
732 Element pair = std::make_pair(format, Collection::mapped_type{});
733
734 std::string subformatsLiteral = getXmlAttribute(cur, Attributes::subformats);
735 if (subformatsLiteral.empty()) return pair;
736 FormatVector subformats = formatsFromString(subformatsLiteral, " ");
737 for (const auto& subformat : subformats) {
738 auto result = pair.second.insert(subformat);
739 if (!result.second) {
740 ALOGE("%s: could not add subformat %x to collection", __func__, subformat);
741 return Status::fromStatusT(BAD_VALUE);
742 }
743 }
744 return pair;
745 }
746
deserialize(const char * configFile,AudioPolicyConfig * config)747 status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig *config)
748 {
749 auto doc = make_xmlUnique(xmlParseFile(configFile));
750 if (doc == nullptr) {
751 ALOGE("%s: Could not parse %s document.", __func__, configFile);
752 return BAD_VALUE;
753 }
754 xmlNodePtr root = xmlDocGetRootElement(doc.get());
755 if (root == NULL) {
756 ALOGE("%s: Could not parse %s document: empty.", __func__, configFile);
757 return BAD_VALUE;
758 }
759 if (xmlXIncludeProcess(doc.get()) < 0) {
760 ALOGE("%s: libxml failed to resolve XIncludes on %s document.", __func__, configFile);
761 }
762
763 if (xmlStrcmp(root->name, reinterpret_cast<const xmlChar*>(rootName))) {
764 ALOGE("%s: No %s root element found in xml data %s.", __func__, rootName,
765 reinterpret_cast<const char*>(root->name));
766 return BAD_VALUE;
767 }
768
769 std::string version = getXmlAttribute(root, versionAttribute);
770 if (version.empty()) {
771 ALOGE("%s: No version found in root node %s", __func__, rootName);
772 return BAD_VALUE;
773 }
774 if (version != mVersion) {
775 ALOGE("%s: Version does not match; expect %s got %s", __func__, mVersion.c_str(),
776 version.c_str());
777 return BAD_VALUE;
778 }
779 // Lets deserialize children
780 // Modules
781 ModuleTraits::Collection modules;
782 status_t status = deserializeCollection<ModuleTraits>(root, &modules, config);
783 if (status != NO_ERROR) {
784 return status;
785 }
786 config->setHwModules(modules);
787
788 // Global Configuration
789 GlobalConfigTraits::deserialize(root, config);
790
791 // Surround configuration
792 SurroundSoundTraits::deserialize(root, config);
793
794 return android::OK;
795 }
796
797 } // namespace
798
deserializeAudioPolicyFile(const char * fileName,AudioPolicyConfig * config)799 status_t deserializeAudioPolicyFile(const char *fileName, AudioPolicyConfig *config)
800 {
801 PolicySerializer serializer;
802 return serializer.deserialize(fileName, config);
803 }
804
805 } // namespace android
806