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