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