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