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