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 };
203
204 static status_t deserialize(const xmlNode *root, AudioPolicyConfig *config);
205 };
206
207 struct SurroundSoundTraits
208 {
209 static constexpr const char *tag = "surroundSound";
210
211 static status_t deserialize(const xmlNode *root, AudioPolicyConfig *config);
212 // Children: SurroundSoundFormatTraits
213 };
214
215 struct SurroundSoundFormatTraits : public StdCollectionTraits<AudioPolicyConfig::SurroundFormats>
216 {
217 static constexpr const char *tag = "format";
218 static constexpr const char *collectionTag = "formats";
219
220 struct Attributes
221 {
222 static constexpr const char *name = "name";
223 static constexpr const char *subformats = "subformats";
224 };
225
226 static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext);
227 };
228
229 class PolicySerializer
230 {
231 public:
PolicySerializer()232 PolicySerializer() : mVersion{std::to_string(gMajor) + "." + std::to_string(gMinor)}
233 {
234 ALOGV("%s: Version=%s Root=%s", __func__, mVersion.c_str(), rootName);
235 }
236 status_t deserialize(const char *configFile, AudioPolicyConfig *config);
237
238 private:
239 static constexpr const char *rootName = "audioPolicyConfiguration";
240 static constexpr const char *versionAttribute = "version";
241 static constexpr uint32_t gMajor = 1; /**< the major number of the policy xml format version. */
242 static constexpr uint32_t gMinor = 0; /**< the minor number of the policy xml format version. */
243
244 typedef AudioPolicyConfig Element;
245
246 const std::string mVersion;
247
248 // Children: ModulesTraits, VolumeTraits, SurroundSoundTraits (optional)
249 };
250
251 template <class T>
252 constexpr void (*xmlDeleter)(T* t);
253 template <>
254 constexpr auto xmlDeleter<xmlDoc> = xmlFreeDoc;
255 // http://b/111067277 - Add back constexpr when we switch to C++17.
256 template <>
__anonaf21c8190202(xmlChar *s) 257 auto xmlDeleter<xmlChar> = [](xmlChar *s) { xmlFree(s); };
258
259 /** @return a unique_ptr with the correct deleter for the libxml2 object. */
260 template <class T>
make_xmlUnique(T * t)261 constexpr auto make_xmlUnique(T *t) {
262 // Wrap deleter in lambda to enable empty base optimization
263 auto deleter = [](T *t) { xmlDeleter<T>(t); };
264 return std::unique_ptr<T, decltype(deleter)>{t, deleter};
265 }
266
getXmlAttribute(const xmlNode * cur,const char * attribute)267 std::string getXmlAttribute(const xmlNode *cur, const char *attribute)
268 {
269 auto xmlValue = make_xmlUnique(xmlGetProp(cur, reinterpret_cast<const xmlChar*>(attribute)));
270 if (xmlValue == nullptr) {
271 return "";
272 }
273 std::string value(reinterpret_cast<const char*>(xmlValue.get()));
274 return value;
275 }
276
277 template <class Trait>
getReference(const xmlNode * cur,const std::string & refName)278 const xmlNode* getReference(const xmlNode *cur, const std::string &refName)
279 {
280 for (; cur != NULL; cur = cur->next) {
281 if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::collectionTag))) {
282 for (const xmlNode *child = cur->children; child != NULL; child = child->next) {
283 if ((!xmlStrcmp(child->name,
284 reinterpret_cast<const xmlChar*>(Trait::referenceTag)))) {
285 std::string name = getXmlAttribute(child, Trait::Attributes::referenceName);
286 if (refName == name) {
287 return child;
288 }
289 }
290 }
291 }
292 }
293 return NULL;
294 }
295
296 template <class Trait>
deserializeCollection(const xmlNode * cur,typename Trait::Collection * collection,typename Trait::PtrSerializingCtx serializingContext)297 status_t deserializeCollection(const xmlNode *cur,
298 typename Trait::Collection *collection,
299 typename Trait::PtrSerializingCtx serializingContext)
300 {
301 for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
302 const xmlNode *child = NULL;
303 if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::collectionTag))) {
304 child = cur->xmlChildrenNode;
305 } else if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::tag))) {
306 child = cur;
307 }
308 for (; child != NULL; child = child->next) {
309 if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>(Trait::tag))) {
310 auto element = Trait::deserialize(child, serializingContext);
311 if (element.isOk()) {
312 status_t status = Trait::addElementToCollection(element, collection);
313 if (status != NO_ERROR) {
314 ALOGE("%s: could not add element to %s collection", __func__,
315 Trait::collectionTag);
316 return status;
317 }
318 } else {
319 return BAD_VALUE;
320 }
321 }
322 }
323 if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::tag))) {
324 return NO_ERROR;
325 }
326 }
327 return NO_ERROR;
328 }
329
deserialize(const xmlNode * cur,PtrSerializingCtx)330 Return<AudioGainTraits::Element> AudioGainTraits::deserialize(const xmlNode *cur,
331 PtrSerializingCtx /*serializingContext*/)
332 {
333 static uint32_t index = 0;
334 Element gain = new AudioGain(index++, true);
335
336 std::string mode = getXmlAttribute(cur, Attributes::mode);
337 if (!mode.empty()) {
338 gain->setMode(GainModeConverter::maskFromString(mode));
339 }
340
341 std::string channelsLiteral = getXmlAttribute(cur, Attributes::channelMask);
342 if (!channelsLiteral.empty()) {
343 gain->setChannelMask(channelMaskFromString(channelsLiteral));
344 }
345
346 std::string minValueMBLiteral = getXmlAttribute(cur, Attributes::minValueMB);
347 int32_t minValueMB;
348 if (!minValueMBLiteral.empty() && convertTo(minValueMBLiteral, minValueMB)) {
349 gain->setMinValueInMb(minValueMB);
350 }
351
352 std::string maxValueMBLiteral = getXmlAttribute(cur, Attributes::maxValueMB);
353 int32_t maxValueMB;
354 if (!maxValueMBLiteral.empty() && convertTo(maxValueMBLiteral, maxValueMB)) {
355 gain->setMaxValueInMb(maxValueMB);
356 }
357
358 std::string defaultValueMBLiteral = getXmlAttribute(cur, Attributes::defaultValueMB);
359 int32_t defaultValueMB;
360 if (!defaultValueMBLiteral.empty() && convertTo(defaultValueMBLiteral, defaultValueMB)) {
361 gain->setDefaultValueInMb(defaultValueMB);
362 }
363
364 std::string stepValueMBLiteral = getXmlAttribute(cur, Attributes::stepValueMB);
365 uint32_t stepValueMB;
366 if (!stepValueMBLiteral.empty() && convertTo(stepValueMBLiteral, stepValueMB)) {
367 gain->setStepValueInMb(stepValueMB);
368 }
369
370 std::string minRampMsLiteral = getXmlAttribute(cur, Attributes::minRampMs);
371 uint32_t minRampMs;
372 if (!minRampMsLiteral.empty() && convertTo(minRampMsLiteral, minRampMs)) {
373 gain->setMinRampInMs(minRampMs);
374 }
375
376 std::string maxRampMsLiteral = getXmlAttribute(cur, Attributes::maxRampMs);
377 uint32_t maxRampMs;
378 if (!maxRampMsLiteral.empty() && convertTo(maxRampMsLiteral, maxRampMs)) {
379 gain->setMaxRampInMs(maxRampMs);
380 }
381 std::string useForVolumeLiteral = getXmlAttribute(cur, Attributes::useForVolume);
382 bool useForVolume = false;
383 if (!useForVolumeLiteral.empty() && convertTo(useForVolumeLiteral, useForVolume)) {
384 gain->setUseForVolume(useForVolume);
385 }
386 ALOGV("%s: adding new gain mode %08x channel mask %08x min mB %d max mB %d UseForVolume: %d",
387 __func__, gain->getMode(), gain->getChannelMask(), gain->getMinValueInMb(),
388 gain->getMaxValueInMb(), useForVolume);
389
390 if (gain->getMode() != 0) {
391 return gain;
392 } else {
393 return Status::fromStatusT(BAD_VALUE);
394 }
395 }
396
deserialize(const xmlNode * cur,PtrSerializingCtx)397 Return<AudioProfileTraits::Element> AudioProfileTraits::deserialize(const xmlNode *cur,
398 PtrSerializingCtx /*serializingContext*/)
399 {
400 std::string samplingRates = getXmlAttribute(cur, Attributes::samplingRates);
401 std::string format = getXmlAttribute(cur, Attributes::format);
402 std::string channels = getXmlAttribute(cur, Attributes::channelMasks);
403
404 Element profile = new AudioProfile(formatFromString(format, gDynamicFormat),
405 channelMasksFromString(channels, ","),
406 samplingRatesFromString(samplingRates, ","));
407
408 profile->setDynamicFormat(profile->getFormat() == gDynamicFormat);
409 profile->setDynamicChannels(profile->getChannels().isEmpty());
410 profile->setDynamicRate(profile->getSampleRates().isEmpty());
411
412 return profile;
413 }
414
deserialize(const xmlNode * child,PtrSerializingCtx)415 Return<MixPortTraits::Element> MixPortTraits::deserialize(const xmlNode *child,
416 PtrSerializingCtx /*serializingContext*/)
417 {
418 std::string name = getXmlAttribute(child, Attributes::name);
419 if (name.empty()) {
420 ALOGE("%s: No %s found", __func__, Attributes::name);
421 return Status::fromStatusT(BAD_VALUE);
422 }
423 ALOGV("%s: %s %s=%s", __func__, tag, Attributes::name, name.c_str());
424 std::string role = getXmlAttribute(child, Attributes::role);
425 if (role.empty()) {
426 ALOGE("%s: No %s found", __func__, Attributes::role);
427 return Status::fromStatusT(BAD_VALUE);
428 }
429 ALOGV("%s: Role=%s", __func__, role.c_str());
430 audio_port_role_t portRole = (role == Attributes::roleSource) ?
431 AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
432
433 Element mixPort = new IOProfile(String8(name.c_str()), portRole);
434
435 AudioProfileTraits::Collection profiles;
436 status_t status = deserializeCollection<AudioProfileTraits>(child, &profiles, NULL);
437 if (status != NO_ERROR) {
438 return Status::fromStatusT(status);
439 }
440 if (profiles.isEmpty()) {
441 profiles.add(AudioProfile::createFullDynamic());
442 }
443 mixPort->setAudioProfiles(profiles);
444
445 std::string flags = getXmlAttribute(child, Attributes::flags);
446 if (!flags.empty()) {
447 // Source role
448 if (portRole == AUDIO_PORT_ROLE_SOURCE) {
449 mixPort->setFlags(OutputFlagConverter::maskFromString(flags));
450 } else {
451 // Sink role
452 mixPort->setFlags(InputFlagConverter::maskFromString(flags));
453 }
454 }
455 std::string maxOpenCount = getXmlAttribute(child, Attributes::maxOpenCount);
456 if (!maxOpenCount.empty()) {
457 convertTo(maxOpenCount, mixPort->maxOpenCount);
458 }
459 std::string maxActiveCount = getXmlAttribute(child, Attributes::maxActiveCount);
460 if (!maxActiveCount.empty()) {
461 convertTo(maxActiveCount, mixPort->maxActiveCount);
462 }
463 // Deserialize children
464 AudioGainTraits::Collection gains;
465 status = deserializeCollection<AudioGainTraits>(child, &gains, NULL);
466 if (status != NO_ERROR) {
467 return Status::fromStatusT(status);
468 }
469 mixPort->setGains(gains);
470
471 return mixPort;
472 }
473
deserialize(const xmlNode * cur,PtrSerializingCtx)474 Return<DevicePortTraits::Element> DevicePortTraits::deserialize(const xmlNode *cur,
475 PtrSerializingCtx /*serializingContext*/)
476 {
477 std::string name = getXmlAttribute(cur, Attributes::tagName);
478 if (name.empty()) {
479 ALOGE("%s: No %s found", __func__, Attributes::tagName);
480 return Status::fromStatusT(BAD_VALUE);
481 }
482 ALOGV("%s: %s %s=%s", __func__, tag, Attributes::tagName, name.c_str());
483 std::string typeName = getXmlAttribute(cur, Attributes::type);
484 if (typeName.empty()) {
485 ALOGE("%s: no type for %s", __func__, name.c_str());
486 return Status::fromStatusT(BAD_VALUE);
487 }
488 ALOGV("%s: %s %s=%s", __func__, tag, Attributes::type, typeName.c_str());
489 std::string role = getXmlAttribute(cur, Attributes::role);
490 if (role.empty()) {
491 ALOGE("%s: No %s found", __func__, Attributes::role);
492 return Status::fromStatusT(BAD_VALUE);
493 }
494 ALOGV("%s: %s %s=%s", __func__, tag, Attributes::role, role.c_str());
495 audio_port_role_t portRole = (role == Attributes::roleSource) ?
496 AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
497
498 audio_devices_t type = AUDIO_DEVICE_NONE;
499 if (!deviceFromString(typeName, type) ||
500 (!audio_is_input_device(type) && portRole == AUDIO_PORT_ROLE_SOURCE) ||
501 (!audio_is_output_devices(type) && portRole == AUDIO_PORT_ROLE_SINK)) {
502 ALOGW("%s: bad type %08x", __func__, type);
503 return Status::fromStatusT(BAD_VALUE);
504 }
505 std::string encodedFormatsLiteral = getXmlAttribute(cur, Attributes::encodedFormats);
506 ALOGV("%s: %s %s=%s", __func__, tag, Attributes::encodedFormats, encodedFormatsLiteral.c_str());
507 FormatVector encodedFormats;
508 if (!encodedFormatsLiteral.empty()) {
509 encodedFormats = formatsFromString(encodedFormatsLiteral, " ");
510 }
511 Element deviceDesc = new DeviceDescriptor(type, encodedFormats, String8(name.c_str()));
512
513 std::string address = getXmlAttribute(cur, Attributes::address);
514 if (!address.empty()) {
515 ALOGV("%s: address=%s for %s", __func__, address.c_str(), name.c_str());
516 deviceDesc->setAddress(String8(address.c_str()));
517 }
518
519 AudioProfileTraits::Collection profiles;
520 status_t status = deserializeCollection<AudioProfileTraits>(cur, &profiles, NULL);
521 if (status != NO_ERROR) {
522 return Status::fromStatusT(status);
523 }
524 if (profiles.isEmpty()) {
525 profiles.add(AudioProfile::createFullDynamic());
526 }
527 deviceDesc->setAudioProfiles(profiles);
528
529 // Deserialize AudioGain children
530 status = deserializeCollection<AudioGainTraits>(cur, &deviceDesc->mGains, NULL);
531 if (status != NO_ERROR) {
532 return Status::fromStatusT(status);
533 }
534 ALOGV("%s: adding device tag %s type %08x address %s", __func__,
535 deviceDesc->getName().string(), type, deviceDesc->address().string());
536 return deviceDesc;
537 }
538
deserialize(const xmlNode * cur,PtrSerializingCtx ctx)539 Return<RouteTraits::Element> RouteTraits::deserialize(const xmlNode *cur, PtrSerializingCtx ctx)
540 {
541 std::string type = getXmlAttribute(cur, Attributes::type);
542 if (type.empty()) {
543 ALOGE("%s: No %s found", __func__, Attributes::type);
544 return Status::fromStatusT(BAD_VALUE);
545 }
546 audio_route_type_t routeType = (type == Attributes::typeMix) ?
547 AUDIO_ROUTE_MIX : AUDIO_ROUTE_MUX;
548
549 ALOGV("%s: %s %s=%s", __func__, tag, Attributes::type, type.c_str());
550 Element route = new AudioRoute(routeType);
551
552 std::string sinkAttr = getXmlAttribute(cur, Attributes::sink);
553 if (sinkAttr.empty()) {
554 ALOGE("%s: No %s found", __func__, Attributes::sink);
555 return Status::fromStatusT(BAD_VALUE);
556 }
557 // Convert Sink name to port pointer
558 sp<AudioPort> sink = ctx->findPortByTagName(String8(sinkAttr.c_str()));
559 if (sink == NULL) {
560 ALOGE("%s: no sink found with name=%s", __func__, sinkAttr.c_str());
561 return Status::fromStatusT(BAD_VALUE);
562 }
563 route->setSink(sink);
564
565 std::string sourcesAttr = getXmlAttribute(cur, Attributes::sources);
566 if (sourcesAttr.empty()) {
567 ALOGE("%s: No %s found", __func__, Attributes::sources);
568 return Status::fromStatusT(BAD_VALUE);
569 }
570 // Tokenize and Convert Sources name to port pointer
571 AudioPortVector sources;
572 std::unique_ptr<char[]> sourcesLiteral{strndup(
573 sourcesAttr.c_str(), strlen(sourcesAttr.c_str()))};
574 char *devTag = strtok(sourcesLiteral.get(), ",");
575 while (devTag != NULL) {
576 if (strlen(devTag) != 0) {
577 sp<AudioPort> source = ctx->findPortByTagName(String8(devTag));
578 if (source == NULL) {
579 ALOGE("%s: no source found with name=%s", __func__, devTag);
580 return Status::fromStatusT(BAD_VALUE);
581 }
582 sources.add(source);
583 }
584 devTag = strtok(NULL, ",");
585 }
586
587 sink->addRoute(route);
588 for (size_t i = 0; i < sources.size(); i++) {
589 sp<AudioPort> source = sources.itemAt(i);
590 source->addRoute(route);
591 }
592 route->setSources(sources);
593 return route;
594 }
595
deserialize(const xmlNode * cur,PtrSerializingCtx ctx)596 Return<ModuleTraits::Element> ModuleTraits::deserialize(const xmlNode *cur, PtrSerializingCtx ctx)
597 {
598 std::string name = getXmlAttribute(cur, Attributes::name);
599 if (name.empty()) {
600 ALOGE("%s: No %s found", __func__, Attributes::name);
601 return Status::fromStatusT(BAD_VALUE);
602 }
603 uint32_t versionMajor = 0, versionMinor = 0;
604 std::string versionLiteral = getXmlAttribute(cur, Attributes::version);
605 if (!versionLiteral.empty()) {
606 sscanf(versionLiteral.c_str(), "%u.%u", &versionMajor, &versionMinor);
607 ALOGV("%s: mHalVersion = major %u minor %u", __func__,
608 versionMajor, versionMajor);
609 }
610
611 ALOGV("%s: %s %s=%s", __func__, tag, Attributes::name, name.c_str());
612
613 Element module = new HwModule(name.c_str(), versionMajor, versionMinor);
614
615 // Deserialize childrens: Audio Mix Port, Audio Device Ports (Source/Sink), Audio Routes
616 MixPortTraits::Collection mixPorts;
617 status_t status = deserializeCollection<MixPortTraits>(cur, &mixPorts, NULL);
618 if (status != NO_ERROR) {
619 return Status::fromStatusT(status);
620 }
621 module->setProfiles(mixPorts);
622
623 DevicePortTraits::Collection devicePorts;
624 status = deserializeCollection<DevicePortTraits>(cur, &devicePorts, NULL);
625 if (status != NO_ERROR) {
626 return Status::fromStatusT(status);
627 }
628 module->setDeclaredDevices(devicePorts);
629
630 RouteTraits::Collection routes;
631 status = deserializeCollection<RouteTraits>(cur, &routes, module.get());
632 if (status != NO_ERROR) {
633 return Status::fromStatusT(status);
634 }
635 module->setRoutes(routes);
636
637 for (const xmlNode *children = cur->xmlChildrenNode; children != NULL;
638 children = children->next) {
639 if (!xmlStrcmp(children->name, reinterpret_cast<const xmlChar*>(childAttachedDevicesTag))) {
640 ALOGV("%s: %s %s found", __func__, tag, childAttachedDevicesTag);
641 for (const xmlNode *child = children->xmlChildrenNode; child != NULL;
642 child = child->next) {
643 if (!xmlStrcmp(child->name,
644 reinterpret_cast<const xmlChar*>(childAttachedDeviceTag))) {
645 auto attachedDevice = make_xmlUnique(xmlNodeListGetString(
646 child->doc, child->xmlChildrenNode, 1));
647 if (attachedDevice != nullptr) {
648 ALOGV("%s: %s %s=%s", __func__, tag, childAttachedDeviceTag,
649 reinterpret_cast<const char*>(attachedDevice.get()));
650 sp<DeviceDescriptor> device = module->getDeclaredDevices().
651 getDeviceFromTagName(String8(reinterpret_cast<const char*>(
652 attachedDevice.get())));
653 ctx->addAvailableDevice(device);
654 }
655 }
656 }
657 }
658 if (!xmlStrcmp(children->name,
659 reinterpret_cast<const xmlChar*>(childDefaultOutputDeviceTag))) {
660 auto defaultOutputDevice = make_xmlUnique(xmlNodeListGetString(
661 children->doc, children->xmlChildrenNode, 1));
662 if (defaultOutputDevice != nullptr) {
663 ALOGV("%s: %s %s=%s", __func__, tag, childDefaultOutputDeviceTag,
664 reinterpret_cast<const char*>(defaultOutputDevice.get()));
665 sp<DeviceDescriptor> device = module->getDeclaredDevices().getDeviceFromTagName(
666 String8(reinterpret_cast<const char*>(defaultOutputDevice.get())));
667 if (device != 0 && ctx->getDefaultOutputDevice() == 0) {
668 ctx->setDefaultOutputDevice(device);
669 ALOGV("%s: default is %08x",
670 __func__, ctx->getDefaultOutputDevice()->type());
671 }
672 }
673 }
674 }
675 return module;
676 }
677
deserialize(const xmlNode * root,AudioPolicyConfig * config)678 status_t GlobalConfigTraits::deserialize(const xmlNode *root, AudioPolicyConfig *config)
679 {
680 for (const xmlNode *cur = root->xmlChildrenNode; cur != NULL; cur = cur->next) {
681 if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(tag))) {
682 std::string speakerDrcEnabled =
683 getXmlAttribute(cur, Attributes::speakerDrcEnabled);
684 bool isSpeakerDrcEnabled;
685 if (!speakerDrcEnabled.empty() &&
686 convertTo<std::string, bool>(speakerDrcEnabled, isSpeakerDrcEnabled)) {
687 config->setSpeakerDrcEnabled(isSpeakerDrcEnabled);
688 }
689 return NO_ERROR;
690 }
691 }
692 return NO_ERROR;
693 }
694
deserialize(const xmlNode * root,AudioPolicyConfig * config)695 status_t SurroundSoundTraits::deserialize(const xmlNode *root, AudioPolicyConfig *config)
696 {
697 config->setDefaultSurroundFormats();
698
699 for (const xmlNode *cur = root->xmlChildrenNode; cur != NULL; cur = cur->next) {
700 if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(tag))) {
701 AudioPolicyConfig::SurroundFormats formats;
702 status_t status = deserializeCollection<SurroundSoundFormatTraits>(
703 cur, &formats, nullptr);
704 if (status == NO_ERROR) {
705 config->setSurroundFormats(formats);
706 }
707 return NO_ERROR;
708 }
709 }
710 return NO_ERROR;
711 }
712
deserialize(const xmlNode * cur,PtrSerializingCtx)713 Return<SurroundSoundFormatTraits::Element> SurroundSoundFormatTraits::deserialize(
714 const xmlNode *cur, PtrSerializingCtx /*serializingContext*/)
715 {
716 std::string formatLiteral = getXmlAttribute(cur, Attributes::name);
717 if (formatLiteral.empty()) {
718 ALOGE("%s: No %s found for a surround format", __func__, Attributes::name);
719 return Status::fromStatusT(BAD_VALUE);
720 }
721 audio_format_t format = formatFromString(formatLiteral);
722 if (format == AUDIO_FORMAT_DEFAULT) {
723 ALOGE("%s: Unrecognized format %s", __func__, formatLiteral.c_str());
724 return Status::fromStatusT(BAD_VALUE);
725 }
726 Element pair = std::make_pair(format, Collection::mapped_type{});
727
728 std::string subformatsLiteral = getXmlAttribute(cur, Attributes::subformats);
729 if (subformatsLiteral.empty()) return pair;
730 FormatVector subformats = formatsFromString(subformatsLiteral, " ");
731 for (const auto& subformat : subformats) {
732 auto result = pair.second.insert(subformat);
733 if (!result.second) {
734 ALOGE("%s: could not add subformat %x to collection", __func__, subformat);
735 return Status::fromStatusT(BAD_VALUE);
736 }
737 }
738 return pair;
739 }
740
deserialize(const char * configFile,AudioPolicyConfig * config)741 status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig *config)
742 {
743 auto doc = make_xmlUnique(xmlParseFile(configFile));
744 if (doc == nullptr) {
745 ALOGE("%s: Could not parse %s document.", __func__, configFile);
746 return BAD_VALUE;
747 }
748 xmlNodePtr root = xmlDocGetRootElement(doc.get());
749 if (root == NULL) {
750 ALOGE("%s: Could not parse %s document: empty.", __func__, configFile);
751 return BAD_VALUE;
752 }
753 if (xmlXIncludeProcess(doc.get()) < 0) {
754 ALOGE("%s: libxml failed to resolve XIncludes on %s document.", __func__, configFile);
755 }
756
757 if (xmlStrcmp(root->name, reinterpret_cast<const xmlChar*>(rootName))) {
758 ALOGE("%s: No %s root element found in xml data %s.", __func__, rootName,
759 reinterpret_cast<const char*>(root->name));
760 return BAD_VALUE;
761 }
762
763 std::string version = getXmlAttribute(root, versionAttribute);
764 if (version.empty()) {
765 ALOGE("%s: No version found in root node %s", __func__, rootName);
766 return BAD_VALUE;
767 }
768 if (version != mVersion) {
769 ALOGE("%s: Version does not match; expect %s got %s", __func__, mVersion.c_str(),
770 version.c_str());
771 return BAD_VALUE;
772 }
773 // Lets deserialize children
774 // Modules
775 ModuleTraits::Collection modules;
776 status_t status = deserializeCollection<ModuleTraits>(root, &modules, config);
777 if (status != NO_ERROR) {
778 return status;
779 }
780 config->setHwModules(modules);
781
782 // Global Configuration
783 GlobalConfigTraits::deserialize(root, config);
784
785 // Surround configuration
786 SurroundSoundTraits::deserialize(root, config);
787
788 return android::OK;
789 }
790
791 } // namespace
792
deserializeAudioPolicyFile(const char * fileName,AudioPolicyConfig * config)793 status_t deserializeAudioPolicyFile(const char *fileName, AudioPolicyConfig *config)
794 {
795 PolicySerializer serializer;
796 return serializer.deserialize(fileName, config);
797 }
798
799 } // namespace android
800