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