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 #include <variant>
24 
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 "IOProfile.h"
33 #include "Serializer.h"
34 #include "TypeConverter.h"
35 
36 namespace android {
37 
38 namespace {
39 
40 using utilities::convertTo;
41 
maybeVendorExtension(const std::string & s)42 static inline bool maybeVendorExtension(const std::string& s) {
43     // Only checks whether the string starts with the "vendor prefix".
44     static const std::string vendorPrefix = "VX_";
45     return s.size() > vendorPrefix.size() && s.substr(0, vendorPrefix.size()) == vendorPrefix;
46 }
47 
48 template<typename E, typename C>
49 struct AndroidCollectionTraits {
50     typedef sp<E> Element;
51     typedef C Collection;
52     typedef void* PtrSerializingCtx;
53 
addElementToCollectionandroid::__anonaf21c8190111::AndroidCollectionTraits54     static status_t addElementToCollection(const Element &element, Collection *collection) {
55         return collection->add(element) >= 0 ? NO_ERROR : BAD_VALUE;
56     }
57 };
58 
59 template<typename C>
60 struct StdCollectionTraits {
61     typedef C Collection;
62     typedef typename C::value_type Element;
63     typedef void* PtrSerializingCtx;
64 
addElementToCollectionandroid::__anonaf21c8190111::StdCollectionTraits65     static status_t addElementToCollection(const Element &element, Collection *collection) {
66         auto pair = collection->insert(element);
67         return pair.second ? NO_ERROR : BAD_VALUE;
68     }
69 };
70 
71 struct AudioGainTraits : public AndroidCollectionTraits<AudioGain, AudioGains>
72 {
73     static constexpr const char *tag = "gain";
74     static constexpr const char *collectionTag = "gains";
75 
76     struct Attributes
77     {
78         /** gain modes supported, e.g. AUDIO_GAIN_MODE_CHANNELS. */
79         static constexpr const char *mode = "mode";
80         /** controlled channels, needed if mode AUDIO_GAIN_MODE_CHANNELS. */
81         static constexpr const char *channelMask = "channel_mask";
82         static constexpr const char *minValueMB = "minValueMB"; /**< min value in millibel. */
83         static constexpr const char *maxValueMB = "maxValueMB"; /**< max value in millibel. */
84         /** default value in millibel. */
85         static constexpr const char *defaultValueMB = "defaultValueMB";
86         static constexpr const char *stepValueMB = "stepValueMB"; /**< step value in millibel. */
87         /** needed if mode AUDIO_GAIN_MODE_RAMP. */
88         static constexpr const char *minRampMs = "minRampMs";
89         /** needed if mode AUDIO_GAIN_MODE_RAMP. */
90         static constexpr const char *maxRampMs = "maxRampMs";
91         /** needed to allow use setPortGain instead of setStreamVolume. */
92         static constexpr const char *useForVolume = "useForVolume";
93 
94     };
95 
96     // No children
97 };
98 
99 // A profile section contains a name,  one audio format and the list of supported sampling rates
100 // and channel masks for this format
101 struct AudioProfileTraits : public AndroidCollectionTraits<AudioProfile, AudioProfileVector>
102 {
103     static constexpr const char *tag = "profile";
104     static constexpr const char *collectionTag = "profiles";
105 
106     struct Attributes
107     {
108         static constexpr const char *samplingRates = "samplingRates";
109         static constexpr const char *format = "format";
110         static constexpr const char *channelMasks = "channelMasks";
111     };
112 };
113 
114 struct MixPortTraits : public AndroidCollectionTraits<IOProfile, IOProfileCollection>
115 {
116     static constexpr const char *tag = "mixPort";
117     static constexpr const char *collectionTag = "mixPorts";
118 
119     struct Attributes
120     {
121         static constexpr const char *name = "name";
122         static constexpr const char *role = "role";
123         static constexpr const char *roleSource = "source"; /**< <attribute role source value>. */
124         static constexpr const char *flags = "flags";
125         static constexpr const char *maxOpenCount = "maxOpenCount";
126         static constexpr const char *maxActiveCount = "maxActiveCount";
127         static constexpr const char *recommendedMuteDurationMs = "recommendedMuteDurationMs";
128     };
129 
130     // Children: GainTraits
131 };
132 
133 struct DevicePortTraits : public AndroidCollectionTraits<DeviceDescriptor, DeviceVector>
134 {
135     static constexpr const char *tag = "devicePort";
136     static constexpr const char *collectionTag = "devicePorts";
137 
138     struct Attributes
139     {
140         /**  <device tag name>: any string without space. */
141         static constexpr const char *tagName = "tagName";
142         static constexpr const char *type = "type"; /**< <device type>. */
143         static constexpr const char *role = "role"; /**< <device role: sink or source>. */
144         static constexpr const char *roleSource = "source"; /**< <attribute role source value>. */
145         /** optional: device address, char string less than 64. */
146         static constexpr const char *address = "address";
147         /** optional: the list of encoded audio formats that are known to be supported. */
148         static constexpr const char *encodedFormats = "encodedFormats";
149     };
150 
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 
171 struct ModuleTraits : public AndroidCollectionTraits<HwModule, HwModuleCollection>
172 {
173     static constexpr const char *tag = "module";
174     static constexpr const char *collectionTag = "modules";
175 
176     static constexpr const char *childAttachedDevicesTag = "attachedDevices";
177     static constexpr const char *childAttachedDeviceTag = "item";
178     static constexpr const char *childDefaultOutputDeviceTag = "defaultOutputDevice";
179 
180     struct Attributes
181     {
182         static constexpr const char *name = "name";
183         static constexpr const char *version = "halVersion";
184     };
185 
186     typedef AudioPolicyConfig *PtrSerializingCtx;
187 
188     // Children: mixPortTraits, devicePortTraits, and routeTraits
189     // Need to call deserialize on each child
190 };
191 
192 struct GlobalConfigTraits
193 {
194     typedef std::monostate Element;
195 
196     static constexpr const char *tag = "globalConfiguration";
197 
198     struct Attributes
199     {
200         static constexpr const char *callScreenModeSupported= "call_screen_mode_supported";
201         static constexpr const char *engineLibrarySuffix = "engine_library";
202     };
203 
204     typedef AudioPolicyConfig *PtrSerializingCtx;
205 };
206 
207 struct SurroundSoundTraits
208 {
209     typedef std::monostate Element;
210 
211     static constexpr const char *tag = "surroundSound";
212 
213     typedef AudioPolicyConfig *PtrSerializingCtx;
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 
229 class PolicySerializer
230 {
231 public:
232     status_t deserialize(const char *configFile, AudioPolicyConfig *config,
233             bool ignoreVendorExtensions = false);
234 
235     template <class Trait>
236     status_t deserializeCollection(const xmlNode *cur,
237             typename Trait::Collection *collection,
238             typename Trait::PtrSerializingCtx serializingContext);
239     template <class Trait>
240     std::variant<status_t, typename Trait::Element> deserialize(const xmlNode *cur,
241             typename Trait::PtrSerializingCtx serializingContext);
242 
243 private:
244     static constexpr const char *rootName = "audioPolicyConfiguration";
245     static constexpr const char *versionAttribute = "version";
246 
247     typedef AudioPolicyConfig Element;
248 
249     bool mIgnoreVendorExtensions = false;
250     std::string mChannelMasksSeparator = ",";
251     std::string mSamplingRatesSeparator = ",";
252     std::string mFlagsSeparator = "|";
253 
254     // Children: ModulesTraits, VolumeTraits, SurroundSoundTraits (optional)
255 };
256 
257 // Deleter using free() for use with std::unique_ptr<>. See also UniqueCPtr<> below.
258 struct FreeDelete {
259     // NOTE: Deleting a const object is valid but free() takes a non-const pointer.
operator ()android::__anonaf21c8190111::FreeDelete260     void operator()(const void* ptr) const {
261         free(const_cast<void*>(ptr));
262     }
263 };
264 
265 // Alias for std::unique_ptr<> that uses the C function free() to delete objects.
266 template <typename T>
267 using UniqueCPtr = std::unique_ptr<T, FreeDelete>;
268 
269 template <class T>
270 constexpr void (*xmlDeleter)(T* t);
271 template <>
272 constexpr auto xmlDeleter<xmlDoc> = xmlFreeDoc;
273 template <>
__anonaf21c8190202(xmlChar *s) 274 constexpr auto xmlDeleter<xmlChar> = [](xmlChar *s) { xmlFree(s); };
275 
276 /** @return a unique_ptr with the correct deleter for the libxml2 object. */
277 template <class T>
make_xmlUnique(T * t)278 constexpr auto make_xmlUnique(T *t) {
279     // Wrap deleter in lambda to enable empty base optimization
280     auto deleter = [](T *t) { xmlDeleter<T>(t); };
281     return std::unique_ptr<T, decltype(deleter)>{t, deleter};
282 }
283 
getXmlAttribute(const xmlNode * cur,const char * attribute)284 std::string getXmlAttribute(const xmlNode *cur, const char *attribute)
285 {
286     auto xmlValue = make_xmlUnique(xmlGetProp(cur, reinterpret_cast<const xmlChar*>(attribute)));
287     if (xmlValue == nullptr) {
288         return "";
289     }
290     std::string value(reinterpret_cast<const char*>(xmlValue.get()));
291     return value;
292 }
293 
294 template <class Trait>
getReference(const xmlNode * cur,const std::string & refName)295 const xmlNode* getReference(const xmlNode *cur, const std::string &refName)
296 {
297     for (; cur != NULL; cur = cur->next) {
298         if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::collectionTag))) {
299             for (const xmlNode *child = cur->children; child != NULL; child = child->next) {
300                 if ((!xmlStrcmp(child->name,
301                                         reinterpret_cast<const xmlChar*>(Trait::referenceTag)))) {
302                     std::string name = getXmlAttribute(child, Trait::Attributes::referenceName);
303                     if (refName == name) {
304                         return child;
305                     }
306                 }
307             }
308         }
309     }
310     return NULL;
311 }
312 
313 template <class Trait>
deserializeCollection(const xmlNode * cur,typename Trait::Collection * collection,typename Trait::PtrSerializingCtx serializingContext)314 status_t PolicySerializer::deserializeCollection(const xmlNode *cur,
315         typename Trait::Collection *collection,
316         typename Trait::PtrSerializingCtx serializingContext)
317 {
318     for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
319         const xmlNode *child = NULL;
320         if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::collectionTag))) {
321             child = cur->xmlChildrenNode;
322         } else if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::tag))) {
323             child = cur;
324         }
325         for (; child != NULL; child = child->next) {
326             if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>(Trait::tag))) {
327                 auto maybeElement = deserialize<Trait>(child, serializingContext);
328                 if (maybeElement.index() == 1) {
329                     status_t status = Trait::addElementToCollection(
330                             std::get<1>(maybeElement), collection);
331                     if (status != NO_ERROR) {
332                         ALOGE("%s: could not add element to %s collection", __func__,
333                             Trait::collectionTag);
334                         return status;
335                     }
336                 } else if (mIgnoreVendorExtensions && std::get<status_t>(maybeElement) == NO_INIT) {
337                     // Skip a vendor extension element.
338                 } else {
339                     return BAD_VALUE;
340                 }
341             }
342         }
343         if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::tag))) {
344             return NO_ERROR;
345         }
346     }
347     return NO_ERROR;
348 }
349 
350 template<>
deserialize(const xmlNode * cur,AudioGainTraits::PtrSerializingCtx)351 std::variant<status_t, AudioGainTraits::Element> PolicySerializer::deserialize<AudioGainTraits>(
352         const xmlNode *cur, AudioGainTraits::PtrSerializingCtx /*serializingContext*/)
353 {
354     using Attributes = AudioGainTraits::Attributes;
355 
356     static uint32_t index = 0;
357     AudioGainTraits::Element gain = new AudioGain(index++, true);
358 
359     std::string mode = getXmlAttribute(cur, Attributes::mode);
360     if (!mode.empty()) {
361         gain->setMode(GainModeConverter::maskFromString(mode, " "));
362     }
363 
364     std::string channelsLiteral = getXmlAttribute(cur, Attributes::channelMask);
365     if (!channelsLiteral.empty()) {
366         gain->setChannelMask(channelMaskFromString(channelsLiteral));
367     }
368 
369     std::string minValueMBLiteral = getXmlAttribute(cur, Attributes::minValueMB);
370     int32_t minValueMB;
371     if (!minValueMBLiteral.empty() && convertTo(minValueMBLiteral, minValueMB)) {
372         gain->setMinValueInMb(minValueMB);
373     }
374 
375     std::string maxValueMBLiteral = getXmlAttribute(cur, Attributes::maxValueMB);
376     int32_t maxValueMB;
377     if (!maxValueMBLiteral.empty() && convertTo(maxValueMBLiteral, maxValueMB)) {
378         gain->setMaxValueInMb(maxValueMB);
379     }
380 
381     std::string defaultValueMBLiteral = getXmlAttribute(cur, Attributes::defaultValueMB);
382     int32_t defaultValueMB;
383     if (!defaultValueMBLiteral.empty() && convertTo(defaultValueMBLiteral, defaultValueMB)) {
384         gain->setDefaultValueInMb(defaultValueMB);
385     }
386 
387     std::string stepValueMBLiteral = getXmlAttribute(cur, Attributes::stepValueMB);
388     uint32_t stepValueMB;
389     if (!stepValueMBLiteral.empty() && convertTo(stepValueMBLiteral, stepValueMB)) {
390         gain->setStepValueInMb(stepValueMB);
391     }
392 
393     std::string minRampMsLiteral = getXmlAttribute(cur, Attributes::minRampMs);
394     uint32_t minRampMs;
395     if (!minRampMsLiteral.empty() && convertTo(minRampMsLiteral, minRampMs)) {
396         gain->setMinRampInMs(minRampMs);
397     }
398 
399     std::string maxRampMsLiteral = getXmlAttribute(cur, Attributes::maxRampMs);
400     uint32_t maxRampMs;
401     if (!maxRampMsLiteral.empty() && convertTo(maxRampMsLiteral, maxRampMs)) {
402         gain->setMaxRampInMs(maxRampMs);
403     }
404     std::string useForVolumeLiteral = getXmlAttribute(cur, Attributes::useForVolume);
405     bool useForVolume = false;
406     if (!useForVolumeLiteral.empty() && convertTo(useForVolumeLiteral, useForVolume)) {
407         gain->setUseForVolume(useForVolume);
408     }
409     ALOGV("%s: adding new gain mode %08x channel mask %08x min mB %d max mB %d UseForVolume: %d",
410           __func__, gain->getMode(), gain->getChannelMask(), gain->getMinValueInMb(),
411           gain->getMaxValueInMb(), useForVolume);
412 
413     if (gain->getMode() != 0) {
414         return gain;
415     } else {
416         return BAD_VALUE;
417     }
418 }
419 
420 template<>
421 std::variant<status_t, AudioProfileTraits::Element>
deserialize(const xmlNode * cur,AudioProfileTraits::PtrSerializingCtx)422 PolicySerializer::deserialize<AudioProfileTraits>(
423         const xmlNode *cur, AudioProfileTraits::PtrSerializingCtx /*serializingContext*/)
424 {
425     using Attributes = AudioProfileTraits::Attributes;
426 
427     std::string samplingRates = getXmlAttribute(cur, Attributes::samplingRates);
428     std::string format = getXmlAttribute(cur, Attributes::format);
429     std::string channels = getXmlAttribute(cur, Attributes::channelMasks);
430 
431     if (mIgnoreVendorExtensions && maybeVendorExtension(format)) {
432         ALOGI("%s: vendor extension format \"%s\" skipped", __func__, format.c_str());
433         return NO_INIT;
434     }
435     AudioProfileTraits::Element profile = new AudioProfile(formatFromString(format, gDynamicFormat),
436             channelMasksFromString(channels, mChannelMasksSeparator.c_str()),
437             samplingRatesFromString(samplingRates, mSamplingRatesSeparator.c_str()));
438 
439     profile->setDynamicFormat(profile->getFormat() == gDynamicFormat);
440     profile->setDynamicChannels(profile->getChannels().empty());
441     profile->setDynamicRate(profile->getSampleRates().empty());
442 
443     return profile;
444 }
445 
446 template<>
deserialize(const xmlNode * child,MixPortTraits::PtrSerializingCtx)447 std::variant<status_t, MixPortTraits::Element> PolicySerializer::deserialize<MixPortTraits>(
448         const xmlNode *child, MixPortTraits::PtrSerializingCtx /*serializingContext*/)
449 {
450     using Attributes = MixPortTraits::Attributes;
451 
452     std::string name = getXmlAttribute(child, Attributes::name);
453     if (name.empty()) {
454         ALOGE("%s: No %s found", __func__, Attributes::name);
455         return BAD_VALUE;
456     }
457     ALOGV("%s: %s %s=%s", __func__, MixPortTraits::tag, Attributes::name, name.c_str());
458     std::string role = getXmlAttribute(child, Attributes::role);
459     if (role.empty()) {
460         ALOGE("%s: No %s found", __func__, Attributes::role);
461         return BAD_VALUE;
462     }
463     ALOGV("%s: Role=%s", __func__, role.c_str());
464     audio_port_role_t portRole = (role == Attributes::roleSource) ?
465             AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
466 
467     MixPortTraits::Element mixPort = new IOProfile(name, portRole);
468 
469     AudioProfileTraits::Collection profiles;
470     status_t status = deserializeCollection<AudioProfileTraits>(child, &profiles, NULL);
471     if (status != NO_ERROR) {
472         return status;
473     }
474     if (profiles.empty()) {
475         profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
476     }
477     // The audio profiles are in order of listed in audio policy configuration file.
478     // Sort audio profiles accroding to the format.
479     sortAudioProfiles(profiles);
480     mixPort->setAudioProfiles(profiles);
481 
482     std::string flags = getXmlAttribute(child, Attributes::flags);
483     if (!flags.empty()) {
484         // Source role
485         if (portRole == AUDIO_PORT_ROLE_SOURCE) {
486             //TODO: b/193496180 use spatializer flag at audio HAL when available until then,
487             // use DEEP_BUFFER+FAST flag combo to indicate the spatializer output profile
488             uint32_t intFlags =
489                     OutputFlagConverter::maskFromString(flags, mFlagsSeparator.c_str());
490             if (intFlags == (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_DEEP_BUFFER)) {
491                 intFlags = AUDIO_OUTPUT_FLAG_SPATIALIZER;
492             }
493             mixPort->setFlags(intFlags);
494         } else {
495             // Sink role
496             mixPort->setFlags(InputFlagConverter::maskFromString(flags, mFlagsSeparator.c_str()));
497         }
498     }
499     std::string maxOpenCount = getXmlAttribute(child, Attributes::maxOpenCount);
500     if (!maxOpenCount.empty()) {
501         convertTo(maxOpenCount, mixPort->maxOpenCount);
502     }
503     std::string maxActiveCount = getXmlAttribute(child, Attributes::maxActiveCount);
504     if (!maxActiveCount.empty()) {
505         convertTo(maxActiveCount, mixPort->maxActiveCount);
506     }
507 
508     std::string recommendedmuteDurationMsLiteral =
509             getXmlAttribute(child, Attributes::recommendedMuteDurationMs);
510     if (!recommendedmuteDurationMsLiteral.empty()) {
511         convertTo(recommendedmuteDurationMsLiteral, mixPort->recommendedMuteDurationMs);
512     }
513 
514     // Deserialize children
515     AudioGainTraits::Collection gains;
516     status = deserializeCollection<AudioGainTraits>(child, &gains, NULL);
517     if (status != NO_ERROR) {
518         return status;
519     }
520     mixPort->setGains(gains);
521 
522     return mixPort;
523 }
524 
525 template<>
deserialize(const xmlNode * cur,DevicePortTraits::PtrSerializingCtx)526 std::variant<status_t, DevicePortTraits::Element> PolicySerializer::deserialize<DevicePortTraits>(
527         const xmlNode *cur, DevicePortTraits::PtrSerializingCtx /*serializingContext*/)
528 {
529     using Attributes = DevicePortTraits::Attributes;
530     auto& tag = DevicePortTraits::tag;
531 
532     std::string name = getXmlAttribute(cur, Attributes::tagName);
533     if (name.empty()) {
534         ALOGE("%s: No %s found", __func__, Attributes::tagName);
535         return BAD_VALUE;
536     }
537     ALOGV("%s: %s %s=%s", __func__, tag, Attributes::tagName, name.c_str());
538     std::string typeName = getXmlAttribute(cur, Attributes::type);
539     if (typeName.empty()) {
540         ALOGE("%s: no type for %s", __func__, name.c_str());
541         return BAD_VALUE;
542     }
543     ALOGV("%s: %s %s=%s", __func__, tag, Attributes::type, typeName.c_str());
544     std::string role = getXmlAttribute(cur, Attributes::role);
545     if (role.empty()) {
546         ALOGE("%s: No %s found", __func__, Attributes::role);
547         return BAD_VALUE;
548     }
549     ALOGV("%s: %s %s=%s", __func__, tag, Attributes::role, role.c_str());
550     audio_port_role_t portRole = (role == Attributes::roleSource) ?
551                 AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
552 
553     if (mIgnoreVendorExtensions && maybeVendorExtension(typeName)) {
554         ALOGI("%s: vendor extension device type \"%s\" skipped", __func__, typeName.c_str());
555         return NO_INIT;
556     }
557     audio_devices_t type = AUDIO_DEVICE_NONE;
558     if (!DeviceConverter::fromString(typeName, type) ||
559             (!audio_is_input_device(type) && portRole == AUDIO_PORT_ROLE_SOURCE) ||
560             (!audio_is_output_devices(type) && portRole == AUDIO_PORT_ROLE_SINK)) {
561         ALOGW("%s: bad type %08x", __func__, type);
562         return BAD_VALUE;
563     }
564     std::string encodedFormatsLiteral = getXmlAttribute(cur, Attributes::encodedFormats);
565     ALOGV("%s: %s %s=%s", __func__, tag, Attributes::encodedFormats, encodedFormatsLiteral.c_str());
566     FormatVector encodedFormats;
567     if (!encodedFormatsLiteral.empty()) {
568         encodedFormats = formatsFromString(encodedFormatsLiteral, " ");
569     }
570     std::string address = getXmlAttribute(cur, Attributes::address);
571     DevicePortTraits::Element deviceDesc =
572             new DeviceDescriptor(type, name, address, encodedFormats);
573 
574     AudioProfileTraits::Collection profiles;
575     status_t status = deserializeCollection<AudioProfileTraits>(cur, &profiles, NULL);
576     if (status != NO_ERROR) {
577         return status;
578     }
579     if (profiles.empty()) {
580         profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
581     }
582     // The audio profiles are in order of listed in audio policy configuration file.
583     // Sort audio profiles accroding to the format.
584     sortAudioProfiles(profiles);
585     deviceDesc->setAudioProfiles(profiles);
586 
587     // Deserialize AudioGain children
588     status = deserializeCollection<AudioGainTraits>(cur, &deviceDesc->mGains, NULL);
589     if (status != NO_ERROR) {
590         return status;
591     }
592     ALOGV("%s: adding device tag %s type %08x address %s", __func__,
593           deviceDesc->getName().c_str(), type, deviceDesc->address().c_str());
594     return deviceDesc;
595 }
596 
597 template<>
deserialize(const xmlNode * cur,RouteTraits::PtrSerializingCtx ctx)598 std::variant<status_t, RouteTraits::Element> PolicySerializer::deserialize<RouteTraits>(
599         const xmlNode *cur, RouteTraits::PtrSerializingCtx ctx)
600 {
601     using Attributes = RouteTraits::Attributes;
602 
603     std::string type = getXmlAttribute(cur, Attributes::type);
604     if (type.empty()) {
605         ALOGE("%s: No %s found", __func__, Attributes::type);
606         return BAD_VALUE;
607     }
608     audio_route_type_t routeType = (type == Attributes::typeMix) ?
609                 AUDIO_ROUTE_MIX : AUDIO_ROUTE_MUX;
610 
611     ALOGV("%s: %s %s=%s", __func__, RouteTraits::tag, Attributes::type, type.c_str());
612     RouteTraits::Element route = new AudioRoute(routeType);
613 
614     std::string sinkAttr = getXmlAttribute(cur, Attributes::sink);
615     if (sinkAttr.empty()) {
616         ALOGE("%s: No %s found", __func__, Attributes::sink);
617         return BAD_VALUE;
618     }
619     // Convert Sink name to port pointer
620     sp<PolicyAudioPort> sink = ctx->findPortByTagName(sinkAttr);
621     if (sink == NULL) {
622         if (!mIgnoreVendorExtensions) {
623             ALOGE("%s: no sink found with name \"%s\"", __func__, sinkAttr.c_str());
624             return BAD_VALUE;
625         } else {
626             ALOGW("%s: skipping route to sink \"%s\" as it likely has vendor extension type",
627                   __func__, sinkAttr.c_str());
628             return NO_INIT;
629         }
630     }
631     route->setSink(sink);
632 
633     std::string sourcesAttr = getXmlAttribute(cur, Attributes::sources);
634     if (sourcesAttr.empty()) {
635         ALOGE("%s: No %s found", __func__, Attributes::sources);
636         return BAD_VALUE;
637     }
638     // Tokenize and Convert Sources name to port pointer
639     PolicyAudioPortVector sources;
640     UniqueCPtr<char> sourcesLiteral{strndup(
641                 sourcesAttr.c_str(), strlen(sourcesAttr.c_str()))};
642     char *devTag = strtok(sourcesLiteral.get(), ",");
643     while (devTag != NULL) {
644         if (strlen(devTag) != 0) {
645             sp<PolicyAudioPort> source = ctx->findPortByTagName(devTag);
646             if (source == NULL) {
647                 if (!mIgnoreVendorExtensions) {
648                     ALOGE("%s: no source found with name \"%s\"", __func__, devTag);
649                     return BAD_VALUE;
650                 } else {
651                     ALOGW("%s: skipping route source \"%s\" as it likely has vendor extension type",
652                           __func__, devTag);
653                 }
654             } else {
655                 sources.add(source);
656             }
657         }
658         devTag = strtok(NULL, ",");
659     }
660 
661     sink->addRoute(route);
662     for (size_t i = 0; i < sources.size(); i++) {
663         sp<PolicyAudioPort> source = sources.itemAt(i);
664         source->addRoute(route);
665     }
666     route->setSources(sources);
667     return route;
668 }
669 
670 template<>
deserialize(const xmlNode * cur,ModuleTraits::PtrSerializingCtx ctx)671 std::variant<status_t, ModuleTraits::Element> PolicySerializer::deserialize<ModuleTraits>(
672         const xmlNode *cur, ModuleTraits::PtrSerializingCtx ctx)
673 {
674     using Attributes = ModuleTraits::Attributes;
675     auto& tag = ModuleTraits::tag;
676     auto& childAttachedDevicesTag = ModuleTraits::childAttachedDevicesTag;
677     auto& childAttachedDeviceTag = ModuleTraits::childAttachedDeviceTag;
678     auto& childDefaultOutputDeviceTag = ModuleTraits::childDefaultOutputDeviceTag;
679 
680     std::string name = getXmlAttribute(cur, Attributes::name);
681     if (name.empty()) {
682         ALOGE("%s: No %s found", __func__, Attributes::name);
683         return BAD_VALUE;
684     }
685     uint32_t versionMajor = 0, versionMinor = 0;
686     std::string versionLiteral = getXmlAttribute(cur, Attributes::version);
687     if (!versionLiteral.empty()) {
688         sscanf(versionLiteral.c_str(), "%u.%u", &versionMajor, &versionMinor);
689         ALOGV("%s: mHalVersion = major %u minor %u",  __func__,
690               versionMajor, versionMajor);
691     }
692 
693     ALOGV("%s: %s %s=%s", __func__, ModuleTraits::tag, Attributes::name, name.c_str());
694 
695     ModuleTraits::Element module = new HwModule(name.c_str(), versionMajor, versionMinor);
696 
697     // Deserialize children: Audio Mix Port, Audio Device Ports (Source/Sink), Audio Routes
698     MixPortTraits::Collection mixPorts;
699     status_t status = deserializeCollection<MixPortTraits>(cur, &mixPorts, NULL);
700     if (status != NO_ERROR) {
701         return status;
702     }
703     module->setProfiles(mixPorts);
704 
705     DevicePortTraits::Collection devicePorts;
706     status = deserializeCollection<DevicePortTraits>(cur, &devicePorts, NULL);
707     if (status != NO_ERROR) {
708         return status;
709     }
710     module->setDeclaredDevices(devicePorts);
711 
712     RouteTraits::Collection routes;
713     status = deserializeCollection<RouteTraits>(cur, &routes, module.get());
714     if (status != NO_ERROR) {
715         return status;
716     }
717     module->setRoutes(routes);
718 
719     for (const xmlNode *children = cur->xmlChildrenNode; children != NULL;
720          children = children->next) {
721         if (!xmlStrcmp(children->name, reinterpret_cast<const xmlChar*>(childAttachedDevicesTag))) {
722             ALOGV("%s: %s %s found", __func__, tag, childAttachedDevicesTag);
723             for (const xmlNode *child = children->xmlChildrenNode; child != NULL;
724                  child = child->next) {
725                 if (!xmlStrcmp(child->name,
726                                 reinterpret_cast<const xmlChar*>(childAttachedDeviceTag))) {
727                     auto attachedDevice = make_xmlUnique(xmlNodeListGetString(
728                                     child->doc, child->xmlChildrenNode, 1));
729                     if (attachedDevice != nullptr) {
730                         ALOGV("%s: %s %s=%s", __func__, tag, childAttachedDeviceTag,
731                                 reinterpret_cast<const char*>(attachedDevice.get()));
732                         sp<DeviceDescriptor> device = module->getDeclaredDevices().
733                                 getDeviceFromTagName(std::string(reinterpret_cast<const char*>(
734                                                         attachedDevice.get())));
735                         if (device == NULL) {
736                             if (mIgnoreVendorExtensions) {
737                                 ALOGW("%s: skipped attached device \"%s\" because it likely uses a "
738                                       "vendor extension type",
739                                       __func__,
740                                       reinterpret_cast<const char*>(attachedDevice.get()));
741                             } else {
742                                 ALOGE("%s: got null device in %s, \"%s\"", __func__, child->name,
743                                       reinterpret_cast<const char*>(attachedDevice.get()));
744                             }
745                             continue;
746                         }
747                         ctx->addDevice(device);
748                     }
749                 }
750             }
751         }
752         if (!xmlStrcmp(children->name,
753                         reinterpret_cast<const xmlChar*>(childDefaultOutputDeviceTag))) {
754             auto defaultOutputDevice = make_xmlUnique(xmlNodeListGetString(
755                             children->doc, children->xmlChildrenNode, 1));
756             if (defaultOutputDevice != nullptr) {
757                 ALOGV("%s: %s %s=%s", __func__, tag, childDefaultOutputDeviceTag,
758                         reinterpret_cast<const char*>(defaultOutputDevice.get()));
759                 sp<DeviceDescriptor> device = module->getDeclaredDevices().getDeviceFromTagName(
760                         std::string(reinterpret_cast<const char*>(defaultOutputDevice.get())));
761                 if (device != 0 && ctx->getDefaultOutputDevice() == 0) {
762                     ctx->setDefaultOutputDevice(device);
763                     ALOGV("%s: default is %08x",
764                             __func__, ctx->getDefaultOutputDevice()->type());
765                 }
766             }
767         }
768     }
769     return module;
770 }
771 
772 template<>
773 std::variant<status_t, GlobalConfigTraits::Element>
deserialize(const xmlNode * root,GlobalConfigTraits::PtrSerializingCtx config)774 PolicySerializer::deserialize<GlobalConfigTraits>(
775         const xmlNode *root, GlobalConfigTraits::PtrSerializingCtx config)
776 {
777     using Attributes = GlobalConfigTraits::Attributes;
778 
779     for (const xmlNode *cur = root->xmlChildrenNode; cur != NULL; cur = cur->next) {
780         if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(GlobalConfigTraits::tag))) {
781             bool value;
782             std::string attr = getXmlAttribute(cur, Attributes::callScreenModeSupported);
783             if (!attr.empty() &&
784                     convertTo<std::string, bool>(attr, value)) {
785                 config->setCallScreenModeSupported(value);
786             }
787             std::string engineLibrarySuffix = getXmlAttribute(cur, Attributes::engineLibrarySuffix);
788             if (!engineLibrarySuffix.empty()) {
789                 config->setEngineLibraryNameSuffix(engineLibrarySuffix);
790             }
791             return NO_ERROR;
792         }
793     }
794     return NO_ERROR;
795 }
796 
797 template<>
798 std::variant<status_t, SurroundSoundTraits::Element>
deserialize(const xmlNode * root,SurroundSoundTraits::PtrSerializingCtx config)799 PolicySerializer::deserialize<SurroundSoundTraits>(
800         const xmlNode *root, SurroundSoundTraits::PtrSerializingCtx config)
801 {
802     config->setDefaultSurroundFormats();
803 
804     for (const xmlNode *cur = root->xmlChildrenNode; cur != NULL; cur = cur->next) {
805         if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(SurroundSoundTraits::tag))) {
806             AudioPolicyConfig::SurroundFormats formats;
807             status_t status = deserializeCollection<SurroundSoundFormatTraits>(
808                     cur, &formats, nullptr);
809             if (status == NO_ERROR) {
810                 config->setSurroundFormats(formats);
811             }
812             return NO_ERROR;
813         }
814     }
815     return NO_ERROR;
816 }
817 
818 template<>
819 std::variant<status_t, SurroundSoundFormatTraits::Element>
deserialize(const xmlNode * cur,SurroundSoundFormatTraits::PtrSerializingCtx)820 PolicySerializer::deserialize<SurroundSoundFormatTraits>(
821         const xmlNode *cur, SurroundSoundFormatTraits::PtrSerializingCtx /*serializingContext*/)
822 {
823     using Attributes = SurroundSoundFormatTraits::Attributes;
824 
825     std::string formatLiteral = getXmlAttribute(cur, Attributes::name);
826     if (formatLiteral.empty()) {
827         ALOGE("%s: No %s found for a surround format", __func__, Attributes::name);
828         return BAD_VALUE;
829     }
830     if (mIgnoreVendorExtensions && maybeVendorExtension(formatLiteral)) {
831         ALOGI("%s: vendor extension format \"%s\" skipped", __func__, formatLiteral.c_str());
832         return NO_INIT;
833     }
834     audio_format_t format = formatFromString(formatLiteral);
835     if (format == AUDIO_FORMAT_DEFAULT) {
836         ALOGE("%s: Unrecognized format %s", __func__, formatLiteral.c_str());
837         return BAD_VALUE;
838     }
839     SurroundSoundFormatTraits::Element pair = std::make_pair(
840             format, SurroundSoundFormatTraits::Collection::mapped_type{});
841 
842     std::string subformatsLiteral = getXmlAttribute(cur, Attributes::subformats);
843     if (subformatsLiteral.empty()) return pair;
844     FormatVector subformats = formatsFromString(subformatsLiteral, " ");
845     for (const auto& subformat : subformats) {
846         auto result = pair.second.insert(subformat);
847         if (!result.second) {
848             ALOGE("%s: could not add subformat %x to collection", __func__, subformat);
849             return BAD_VALUE;
850         }
851     }
852     return pair;
853 }
854 
deserialize(const char * configFile,AudioPolicyConfig * config,bool ignoreVendorExtensions)855 status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig *config,
856                                        bool ignoreVendorExtensions)
857 {
858     mIgnoreVendorExtensions = ignoreVendorExtensions;
859     auto doc = make_xmlUnique(xmlParseFile(configFile));
860     if (doc == nullptr) {
861         ALOGE("%s: Could not parse %s document.", __func__, configFile);
862         return BAD_VALUE;
863     }
864     xmlNodePtr root = xmlDocGetRootElement(doc.get());
865     if (root == NULL) {
866         ALOGE("%s: Could not parse %s document: empty.", __func__, configFile);
867         return BAD_VALUE;
868     }
869     if (xmlXIncludeProcess(doc.get()) < 0) {
870         ALOGE("%s: libxml failed to resolve XIncludes on %s document.", __func__, configFile);
871     }
872 
873     if (xmlStrcmp(root->name, reinterpret_cast<const xmlChar*>(rootName)))  {
874         ALOGE("%s: No %s root element found in xml data %s.", __func__, rootName,
875                 reinterpret_cast<const char*>(root->name));
876         return BAD_VALUE;
877     }
878 
879     std::string version = getXmlAttribute(root, versionAttribute);
880     if (version.empty()) {
881         ALOGE("%s: No version found in root node %s", __func__, rootName);
882         return BAD_VALUE;
883     }
884     if (version == "7.0" || version == "7.1") {
885         mChannelMasksSeparator = mSamplingRatesSeparator = mFlagsSeparator = " ";
886     } else if (version != "1.0") {
887         ALOGE("%s: Version does not match; expected \"1.0\", \"7.0\", or \"7.1\" got \"%s\"",
888                 __func__, version.c_str());
889         return BAD_VALUE;
890     }
891     // Let's deserialize children
892     // Modules
893     ModuleTraits::Collection modules;
894     status_t status = deserializeCollection<ModuleTraits>(root, &modules, config);
895     if (status != NO_ERROR) {
896         return status;
897     }
898     config->setHwModules(modules);
899 
900     // Global Configuration
901     deserialize<GlobalConfigTraits>(root, config);
902 
903     // Surround configuration
904     deserialize<SurroundSoundTraits>(root, config);
905 
906     return android::OK;
907 }
908 
909 }  // namespace
910 
deserializeAudioPolicyFile(const char * fileName,AudioPolicyConfig * config)911 status_t deserializeAudioPolicyFile(const char *fileName, AudioPolicyConfig *config)
912 {
913     PolicySerializer serializer;
914     status_t status = serializer.deserialize(fileName, config);
915     return status;
916 }
917 
deserializeAudioPolicyFileForVts(const char * fileName,AudioPolicyConfig * config)918 status_t deserializeAudioPolicyFileForVts(const char *fileName, AudioPolicyConfig *config)
919 {
920     PolicySerializer serializer;
921     status_t status = serializer.deserialize(fileName, config, true /*ignoreVendorExtensions*/);
922     return status;
923 }
924 
925 } // namespace android
926