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