1f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie/*
2f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie * Copyright (C) 2015 The Android Open Source Project
3f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie *
4f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie * Licensed under the Apache License, Version 2.0 (the "License");
5f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie * you may not use this file except in compliance with the License.
6f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie * You may obtain a copy of the License at
7f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie *
8f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie *      http://www.apache.org/licenses/LICENSE-2.0
9f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie *
10f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie * Unless required by applicable law or agreed to in writing, software
11f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie * distributed under the License is distributed on an "AS IS" BASIS,
12f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie * See the License for the specific language governing permissions and
14f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie * limitations under the License.
15f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie */
16f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
17f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie#define LOG_TAG "APM::Serializer"
18f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie//#define LOG_NDEBUG 0
19f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
20f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie#include "Serializer.h"
21913d06c099bd689375483a839e11057ccf284d1cMikhail Naganov#include <media/convert.h>
22f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie#include "TypeConverter.h"
23f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie#include <libxml/parser.h>
24f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie#include <libxml/xinclude.h>
25f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie#include <string>
26f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie#include <sstream>
27f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie#include <istream>
28f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
29f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieusing std::string;
30f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
31f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffienamespace android {
32f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
33f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffiestring getXmlAttribute(const xmlNode *cur, const char *attribute)
34f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie{
35f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    xmlChar *xmlValue = xmlGetProp(cur, (const xmlChar*)attribute);
36f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (xmlValue == NULL) {
37f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return "";
38f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
39f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string value((const char*)xmlValue);
40f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    xmlFree(xmlValue);
41f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    return value;
42f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie}
43f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
44f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieusing utilities::convertTo;
45f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
46f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char *const PolicySerializer::rootName = "audioPolicyConfiguration";
47f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char *const PolicySerializer::versionAttribute = "version";
48f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst uint32_t PolicySerializer::gMajor = 1;
49f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst uint32_t PolicySerializer::gMinor = 0;
50c9d7c4e35afd48ac8a315f53666943b6210dafa1François Gaffiestatic const char *const gReferenceElementName = "reference";
51c9d7c4e35afd48ac8a315f53666943b6210dafa1François Gaffiestatic const char *const gReferenceAttributeName = "name";
52c9d7c4e35afd48ac8a315f53666943b6210dafa1François Gaffie
5319219b44e05555b29e00ce56ce273d168fa83888François Gaffietemplate <class Trait>
54c9d7c4e35afd48ac8a315f53666943b6210dafa1François Gaffiestatic void getReference(const _xmlNode *root, const _xmlNode *&refNode, const string &refName)
55c9d7c4e35afd48ac8a315f53666943b6210dafa1François Gaffie{
5619219b44e05555b29e00ce56ce273d168fa83888François Gaffie    const _xmlNode *col = root;
5719219b44e05555b29e00ce56ce273d168fa83888François Gaffie    while (col != NULL) {
5819219b44e05555b29e00ce56ce273d168fa83888François Gaffie        if (!xmlStrcmp(col->name, (const xmlChar *)Trait::collectionTag)) {
5919219b44e05555b29e00ce56ce273d168fa83888François Gaffie            const xmlNode *cur = col->children;
6019219b44e05555b29e00ce56ce273d168fa83888François Gaffie            while (cur != NULL) {
6119219b44e05555b29e00ce56ce273d168fa83888François Gaffie                if ((!xmlStrcmp(cur->name, (const xmlChar *)gReferenceElementName))) {
6219219b44e05555b29e00ce56ce273d168fa83888François Gaffie                    string name = getXmlAttribute(cur, gReferenceAttributeName);
6319219b44e05555b29e00ce56ce273d168fa83888François Gaffie                    if (refName == name) {
6419219b44e05555b29e00ce56ce273d168fa83888François Gaffie                        refNode = cur;
6519219b44e05555b29e00ce56ce273d168fa83888François Gaffie                        return;
6619219b44e05555b29e00ce56ce273d168fa83888François Gaffie                    }
6719219b44e05555b29e00ce56ce273d168fa83888François Gaffie                }
6819219b44e05555b29e00ce56ce273d168fa83888François Gaffie                cur = cur->next;
6919219b44e05555b29e00ce56ce273d168fa83888François Gaffie            }
70c9d7c4e35afd48ac8a315f53666943b6210dafa1François Gaffie        }
7119219b44e05555b29e00ce56ce273d168fa83888François Gaffie        col = col->next;
72c9d7c4e35afd48ac8a315f53666943b6210dafa1François Gaffie    }
73c9d7c4e35afd48ac8a315f53666943b6210dafa1François Gaffie    return;
74c9d7c4e35afd48ac8a315f53666943b6210dafa1François Gaffie}
75f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
76f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffietemplate <class Trait>
77f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffiestatic status_t deserializeCollection(_xmlDoc *doc, const _xmlNode *cur,
78f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                                      typename Trait::Collection &collection,
79f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                                      typename Trait::PtrSerializingCtx serializingContext)
80f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie{
81f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    const xmlNode *root = cur->xmlChildrenNode;
82f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    while (root != NULL) {
83f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        if (xmlStrcmp(root->name, (const xmlChar *)Trait::collectionTag) &&
84f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                xmlStrcmp(root->name, (const xmlChar *)Trait::tag)) {
85f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            root = root->next;
86f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            continue;
87f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        }
88d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie        const xmlNode *child = root;
89d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie        if (!xmlStrcmp(child->name, (const xmlChar *)Trait::collectionTag)) {
90d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie            child = child->xmlChildrenNode;
91f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        }
92d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie        while (child != NULL) {
93d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie            if (!xmlStrcmp(child->name, (const xmlChar *)Trait::tag)) {
94f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                typename Trait::PtrElement element;
95d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie                status_t status = Trait::deserialize(doc, child, element, serializingContext);
96f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                if (status != NO_ERROR) {
97f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                    return status;
98f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                }
99f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                if (collection.add(element) < 0) {
100f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                    ALOGE("%s: could not add element to %s collection", __FUNCTION__,
101f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                          Trait::collectionTag);
102f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                }
103f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            }
104d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie            child = child->next;
105d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie        }
106d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie        if (!xmlStrcmp(root->name, (const xmlChar *)Trait::tag)) {
107d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie            return NO_ERROR;
108f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        }
109d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie        root = root->next;
110f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
111d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie    return NO_ERROR;
112f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie}
113f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
114f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char *const AudioGainTraits::tag = "gain";
115f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char *const AudioGainTraits::collectionTag = "gains";
116f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
117f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char AudioGainTraits::Attributes::mode[] = "mode";
118f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char AudioGainTraits::Attributes::channelMask[] = "channel_mask";
119f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char AudioGainTraits::Attributes::minValueMB[] = "minValueMB";
120f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char AudioGainTraits::Attributes::maxValueMB[] = "maxValueMB";
121f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char AudioGainTraits::Attributes::defaultValueMB[] = "defaultValueMB";
122f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char AudioGainTraits::Attributes::stepValueMB[] = "stepValueMB";
123f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char AudioGainTraits::Attributes::minRampMs[] = "minRampMs";
124f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char AudioGainTraits::Attributes::maxRampMs[] = "maxRampMs";
125f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
126f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffiestatus_t AudioGainTraits::deserialize(_xmlDoc */*doc*/, const _xmlNode *root, PtrElement &gain,
127f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                                      PtrSerializingCtx /*serializingContext*/)
128f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie{
129f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    static uint32_t index = 0;
130f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    gain = new Element(index++, true);
131f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
132f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string mode = getXmlAttribute(root, Attributes::mode);
133f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (!mode.empty()) {
134f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        gain->setMode(GainModeConverter::maskFromString(mode));
135f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
136f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
137f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string channelsLiteral = getXmlAttribute(root, Attributes::channelMask);
138f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (!channelsLiteral.empty()) {
139f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        gain->setChannelMask(channelMaskFromString(channelsLiteral));
140f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
141f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
142f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string minValueMBLiteral = getXmlAttribute(root, Attributes::minValueMB);
143f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    uint32_t minValueMB;
144f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (!minValueMBLiteral.empty() && convertTo(minValueMBLiteral, minValueMB)) {
145f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        gain->setMinValueInMb(minValueMB);
146f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
147f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
148f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string maxValueMBLiteral = getXmlAttribute(root, Attributes::maxValueMB);
149f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    uint32_t maxValueMB;
150f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (!maxValueMBLiteral.empty() && convertTo(maxValueMBLiteral, maxValueMB)) {
151f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        gain->setMaxValueInMb(maxValueMB);
152f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
153f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
154f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string defaultValueMBLiteral = getXmlAttribute(root, Attributes::defaultValueMB);
155f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    uint32_t defaultValueMB;
156f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (!defaultValueMBLiteral.empty() && convertTo(defaultValueMBLiteral, defaultValueMB)) {
157f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        gain->setDefaultValueInMb(defaultValueMB);
158f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
159f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
160f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string stepValueMBLiteral = getXmlAttribute(root, Attributes::stepValueMB);
161f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    uint32_t stepValueMB;
162f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (!stepValueMBLiteral.empty() && convertTo(stepValueMBLiteral, stepValueMB)) {
163f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        gain->setStepValueInMb(stepValueMB);
164f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
165f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
166f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string minRampMsLiteral = getXmlAttribute(root, Attributes::minRampMs);
167f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    uint32_t minRampMs;
168f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (!minRampMsLiteral.empty() && convertTo(minRampMsLiteral, minRampMs)) {
169f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        gain->setMinRampInMs(minRampMs);
170f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
171f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
172f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string maxRampMsLiteral = getXmlAttribute(root, Attributes::maxRampMs);
173f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    uint32_t maxRampMs;
174f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (!maxRampMsLiteral.empty() && convertTo(maxRampMsLiteral, maxRampMs)) {
175f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        gain->setMaxRampInMs(maxRampMs);
176f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
177f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    ALOGV("%s: adding new gain mode %08x channel mask %08x min mB %d max mB %d", __FUNCTION__,
178f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie          gain->getMode(), gain->getChannelMask(), gain->getMinValueInMb(),
179f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie          gain->getMaxValueInMb());
180f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
181f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (gain->getMode() == 0) {
182f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return BAD_VALUE;
183f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
184f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    return NO_ERROR;
185f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie}
186f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
187f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char *const AudioProfileTraits::collectionTag = "profiles";
188f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char *const AudioProfileTraits::tag = "profile";
189f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
190f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char AudioProfileTraits::Attributes::name[] = "name";
191f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char AudioProfileTraits::Attributes::samplingRates[] = "samplingRates";
192f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char AudioProfileTraits::Attributes::format[] = "format";
193f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char AudioProfileTraits::Attributes::channelMasks[] = "channelMasks";
194f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
195f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffiestatus_t AudioProfileTraits::deserialize(_xmlDoc */*doc*/, const _xmlNode *root, PtrElement &profile,
196f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                                         PtrSerializingCtx /*serializingContext*/)
197f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie{
198f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string samplingRates = getXmlAttribute(root, Attributes::samplingRates);
199f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string format = getXmlAttribute(root, Attributes::format);
200f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string channels = getXmlAttribute(root, Attributes::channelMasks);
201f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
202913d06c099bd689375483a839e11057ccf284d1cMikhail Naganov    profile = new Element(formatFromString(format, gDynamicFormat),
203913d06c099bd689375483a839e11057ccf284d1cMikhail Naganov                          channelMasksFromString(channels, ","),
204f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                          samplingRatesFromString(samplingRates, ","));
205f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
206f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    profile->setDynamicFormat(profile->getFormat() == gDynamicFormat);
207f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    profile->setDynamicChannels(profile->getChannels().isEmpty());
208f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    profile->setDynamicRate(profile->getSampleRates().isEmpty());
209f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
210f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    return NO_ERROR;
211f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie}
212f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
213f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
214f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char *const MixPortTraits::collectionTag = "mixPorts";
215f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char *const MixPortTraits::tag = "mixPort";
216f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
217f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char MixPortTraits::Attributes::name[] = "name";
218f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char MixPortTraits::Attributes::role[] = "role";
219f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char MixPortTraits::Attributes::flags[] = "flags";
220f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
221f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffiestatus_t MixPortTraits::deserialize(_xmlDoc *doc, const _xmlNode *child, PtrElement &mixPort,
222f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                                    PtrSerializingCtx /*serializingContext*/)
223f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie{
224f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string name = getXmlAttribute(child, Attributes::name);
225f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (name.empty()) {
226f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        ALOGE("%s: No %s found", __FUNCTION__, Attributes::name);
227f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return BAD_VALUE;
228f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
229f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::name, name.c_str());
230f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string role = getXmlAttribute(child, Attributes::role);
231f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (role.empty()) {
232f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        ALOGE("%s: No %s found", __FUNCTION__, Attributes::role);
233f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return BAD_VALUE;
234f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
235f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    ALOGV("%s: Role=%s", __FUNCTION__, role.c_str());
236f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    audio_port_role_t portRole = role == "source" ? AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
237f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
238f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    mixPort = new Element(String8(name.c_str()), portRole);
239f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
240f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    AudioProfileTraits::Collection profiles;
241f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    deserializeCollection<AudioProfileTraits>(doc, child, profiles, NULL);
242f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (profiles.isEmpty()) {
243f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        sp <AudioProfile> dynamicProfile = new AudioProfile(gDynamicFormat,
244f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                                                            ChannelsVector(), SampleRateVector());
245f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        dynamicProfile->setDynamicFormat(true);
246f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        dynamicProfile->setDynamicChannels(true);
247f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        dynamicProfile->setDynamicRate(true);
248f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        profiles.add(dynamicProfile);
249f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
250f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    mixPort->setAudioProfiles(profiles);
251f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
252f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string flags = getXmlAttribute(child, Attributes::flags);
253f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (!flags.empty()) {
254f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        // Source role
255f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        if (portRole == AUDIO_PORT_ROLE_SOURCE) {
256f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            mixPort->setFlags(OutputFlagConverter::maskFromString(flags));
257f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        } else {
258f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            // Sink role
259f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            mixPort->setFlags(InputFlagConverter::maskFromString(flags));
260f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        }
261f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
262f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    // Deserialize children
263f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    AudioGainTraits::Collection gains;
264f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    deserializeCollection<AudioGainTraits>(doc, child, gains, NULL);
265f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    mixPort->setGains(gains);
266f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
267f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    return NO_ERROR;
268f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie}
269f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
270f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char *const DevicePortTraits::tag = "devicePort";
271f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char *const DevicePortTraits::collectionTag = "devicePorts";
272f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
273f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char DevicePortTraits::Attributes::tagName[] = "tagName";
274f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char DevicePortTraits::Attributes::type[] = "type";
275f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char DevicePortTraits::Attributes::role[] = "role";
276f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char DevicePortTraits::Attributes::address[] = "address";
277f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char DevicePortTraits::Attributes::roleSource[] = "source";
278f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
279f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffiestatus_t DevicePortTraits::deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &deviceDesc,
280f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                                       PtrSerializingCtx /*serializingContext*/)
281f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie{
282f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string name = getXmlAttribute(root, Attributes::tagName);
283f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (name.empty()) {
284f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        ALOGE("%s: No %s found", __FUNCTION__, Attributes::tagName);
285f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return BAD_VALUE;
286f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
287f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::tagName, name.c_str());
288f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string typeName = getXmlAttribute(root, Attributes::type);
289f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (typeName.empty()) {
290f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        ALOGE("%s: no type for %s", __FUNCTION__, name.c_str());
291f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return BAD_VALUE;
292f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
293f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::type, typeName.c_str());
294f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string role = getXmlAttribute(root, Attributes::role);
295f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (role.empty()) {
296f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        ALOGE("%s: No %s found", __FUNCTION__, Attributes::role);
297f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return BAD_VALUE;
298f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
299f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::role, role.c_str());
300f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    audio_port_role_t portRole = (role == Attributes::roleSource) ?
301f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
302f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
303f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    audio_devices_t type = AUDIO_DEVICE_NONE;
304913d06c099bd689375483a839e11057ccf284d1cMikhail Naganov    if (!deviceFromString(typeName, type) ||
305f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            (!audio_is_input_device(type) && portRole == AUDIO_PORT_ROLE_SOURCE) ||
306f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            (!audio_is_output_devices(type) && portRole == AUDIO_PORT_ROLE_SINK)) {
307f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        ALOGW("%s: bad type %08x", __FUNCTION__, type);
308f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return BAD_VALUE;
309f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
310f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    deviceDesc = new Element(type, String8(name.c_str()));
311f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
312f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string address = getXmlAttribute(root, Attributes::address);
313f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (!address.empty()) {
314f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        ALOGV("%s: address=%s for %s", __FUNCTION__, address.c_str(), name.c_str());
315f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        deviceDesc->mAddress = String8(address.c_str());
316f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
317f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
318f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    AudioProfileTraits::Collection profiles;
319f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    deserializeCollection<AudioProfileTraits>(doc, root, profiles, NULL);
320f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (profiles.isEmpty()) {
321f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        sp <AudioProfile> dynamicProfile = new AudioProfile(gDynamicFormat,
322f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                                                            ChannelsVector(), SampleRateVector());
323f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        dynamicProfile->setDynamicFormat(true);
324f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        dynamicProfile->setDynamicChannels(true);
325f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        dynamicProfile->setDynamicRate(true);
326f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        profiles.add(dynamicProfile);
327f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
328f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    deviceDesc->setAudioProfiles(profiles);
329f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
330f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    // Deserialize AudioGain children
331f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    deserializeCollection<AudioGainTraits>(doc, root, deviceDesc->mGains, NULL);
332f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    ALOGV("%s: adding device tag %s type %08x address %s", __FUNCTION__,
333f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie          deviceDesc->getName().string(), type, deviceDesc->mAddress.string());
334f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    return NO_ERROR;
335f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie}
336f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
337f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char *const RouteTraits::tag = "route";
338f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char *const RouteTraits::collectionTag = "routes";
339f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
340f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char RouteTraits::Attributes::type[] = "type";
341f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char RouteTraits::Attributes::typeMix[] = "mix";
342f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char RouteTraits::Attributes::sink[] = "sink";
343f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char RouteTraits::Attributes::sources[] = "sources";
344f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
345f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
346f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffiestatus_t RouteTraits::deserialize(_xmlDoc */*doc*/, const _xmlNode *root, PtrElement &element,
347f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                                  PtrSerializingCtx ctx)
348f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie{
349f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string type = getXmlAttribute(root, Attributes::type);
350f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (type.empty()) {
351f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        ALOGE("%s: No %s found", __FUNCTION__, Attributes::type);
352f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return BAD_VALUE;
353f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
354f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    audio_route_type_t routeType = (type == Attributes::typeMix) ?
355f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                AUDIO_ROUTE_MIX : AUDIO_ROUTE_MUX;
356f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
357f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::type, type.c_str());
358f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    element = new Element(routeType);
359f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
360f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string sinkAttr = getXmlAttribute(root, Attributes::sink);
361f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (sinkAttr.empty()) {
362f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        ALOGE("%s: No %s found", __FUNCTION__, Attributes::sink);
363f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return BAD_VALUE;
364f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
365f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    // Convert Sink name to port pointer
366f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    sp<AudioPort> sink = ctx->findPortByTagName(String8(sinkAttr.c_str()));
367f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (sink == NULL) {
368f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        ALOGE("%s: no sink found with name=%s", __FUNCTION__, sinkAttr.c_str());
369f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return BAD_VALUE;
370f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
371f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    element->setSink(sink);
372f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
373f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string sourcesAttr = getXmlAttribute(root, Attributes::sources);
374f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (sourcesAttr.empty()) {
375f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        ALOGE("%s: No %s found", __FUNCTION__, Attributes::sources);
376f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return BAD_VALUE;
377f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
378f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    // Tokenize and Convert Sources name to port pointer
379f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    AudioPortVector sources;
380f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    char *sourcesLiteral = strndup(sourcesAttr.c_str(), strlen(sourcesAttr.c_str()));
381f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    char *devTag = strtok(sourcesLiteral, ",");
382f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    while (devTag != NULL) {
383f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        if (strlen(devTag) != 0) {
384f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            sp<AudioPort> source = ctx->findPortByTagName(String8(devTag));
385f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            if (source == NULL) {
386f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                ALOGE("%s: no source found with name=%s", __FUNCTION__, devTag);
387cc7c0d6fff90c867f661b795e803043aee4d0bb8Yunlian Jiang                free(sourcesLiteral);
388f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                return BAD_VALUE;
389f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            }
390f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            sources.add(source);
391f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        }
392f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        devTag = strtok(NULL, ",");
393f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
394f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    free(sourcesLiteral);
395f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
396f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    sink->addRoute(element);
397f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    for (size_t i = 0; i < sources.size(); i++) {
398f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        sp<AudioPort> source = sources.itemAt(i);
399f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        source->addRoute(element);
400f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
401f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    element->setSources(sources);
402f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    return NO_ERROR;
403f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie}
404f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
405f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char *const ModuleTraits::childAttachedDevicesTag = "attachedDevices";
406f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char *const ModuleTraits::childAttachedDeviceTag = "item";
407f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char *const ModuleTraits::childDefaultOutputDeviceTag = "defaultOutputDevice";
408f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
409f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char *const ModuleTraits::tag = "module";
410f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char *const ModuleTraits::collectionTag = "modules";
411f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
412f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char ModuleTraits::Attributes::name[] = "name";
413f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char ModuleTraits::Attributes::version[] = "halVersion";
414f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
415f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffiestatus_t ModuleTraits::deserialize(xmlDocPtr doc, const xmlNode *root, PtrElement &module,
416f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                                   PtrSerializingCtx ctx)
417f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie{
418f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string name = getXmlAttribute(root, Attributes::name);
419f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (name.empty()) {
420f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        ALOGE("%s: No %s found", __FUNCTION__, Attributes::name);
421f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return BAD_VALUE;
422f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
4239ee0540d3a61bff03d561ca431a371c3d9335d2bMikhail Naganov    uint32_t versionMajor = 0, versionMinor = 0;
424f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string versionLiteral = getXmlAttribute(root, Attributes::version);
425f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (!versionLiteral.empty()) {
4269ee0540d3a61bff03d561ca431a371c3d9335d2bMikhail Naganov        sscanf(versionLiteral.c_str(), "%u.%u", &versionMajor, &versionMinor);
4279ee0540d3a61bff03d561ca431a371c3d9335d2bMikhail Naganov        ALOGV("%s: mHalVersion = major %u minor %u",  __FUNCTION__,
4289ee0540d3a61bff03d561ca431a371c3d9335d2bMikhail Naganov              versionMajor, versionMajor);
429f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
430f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
431f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::name, name.c_str());
432f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
4339ee0540d3a61bff03d561ca431a371c3d9335d2bMikhail Naganov    module = new Element(name.c_str(), versionMajor, versionMinor);
434f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
435f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    // Deserialize childrens: Audio Mix Port, Audio Device Ports (Source/Sink), Audio Routes
436f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    MixPortTraits::Collection mixPorts;
437f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    deserializeCollection<MixPortTraits>(doc, root, mixPorts, NULL);
438f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    module->setProfiles(mixPorts);
439f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
440f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    DevicePortTraits::Collection devicePorts;
441f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    deserializeCollection<DevicePortTraits>(doc, root, devicePorts, NULL);
442f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    module->setDeclaredDevices(devicePorts);
443f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
444f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    RouteTraits::Collection routes;
445f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    deserializeCollection<RouteTraits>(doc, root, routes, module.get());
446f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    module->setRoutes(routes);
447f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
448f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    const xmlNode *children = root->xmlChildrenNode;
449f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    while (children != NULL) {
450f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        if (!xmlStrcmp(children->name, (const xmlChar *)childAttachedDevicesTag)) {
451f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            ALOGV("%s: %s %s found", __FUNCTION__, tag, childAttachedDevicesTag);
452f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            const xmlNode *child = children->xmlChildrenNode;
453f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            while (child != NULL) {
454f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                if (!xmlStrcmp(child->name, (const xmlChar *)childAttachedDeviceTag)) {
455f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                    xmlChar *attachedDevice = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
456f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                    if (attachedDevice != NULL) {
457f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                        ALOGV("%s: %s %s=%s", __FUNCTION__, tag, childAttachedDeviceTag,
458f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                              (const char*)attachedDevice);
459f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                        sp<DeviceDescriptor> device =
460f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                                module->getDeclaredDevices().getDeviceFromTagName(String8((const char*)attachedDevice));
461f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                        ctx->addAvailableDevice(device);
462f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                        xmlFree(attachedDevice);
463f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                    }
464f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                }
465f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                child = child->next;
466f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            }
467f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        }
468f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        if (!xmlStrcmp(children->name, (const xmlChar *)childDefaultOutputDeviceTag)) {
469f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            xmlChar *defaultOutputDevice = xmlNodeListGetString(doc, children->xmlChildrenNode, 1);;
470f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            if (defaultOutputDevice != NULL) {
471f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                ALOGV("%s: %s %s=%s", __FUNCTION__, tag, childDefaultOutputDeviceTag,
472f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                      (const char*)defaultOutputDevice);
473f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                sp<DeviceDescriptor> device =
474f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                        module->getDeclaredDevices().getDeviceFromTagName(String8((const char*)defaultOutputDevice));
475f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                if (device != 0 && ctx->getDefaultOutputDevice() == 0) {
476f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                    ctx->setDefaultOutputDevice(device);
477f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                    ALOGV("%s: default is %08x", __FUNCTION__, ctx->getDefaultOutputDevice()->type());
478f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                }
479f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                xmlFree(defaultOutputDevice);
480f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            }
481f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        }
482f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        children = children->next;
483f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
484f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    return NO_ERROR;
485f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie}
486f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
487f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char *const GlobalConfigTraits::tag = "globalConfiguration";
488f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
489f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char GlobalConfigTraits::Attributes::speakerDrcEnabled[] = "speaker_drc_enabled";
490f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
491f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
492f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffiestatus_t GlobalConfigTraits::deserialize(const xmlNode *cur, AudioPolicyConfig &config)
493f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie{
494f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    const xmlNode *root = cur->xmlChildrenNode;
495f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    while (root != NULL) {
496f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        if (!xmlStrcmp(root->name, (const xmlChar *)tag)) {
497f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            string speakerDrcEnabled =
498f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                    getXmlAttribute(root, Attributes::speakerDrcEnabled);
499f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            bool isSpeakerDrcEnabled;
500f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            if (!speakerDrcEnabled.empty() &&
501f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                    convertTo<string, bool>(speakerDrcEnabled, isSpeakerDrcEnabled)) {
502f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                config.setSpeakerDrcEnabled(isSpeakerDrcEnabled);
503f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            }
504f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            return NO_ERROR;
505f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        }
506f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        root = root->next;
507f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
508f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    return NO_ERROR;
509f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie}
510f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
511f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
512f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char *const VolumeTraits::tag = "volume";
513f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char *const VolumeTraits::collectionTag = "volumes";
514f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char *const VolumeTraits::volumePointTag = "point";
515f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
516f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char VolumeTraits::Attributes::stream[] = "stream";
517f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffieconst char VolumeTraits::Attributes::deviceCategory[] = "deviceCategory";
518c9d7c4e35afd48ac8a315f53666943b6210dafa1François Gaffieconst char VolumeTraits::Attributes::reference[] = "ref";
519f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
520f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffiestatus_t VolumeTraits::deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
521f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                                   PtrSerializingCtx /*serializingContext*/)
522f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie{
523f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string streamTypeLiteral = getXmlAttribute(root, Attributes::stream);
524f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (streamTypeLiteral.empty()) {
525f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        ALOGE("%s: No %s found", __FUNCTION__, Attributes::stream);
526f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return BAD_VALUE;
527f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
528f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    audio_stream_type_t streamType;
529f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (!StreamTypeConverter::fromString(streamTypeLiteral, streamType)) {
530f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        ALOGE("%s: Invalid %s", __FUNCTION__, Attributes::stream);
531f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return BAD_VALUE;
532f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
533f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string deviceCategoryLiteral = getXmlAttribute(root, Attributes::deviceCategory);
534f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (deviceCategoryLiteral.empty()) {
535f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        ALOGE("%s: No %s found", __FUNCTION__, Attributes::deviceCategory);
536f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return BAD_VALUE;
537f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
538f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    device_category deviceCategory;
539f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (!DeviceCategoryConverter::fromString(deviceCategoryLiteral, deviceCategory)) {
540f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        ALOGE("%s: Invalid %s=%s", __FUNCTION__, Attributes::deviceCategory,
541f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie              deviceCategoryLiteral.c_str());
542f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return BAD_VALUE;
543f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
544c9d7c4e35afd48ac8a315f53666943b6210dafa1François Gaffie
545c9d7c4e35afd48ac8a315f53666943b6210dafa1François Gaffie    string referenceName = getXmlAttribute(root, Attributes::reference);
546c9d7c4e35afd48ac8a315f53666943b6210dafa1François Gaffie    const _xmlNode *ref = NULL;
547c9d7c4e35afd48ac8a315f53666943b6210dafa1François Gaffie    if (!referenceName.empty()) {
54819219b44e05555b29e00ce56ce273d168fa83888François Gaffie        getReference<VolumeTraits>(root->parent, ref, referenceName);
549c9d7c4e35afd48ac8a315f53666943b6210dafa1François Gaffie        if (ref == NULL) {
550c9d7c4e35afd48ac8a315f53666943b6210dafa1François Gaffie            ALOGE("%s: No reference Ptr found for %s", __FUNCTION__, referenceName.c_str());
551c9d7c4e35afd48ac8a315f53666943b6210dafa1François Gaffie            return BAD_VALUE;
552c9d7c4e35afd48ac8a315f53666943b6210dafa1François Gaffie        }
553c9d7c4e35afd48ac8a315f53666943b6210dafa1François Gaffie    }
554c9d7c4e35afd48ac8a315f53666943b6210dafa1François Gaffie
555d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie    element = new Element(deviceCategory, streamType);
556d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie
557c9d7c4e35afd48ac8a315f53666943b6210dafa1François Gaffie    const xmlNode *child = referenceName.empty() ? root->xmlChildrenNode : ref->xmlChildrenNode;
558f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    while (child != NULL) {
559f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        if (!xmlStrcmp(child->name, (const xmlChar *)volumePointTag)) {
560f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            xmlChar *pointDefinition = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);;
561f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            if (pointDefinition == NULL) {
562f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                return BAD_VALUE;
563f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            }
564f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            ALOGV("%s: %s=%s", __FUNCTION__, tag, (const char*)pointDefinition);
565f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            Vector<int32_t> point;
566f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            collectionFromString<DefaultTraits<int32_t> >((const char*)pointDefinition, point, ",");
567f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            if (point.size() != 2) {
568f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                ALOGE("%s: Invalid %s: %s", __FUNCTION__, volumePointTag,
569f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                      (const char*)pointDefinition);
570f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                return BAD_VALUE;
571f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            }
572d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie            element->add(CurvePoint(point[0], point[1]));
573f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            xmlFree(pointDefinition);
574f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        }
575f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        child = child->next;
576f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
577f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    return NO_ERROR;
578f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie}
579f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
580f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois GaffiePolicySerializer::PolicySerializer() : mRootElementName(rootName)
581f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie{
582f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    std::ostringstream oss;
583f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    oss << gMajor << "." << gMinor;
584f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    mVersion = oss.str();
585f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    ALOGV("%s: Version=%s Root=%s", __FUNCTION__, mVersion.c_str(), mRootElementName.c_str());
586f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie}
587f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
588f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffiestatus_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig &config)
589f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie{
590f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    xmlDocPtr doc;
591f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    doc = xmlParseFile(configFile);
592f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (doc == NULL) {
593f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        ALOGE("%s: Could not parse %s document.", __FUNCTION__, configFile);
594f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return BAD_VALUE;
595f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
596f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    xmlNodePtr cur = xmlDocGetRootElement(doc);
597f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (cur == NULL) {
598f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        ALOGE("%s: Could not parse %s document: empty.", __FUNCTION__, configFile);
599f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        xmlFreeDoc(doc);
600f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return BAD_VALUE;
601f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
602f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (xmlXIncludeProcess(doc) < 0) {
603f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie         ALOGE("%s: libxml failed to resolve XIncludes on %s document.", __FUNCTION__, configFile);
604f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
605f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
606f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (xmlStrcmp(cur->name, (const xmlChar *) mRootElementName.c_str()))  {
607f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        ALOGE("%s: No %s root element found in xml data %s.", __FUNCTION__, mRootElementName.c_str(),
608f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie              (const char *)cur->name);
609f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        xmlFreeDoc(doc);
610f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return BAD_VALUE;
611f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
612f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
613f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    string version = getXmlAttribute(cur, versionAttribute);
614f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (version.empty()) {
615f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        ALOGE("%s: No version found in root node %s", __FUNCTION__, mRootElementName.c_str());
616f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return BAD_VALUE;
617f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
618f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (version != mVersion) {
619f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        ALOGE("%s: Version does not match; expect %s got %s", __FUNCTION__, mVersion.c_str(),
620f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie              version.c_str());
621f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie        return BAD_VALUE;
622f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    }
623f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    // Lets deserialize children
624f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    // Modules
625f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    ModuleTraits::Collection modules;
626f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    deserializeCollection<ModuleTraits>(doc, cur, modules, &config);
627f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    config.setHwModules(modules);
628f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
629f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    // deserialize volume section
630f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    VolumeTraits::Collection volumes;
631d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie    deserializeCollection<VolumeTraits>(doc, cur, volumes, &config);
632d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie    config.setVolumes(volumes);
633f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
634f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    // Global Configuration
635f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    GlobalConfigTraits::deserialize(cur, config);
636f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
637f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    xmlFreeDoc(doc);
638f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    return android::OK;
639f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie}
640f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie
641f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie}; // namespace android
642