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