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