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 <memory> 21 #include <string> 22 #include <utility> 23 24 #include <hidl/Status.h> 25 #include <libxml/parser.h> 26 #include <libxml/xinclude.h> 27 #include <media/convert.h> 28 #include <utils/Log.h> 29 #include <utils/StrongPointer.h> 30 #include <utils/Errors.h> 31 #include <utils/RefBase.h> 32 #include "Serializer.h" 33 #include "TypeConverter.h" 34 35 namespace android { 36 37 namespace { 38 39 // TODO(mnaganov): Consider finding an alternative for using HIDL code. 40 using hardware::Return; 41 using hardware::Status; 42 using utilities::convertTo; 43 44 template<typename E, typename C> 45 struct AndroidCollectionTraits { 46 typedef sp<E> Element; 47 typedef C Collection; 48 typedef void* PtrSerializingCtx; 49 50 static status_t addElementToCollection(const Element &element, Collection *collection) { 51 return collection->add(element) >= 0 ? NO_ERROR : BAD_VALUE; 52 } 53 }; 54 55 template<typename C> 56 struct StdCollectionTraits { 57 typedef C Collection; 58 typedef typename C::value_type Element; 59 typedef void* PtrSerializingCtx; 60 61 static status_t addElementToCollection(const Element &element, Collection *collection) { 62 auto pair = collection->insert(element); 63 return pair.second ? NO_ERROR : BAD_VALUE; 64 } 65 }; 66 67 struct AudioGainTraits : public AndroidCollectionTraits<AudioGain, AudioGains> 68 { 69 static constexpr const char *tag = "gain"; 70 static constexpr const char *collectionTag = "gains"; 71 72 struct Attributes 73 { 74 /** gain modes supported, e.g. AUDIO_GAIN_MODE_CHANNELS. */ 75 static constexpr const char *mode = "mode"; 76 /** controlled channels, needed if mode AUDIO_GAIN_MODE_CHANNELS. */ 77 static constexpr const char *channelMask = "channel_mask"; 78 static constexpr const char *minValueMB = "minValueMB"; /**< min value in millibel. */ 79 static constexpr const char *maxValueMB = "maxValueMB"; /**< max value in millibel. */ 80 /** default value in millibel. */ 81 static constexpr const char *defaultValueMB = "defaultValueMB"; 82 static constexpr const char *stepValueMB = "stepValueMB"; /**< step value in millibel. */ 83 /** needed if mode AUDIO_GAIN_MODE_RAMP. */ 84 static constexpr const char *minRampMs = "minRampMs"; 85 /** needed if mode AUDIO_GAIN_MODE_RAMP. */ 86 static constexpr const char *maxRampMs = "maxRampMs"; 87 /** needed to allow use setPortGain instead of setStreamVolume. */ 88 static constexpr const char *useForVolume = "useForVolume"; 89 90 }; 91 92 static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext); 93 // No children 94 }; 95 96 // A profile section contains a name, one audio format and the list of supported sampling rates 97 // and channel masks for this format 98 struct AudioProfileTraits : public AndroidCollectionTraits<AudioProfile, AudioProfileVector> 99 { 100 static constexpr const char *tag = "profile"; 101 static constexpr const char *collectionTag = "profiles"; 102 103 struct Attributes 104 { 105 static constexpr const char *samplingRates = "samplingRates"; 106 static constexpr const char *format = "format"; 107 static constexpr const char *channelMasks = "channelMasks"; 108 }; 109 110 static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext); 111 }; 112 113 struct MixPortTraits : public AndroidCollectionTraits<IOProfile, IOProfileCollection> 114 { 115 static constexpr const char *tag = "mixPort"; 116 static constexpr const char *collectionTag = "mixPorts"; 117 118 struct Attributes 119 { 120 static constexpr const char *name = "name"; 121 static constexpr const char *role = "role"; 122 static constexpr const char *roleSource = "source"; /**< <attribute role source value>. */ 123 static constexpr const char *flags = "flags"; 124 static constexpr const char *maxOpenCount = "maxOpenCount"; 125 static constexpr const char *maxActiveCount = "maxActiveCount"; 126 }; 127 128 static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext); 129 // Children: GainTraits 130 }; 131 132 struct DevicePortTraits : public AndroidCollectionTraits<DeviceDescriptor, DeviceVector> 133 { 134 static constexpr const char *tag = "devicePort"; 135 static constexpr const char *collectionTag = "devicePorts"; 136 137 struct Attributes 138 { 139 /** <device tag name>: any string without space. */ 140 static constexpr const char *tagName = "tagName"; 141 static constexpr const char *type = "type"; /**< <device type>. */ 142 static constexpr const char *role = "role"; /**< <device role: sink or source>. */ 143 static constexpr const char *roleSource = "source"; /**< <attribute role source value>. */ 144 /** optional: device address, char string less than 64. */ 145 static constexpr const char *address = "address"; 146 /** optional: the list of encoded audio formats that are known to be supported. */ 147 static constexpr const char *encodedFormats = "encodedFormats"; 148 }; 149 150 static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext); 151 // Children: GainTraits (optional) 152 }; 153 154 struct RouteTraits : public AndroidCollectionTraits<AudioRoute, AudioRouteVector> 155 { 156 static constexpr const char *tag = "route"; 157 static constexpr const char *collectionTag = "routes"; 158 159 struct Attributes 160 { 161 static constexpr const char *type = "type"; /**< <route type>: mix or mux. */ 162 static constexpr const char *typeMix = "mix"; /**< type attribute mix value. */ 163 static constexpr const char *sink = "sink"; /**< <sink: involved in this route>. */ 164 /** sources: all source that can be involved in this route. */ 165 static constexpr const char *sources = "sources"; 166 }; 167 168 typedef HwModule *PtrSerializingCtx; 169 170 static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext); 171 }; 172 173 struct ModuleTraits : public AndroidCollectionTraits<HwModule, HwModuleCollection> 174 { 175 static constexpr const char *tag = "module"; 176 static constexpr const char *collectionTag = "modules"; 177 178 static constexpr const char *childAttachedDevicesTag = "attachedDevices"; 179 static constexpr const char *childAttachedDeviceTag = "item"; 180 static constexpr const char *childDefaultOutputDeviceTag = "defaultOutputDevice"; 181 182 struct Attributes 183 { 184 static constexpr const char *name = "name"; 185 static constexpr const char *version = "halVersion"; 186 }; 187 188 typedef AudioPolicyConfig *PtrSerializingCtx; 189 190 static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext); 191 // Children: mixPortTraits, devicePortTraits, and routeTraits 192 // Need to call deserialize on each child 193 }; 194 195 struct GlobalConfigTraits 196 { 197 static constexpr const char *tag = "globalConfiguration"; 198 199 struct Attributes 200 { 201 static constexpr const char *speakerDrcEnabled = "speaker_drc_enabled"; 202 }; 203 204 static status_t deserialize(const xmlNode *root, AudioPolicyConfig *config); 205 }; 206 207 struct SurroundSoundTraits 208 { 209 static constexpr const char *tag = "surroundSound"; 210 211 static status_t deserialize(const xmlNode *root, AudioPolicyConfig *config); 212 // Children: SurroundSoundFormatTraits 213 }; 214 215 struct SurroundSoundFormatTraits : public StdCollectionTraits<AudioPolicyConfig::SurroundFormats> 216 { 217 static constexpr const char *tag = "format"; 218 static constexpr const char *collectionTag = "formats"; 219 220 struct Attributes 221 { 222 static constexpr const char *name = "name"; 223 static constexpr const char *subformats = "subformats"; 224 }; 225 226 static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext); 227 }; 228 229 class PolicySerializer 230 { 231 public: 232 PolicySerializer() : mVersion{std::to_string(gMajor) + "." + std::to_string(gMinor)} 233 { 234 ALOGV("%s: Version=%s Root=%s", __func__, mVersion.c_str(), rootName); 235 } 236 status_t deserialize(const char *configFile, AudioPolicyConfig *config); 237 238 private: 239 static constexpr const char *rootName = "audioPolicyConfiguration"; 240 static constexpr const char *versionAttribute = "version"; 241 static constexpr uint32_t gMajor = 1; /**< the major number of the policy xml format version. */ 242 static constexpr uint32_t gMinor = 0; /**< the minor number of the policy xml format version. */ 243 244 typedef AudioPolicyConfig Element; 245 246 const std::string mVersion; 247 248 // Children: ModulesTraits, VolumeTraits, SurroundSoundTraits (optional) 249 }; 250 251 template <class T> 252 constexpr void (*xmlDeleter)(T* t); 253 template <> 254 constexpr auto xmlDeleter<xmlDoc> = xmlFreeDoc; 255 // http://b/111067277 - Add back constexpr when we switch to C++17. 256 template <> 257 auto xmlDeleter<xmlChar> = [](xmlChar *s) { xmlFree(s); }; 258 259 /** @return a unique_ptr with the correct deleter for the libxml2 object. */ 260 template <class T> 261 constexpr auto make_xmlUnique(T *t) { 262 // Wrap deleter in lambda to enable empty base optimization 263 auto deleter = [](T *t) { xmlDeleter<T>(t); }; 264 return std::unique_ptr<T, decltype(deleter)>{t, deleter}; 265 } 266 267 std::string getXmlAttribute(const xmlNode *cur, const char *attribute) 268 { 269 auto xmlValue = make_xmlUnique(xmlGetProp(cur, reinterpret_cast<const xmlChar*>(attribute))); 270 if (xmlValue == nullptr) { 271 return ""; 272 } 273 std::string value(reinterpret_cast<const char*>(xmlValue.get())); 274 return value; 275 } 276 277 template <class Trait> 278 const xmlNode* getReference(const xmlNode *cur, const std::string &refName) 279 { 280 for (; cur != NULL; cur = cur->next) { 281 if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::collectionTag))) { 282 for (const xmlNode *child = cur->children; child != NULL; child = child->next) { 283 if ((!xmlStrcmp(child->name, 284 reinterpret_cast<const xmlChar*>(Trait::referenceTag)))) { 285 std::string name = getXmlAttribute(child, Trait::Attributes::referenceName); 286 if (refName == name) { 287 return child; 288 } 289 } 290 } 291 } 292 } 293 return NULL; 294 } 295 296 template <class Trait> 297 status_t deserializeCollection(const xmlNode *cur, 298 typename Trait::Collection *collection, 299 typename Trait::PtrSerializingCtx serializingContext) 300 { 301 for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 302 const xmlNode *child = NULL; 303 if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::collectionTag))) { 304 child = cur->xmlChildrenNode; 305 } else if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::tag))) { 306 child = cur; 307 } 308 for (; child != NULL; child = child->next) { 309 if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>(Trait::tag))) { 310 auto element = Trait::deserialize(child, serializingContext); 311 if (element.isOk()) { 312 status_t status = Trait::addElementToCollection(element, collection); 313 if (status != NO_ERROR) { 314 ALOGE("%s: could not add element to %s collection", __func__, 315 Trait::collectionTag); 316 return status; 317 } 318 } else { 319 return BAD_VALUE; 320 } 321 } 322 } 323 if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::tag))) { 324 return NO_ERROR; 325 } 326 } 327 return NO_ERROR; 328 } 329 330 Return<AudioGainTraits::Element> AudioGainTraits::deserialize(const xmlNode *cur, 331 PtrSerializingCtx /*serializingContext*/) 332 { 333 static uint32_t index = 0; 334 Element gain = new AudioGain(index++, true); 335 336 std::string mode = getXmlAttribute(cur, Attributes::mode); 337 if (!mode.empty()) { 338 gain->setMode(GainModeConverter::maskFromString(mode)); 339 } 340 341 std::string channelsLiteral = getXmlAttribute(cur, Attributes::channelMask); 342 if (!channelsLiteral.empty()) { 343 gain->setChannelMask(channelMaskFromString(channelsLiteral)); 344 } 345 346 std::string minValueMBLiteral = getXmlAttribute(cur, Attributes::minValueMB); 347 int32_t minValueMB; 348 if (!minValueMBLiteral.empty() && convertTo(minValueMBLiteral, minValueMB)) { 349 gain->setMinValueInMb(minValueMB); 350 } 351 352 std::string maxValueMBLiteral = getXmlAttribute(cur, Attributes::maxValueMB); 353 int32_t maxValueMB; 354 if (!maxValueMBLiteral.empty() && convertTo(maxValueMBLiteral, maxValueMB)) { 355 gain->setMaxValueInMb(maxValueMB); 356 } 357 358 std::string defaultValueMBLiteral = getXmlAttribute(cur, Attributes::defaultValueMB); 359 int32_t defaultValueMB; 360 if (!defaultValueMBLiteral.empty() && convertTo(defaultValueMBLiteral, defaultValueMB)) { 361 gain->setDefaultValueInMb(defaultValueMB); 362 } 363 364 std::string stepValueMBLiteral = getXmlAttribute(cur, Attributes::stepValueMB); 365 uint32_t stepValueMB; 366 if (!stepValueMBLiteral.empty() && convertTo(stepValueMBLiteral, stepValueMB)) { 367 gain->setStepValueInMb(stepValueMB); 368 } 369 370 std::string minRampMsLiteral = getXmlAttribute(cur, Attributes::minRampMs); 371 uint32_t minRampMs; 372 if (!minRampMsLiteral.empty() && convertTo(minRampMsLiteral, minRampMs)) { 373 gain->setMinRampInMs(minRampMs); 374 } 375 376 std::string maxRampMsLiteral = getXmlAttribute(cur, Attributes::maxRampMs); 377 uint32_t maxRampMs; 378 if (!maxRampMsLiteral.empty() && convertTo(maxRampMsLiteral, maxRampMs)) { 379 gain->setMaxRampInMs(maxRampMs); 380 } 381 std::string useForVolumeLiteral = getXmlAttribute(cur, Attributes::useForVolume); 382 bool useForVolume = false; 383 if (!useForVolumeLiteral.empty() && convertTo(useForVolumeLiteral, useForVolume)) { 384 gain->setUseForVolume(useForVolume); 385 } 386 ALOGV("%s: adding new gain mode %08x channel mask %08x min mB %d max mB %d UseForVolume: %d", 387 __func__, gain->getMode(), gain->getChannelMask(), gain->getMinValueInMb(), 388 gain->getMaxValueInMb(), useForVolume); 389 390 if (gain->getMode() != 0) { 391 return gain; 392 } else { 393 return Status::fromStatusT(BAD_VALUE); 394 } 395 } 396 397 Return<AudioProfileTraits::Element> AudioProfileTraits::deserialize(const xmlNode *cur, 398 PtrSerializingCtx /*serializingContext*/) 399 { 400 std::string samplingRates = getXmlAttribute(cur, Attributes::samplingRates); 401 std::string format = getXmlAttribute(cur, Attributes::format); 402 std::string channels = getXmlAttribute(cur, Attributes::channelMasks); 403 404 Element profile = new AudioProfile(formatFromString(format, gDynamicFormat), 405 channelMasksFromString(channels, ","), 406 samplingRatesFromString(samplingRates, ",")); 407 408 profile->setDynamicFormat(profile->getFormat() == gDynamicFormat); 409 profile->setDynamicChannels(profile->getChannels().isEmpty()); 410 profile->setDynamicRate(profile->getSampleRates().isEmpty()); 411 412 return profile; 413 } 414 415 Return<MixPortTraits::Element> MixPortTraits::deserialize(const xmlNode *child, 416 PtrSerializingCtx /*serializingContext*/) 417 { 418 std::string name = getXmlAttribute(child, Attributes::name); 419 if (name.empty()) { 420 ALOGE("%s: No %s found", __func__, Attributes::name); 421 return Status::fromStatusT(BAD_VALUE); 422 } 423 ALOGV("%s: %s %s=%s", __func__, tag, Attributes::name, name.c_str()); 424 std::string role = getXmlAttribute(child, Attributes::role); 425 if (role.empty()) { 426 ALOGE("%s: No %s found", __func__, Attributes::role); 427 return Status::fromStatusT(BAD_VALUE); 428 } 429 ALOGV("%s: Role=%s", __func__, role.c_str()); 430 audio_port_role_t portRole = (role == Attributes::roleSource) ? 431 AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK; 432 433 Element mixPort = new IOProfile(String8(name.c_str()), portRole); 434 435 AudioProfileTraits::Collection profiles; 436 status_t status = deserializeCollection<AudioProfileTraits>(child, &profiles, NULL); 437 if (status != NO_ERROR) { 438 return Status::fromStatusT(status); 439 } 440 if (profiles.isEmpty()) { 441 profiles.add(AudioProfile::createFullDynamic()); 442 } 443 mixPort->setAudioProfiles(profiles); 444 445 std::string flags = getXmlAttribute(child, Attributes::flags); 446 if (!flags.empty()) { 447 // Source role 448 if (portRole == AUDIO_PORT_ROLE_SOURCE) { 449 mixPort->setFlags(OutputFlagConverter::maskFromString(flags)); 450 } else { 451 // Sink role 452 mixPort->setFlags(InputFlagConverter::maskFromString(flags)); 453 } 454 } 455 std::string maxOpenCount = getXmlAttribute(child, Attributes::maxOpenCount); 456 if (!maxOpenCount.empty()) { 457 convertTo(maxOpenCount, mixPort->maxOpenCount); 458 } 459 std::string maxActiveCount = getXmlAttribute(child, Attributes::maxActiveCount); 460 if (!maxActiveCount.empty()) { 461 convertTo(maxActiveCount, mixPort->maxActiveCount); 462 } 463 // Deserialize children 464 AudioGainTraits::Collection gains; 465 status = deserializeCollection<AudioGainTraits>(child, &gains, NULL); 466 if (status != NO_ERROR) { 467 return Status::fromStatusT(status); 468 } 469 mixPort->setGains(gains); 470 471 return mixPort; 472 } 473 474 Return<DevicePortTraits::Element> DevicePortTraits::deserialize(const xmlNode *cur, 475 PtrSerializingCtx /*serializingContext*/) 476 { 477 std::string name = getXmlAttribute(cur, Attributes::tagName); 478 if (name.empty()) { 479 ALOGE("%s: No %s found", __func__, Attributes::tagName); 480 return Status::fromStatusT(BAD_VALUE); 481 } 482 ALOGV("%s: %s %s=%s", __func__, tag, Attributes::tagName, name.c_str()); 483 std::string typeName = getXmlAttribute(cur, Attributes::type); 484 if (typeName.empty()) { 485 ALOGE("%s: no type for %s", __func__, name.c_str()); 486 return Status::fromStatusT(BAD_VALUE); 487 } 488 ALOGV("%s: %s %s=%s", __func__, tag, Attributes::type, typeName.c_str()); 489 std::string role = getXmlAttribute(cur, Attributes::role); 490 if (role.empty()) { 491 ALOGE("%s: No %s found", __func__, Attributes::role); 492 return Status::fromStatusT(BAD_VALUE); 493 } 494 ALOGV("%s: %s %s=%s", __func__, tag, Attributes::role, role.c_str()); 495 audio_port_role_t portRole = (role == Attributes::roleSource) ? 496 AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK; 497 498 audio_devices_t type = AUDIO_DEVICE_NONE; 499 if (!deviceFromString(typeName, type) || 500 (!audio_is_input_device(type) && portRole == AUDIO_PORT_ROLE_SOURCE) || 501 (!audio_is_output_devices(type) && portRole == AUDIO_PORT_ROLE_SINK)) { 502 ALOGW("%s: bad type %08x", __func__, type); 503 return Status::fromStatusT(BAD_VALUE); 504 } 505 std::string encodedFormatsLiteral = getXmlAttribute(cur, Attributes::encodedFormats); 506 ALOGV("%s: %s %s=%s", __func__, tag, Attributes::encodedFormats, encodedFormatsLiteral.c_str()); 507 FormatVector encodedFormats; 508 if (!encodedFormatsLiteral.empty()) { 509 encodedFormats = formatsFromString(encodedFormatsLiteral, " "); 510 } 511 Element deviceDesc = new DeviceDescriptor(type, encodedFormats, String8(name.c_str())); 512 513 std::string address = getXmlAttribute(cur, Attributes::address); 514 if (!address.empty()) { 515 ALOGV("%s: address=%s for %s", __func__, address.c_str(), name.c_str()); 516 deviceDesc->setAddress(String8(address.c_str())); 517 } 518 519 AudioProfileTraits::Collection profiles; 520 status_t status = deserializeCollection<AudioProfileTraits>(cur, &profiles, NULL); 521 if (status != NO_ERROR) { 522 return Status::fromStatusT(status); 523 } 524 if (profiles.isEmpty()) { 525 profiles.add(AudioProfile::createFullDynamic()); 526 } 527 deviceDesc->setAudioProfiles(profiles); 528 529 // Deserialize AudioGain children 530 status = deserializeCollection<AudioGainTraits>(cur, &deviceDesc->mGains, NULL); 531 if (status != NO_ERROR) { 532 return Status::fromStatusT(status); 533 } 534 ALOGV("%s: adding device tag %s type %08x address %s", __func__, 535 deviceDesc->getName().string(), type, deviceDesc->address().string()); 536 return deviceDesc; 537 } 538 539 Return<RouteTraits::Element> RouteTraits::deserialize(const xmlNode *cur, PtrSerializingCtx ctx) 540 { 541 std::string type = getXmlAttribute(cur, Attributes::type); 542 if (type.empty()) { 543 ALOGE("%s: No %s found", __func__, Attributes::type); 544 return Status::fromStatusT(BAD_VALUE); 545 } 546 audio_route_type_t routeType = (type == Attributes::typeMix) ? 547 AUDIO_ROUTE_MIX : AUDIO_ROUTE_MUX; 548 549 ALOGV("%s: %s %s=%s", __func__, tag, Attributes::type, type.c_str()); 550 Element route = new AudioRoute(routeType); 551 552 std::string sinkAttr = getXmlAttribute(cur, Attributes::sink); 553 if (sinkAttr.empty()) { 554 ALOGE("%s: No %s found", __func__, Attributes::sink); 555 return Status::fromStatusT(BAD_VALUE); 556 } 557 // Convert Sink name to port pointer 558 sp<AudioPort> sink = ctx->findPortByTagName(String8(sinkAttr.c_str())); 559 if (sink == NULL) { 560 ALOGE("%s: no sink found with name=%s", __func__, sinkAttr.c_str()); 561 return Status::fromStatusT(BAD_VALUE); 562 } 563 route->setSink(sink); 564 565 std::string sourcesAttr = getXmlAttribute(cur, Attributes::sources); 566 if (sourcesAttr.empty()) { 567 ALOGE("%s: No %s found", __func__, Attributes::sources); 568 return Status::fromStatusT(BAD_VALUE); 569 } 570 // Tokenize and Convert Sources name to port pointer 571 AudioPortVector sources; 572 std::unique_ptr<char[]> sourcesLiteral{strndup( 573 sourcesAttr.c_str(), strlen(sourcesAttr.c_str()))}; 574 char *devTag = strtok(sourcesLiteral.get(), ","); 575 while (devTag != NULL) { 576 if (strlen(devTag) != 0) { 577 sp<AudioPort> source = ctx->findPortByTagName(String8(devTag)); 578 if (source == NULL) { 579 ALOGE("%s: no source found with name=%s", __func__, devTag); 580 return Status::fromStatusT(BAD_VALUE); 581 } 582 sources.add(source); 583 } 584 devTag = strtok(NULL, ","); 585 } 586 587 sink->addRoute(route); 588 for (size_t i = 0; i < sources.size(); i++) { 589 sp<AudioPort> source = sources.itemAt(i); 590 source->addRoute(route); 591 } 592 route->setSources(sources); 593 return route; 594 } 595 596 Return<ModuleTraits::Element> ModuleTraits::deserialize(const xmlNode *cur, PtrSerializingCtx ctx) 597 { 598 std::string name = getXmlAttribute(cur, Attributes::name); 599 if (name.empty()) { 600 ALOGE("%s: No %s found", __func__, Attributes::name); 601 return Status::fromStatusT(BAD_VALUE); 602 } 603 uint32_t versionMajor = 0, versionMinor = 0; 604 std::string versionLiteral = getXmlAttribute(cur, Attributes::version); 605 if (!versionLiteral.empty()) { 606 sscanf(versionLiteral.c_str(), "%u.%u", &versionMajor, &versionMinor); 607 ALOGV("%s: mHalVersion = major %u minor %u", __func__, 608 versionMajor, versionMajor); 609 } 610 611 ALOGV("%s: %s %s=%s", __func__, tag, Attributes::name, name.c_str()); 612 613 Element module = new HwModule(name.c_str(), versionMajor, versionMinor); 614 615 // Deserialize childrens: Audio Mix Port, Audio Device Ports (Source/Sink), Audio Routes 616 MixPortTraits::Collection mixPorts; 617 status_t status = deserializeCollection<MixPortTraits>(cur, &mixPorts, NULL); 618 if (status != NO_ERROR) { 619 return Status::fromStatusT(status); 620 } 621 module->setProfiles(mixPorts); 622 623 DevicePortTraits::Collection devicePorts; 624 status = deserializeCollection<DevicePortTraits>(cur, &devicePorts, NULL); 625 if (status != NO_ERROR) { 626 return Status::fromStatusT(status); 627 } 628 module->setDeclaredDevices(devicePorts); 629 630 RouteTraits::Collection routes; 631 status = deserializeCollection<RouteTraits>(cur, &routes, module.get()); 632 if (status != NO_ERROR) { 633 return Status::fromStatusT(status); 634 } 635 module->setRoutes(routes); 636 637 for (const xmlNode *children = cur->xmlChildrenNode; children != NULL; 638 children = children->next) { 639 if (!xmlStrcmp(children->name, reinterpret_cast<const xmlChar*>(childAttachedDevicesTag))) { 640 ALOGV("%s: %s %s found", __func__, tag, childAttachedDevicesTag); 641 for (const xmlNode *child = children->xmlChildrenNode; child != NULL; 642 child = child->next) { 643 if (!xmlStrcmp(child->name, 644 reinterpret_cast<const xmlChar*>(childAttachedDeviceTag))) { 645 auto attachedDevice = make_xmlUnique(xmlNodeListGetString( 646 child->doc, child->xmlChildrenNode, 1)); 647 if (attachedDevice != nullptr) { 648 ALOGV("%s: %s %s=%s", __func__, tag, childAttachedDeviceTag, 649 reinterpret_cast<const char*>(attachedDevice.get())); 650 sp<DeviceDescriptor> device = module->getDeclaredDevices(). 651 getDeviceFromTagName(String8(reinterpret_cast<const char*>( 652 attachedDevice.get()))); 653 ctx->addAvailableDevice(device); 654 } 655 } 656 } 657 } 658 if (!xmlStrcmp(children->name, 659 reinterpret_cast<const xmlChar*>(childDefaultOutputDeviceTag))) { 660 auto defaultOutputDevice = make_xmlUnique(xmlNodeListGetString( 661 children->doc, children->xmlChildrenNode, 1)); 662 if (defaultOutputDevice != nullptr) { 663 ALOGV("%s: %s %s=%s", __func__, tag, childDefaultOutputDeviceTag, 664 reinterpret_cast<const char*>(defaultOutputDevice.get())); 665 sp<DeviceDescriptor> device = module->getDeclaredDevices().getDeviceFromTagName( 666 String8(reinterpret_cast<const char*>(defaultOutputDevice.get()))); 667 if (device != 0 && ctx->getDefaultOutputDevice() == 0) { 668 ctx->setDefaultOutputDevice(device); 669 ALOGV("%s: default is %08x", 670 __func__, ctx->getDefaultOutputDevice()->type()); 671 } 672 } 673 } 674 } 675 return module; 676 } 677 678 status_t GlobalConfigTraits::deserialize(const xmlNode *root, AudioPolicyConfig *config) 679 { 680 for (const xmlNode *cur = root->xmlChildrenNode; cur != NULL; cur = cur->next) { 681 if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(tag))) { 682 std::string speakerDrcEnabled = 683 getXmlAttribute(cur, Attributes::speakerDrcEnabled); 684 bool isSpeakerDrcEnabled; 685 if (!speakerDrcEnabled.empty() && 686 convertTo<std::string, bool>(speakerDrcEnabled, isSpeakerDrcEnabled)) { 687 config->setSpeakerDrcEnabled(isSpeakerDrcEnabled); 688 } 689 return NO_ERROR; 690 } 691 } 692 return NO_ERROR; 693 } 694 695 status_t SurroundSoundTraits::deserialize(const xmlNode *root, AudioPolicyConfig *config) 696 { 697 config->setDefaultSurroundFormats(); 698 699 for (const xmlNode *cur = root->xmlChildrenNode; cur != NULL; cur = cur->next) { 700 if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(tag))) { 701 AudioPolicyConfig::SurroundFormats formats; 702 status_t status = deserializeCollection<SurroundSoundFormatTraits>( 703 cur, &formats, nullptr); 704 if (status == NO_ERROR) { 705 config->setSurroundFormats(formats); 706 } 707 return NO_ERROR; 708 } 709 } 710 return NO_ERROR; 711 } 712 713 Return<SurroundSoundFormatTraits::Element> SurroundSoundFormatTraits::deserialize( 714 const xmlNode *cur, PtrSerializingCtx /*serializingContext*/) 715 { 716 std::string formatLiteral = getXmlAttribute(cur, Attributes::name); 717 if (formatLiteral.empty()) { 718 ALOGE("%s: No %s found for a surround format", __func__, Attributes::name); 719 return Status::fromStatusT(BAD_VALUE); 720 } 721 audio_format_t format = formatFromString(formatLiteral); 722 if (format == AUDIO_FORMAT_DEFAULT) { 723 ALOGE("%s: Unrecognized format %s", __func__, formatLiteral.c_str()); 724 return Status::fromStatusT(BAD_VALUE); 725 } 726 Element pair = std::make_pair(format, Collection::mapped_type{}); 727 728 std::string subformatsLiteral = getXmlAttribute(cur, Attributes::subformats); 729 if (subformatsLiteral.empty()) return pair; 730 FormatVector subformats = formatsFromString(subformatsLiteral, " "); 731 for (const auto& subformat : subformats) { 732 auto result = pair.second.insert(subformat); 733 if (!result.second) { 734 ALOGE("%s: could not add subformat %x to collection", __func__, subformat); 735 return Status::fromStatusT(BAD_VALUE); 736 } 737 } 738 return pair; 739 } 740 741 status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig *config) 742 { 743 auto doc = make_xmlUnique(xmlParseFile(configFile)); 744 if (doc == nullptr) { 745 ALOGE("%s: Could not parse %s document.", __func__, configFile); 746 return BAD_VALUE; 747 } 748 xmlNodePtr root = xmlDocGetRootElement(doc.get()); 749 if (root == NULL) { 750 ALOGE("%s: Could not parse %s document: empty.", __func__, configFile); 751 return BAD_VALUE; 752 } 753 if (xmlXIncludeProcess(doc.get()) < 0) { 754 ALOGE("%s: libxml failed to resolve XIncludes on %s document.", __func__, configFile); 755 } 756 757 if (xmlStrcmp(root->name, reinterpret_cast<const xmlChar*>(rootName))) { 758 ALOGE("%s: No %s root element found in xml data %s.", __func__, rootName, 759 reinterpret_cast<const char*>(root->name)); 760 return BAD_VALUE; 761 } 762 763 std::string version = getXmlAttribute(root, versionAttribute); 764 if (version.empty()) { 765 ALOGE("%s: No version found in root node %s", __func__, rootName); 766 return BAD_VALUE; 767 } 768 if (version != mVersion) { 769 ALOGE("%s: Version does not match; expect %s got %s", __func__, mVersion.c_str(), 770 version.c_str()); 771 return BAD_VALUE; 772 } 773 // Lets deserialize children 774 // Modules 775 ModuleTraits::Collection modules; 776 status_t status = deserializeCollection<ModuleTraits>(root, &modules, config); 777 if (status != NO_ERROR) { 778 return status; 779 } 780 config->setHwModules(modules); 781 782 // Global Configuration 783 GlobalConfigTraits::deserialize(root, config); 784 785 // Surround configuration 786 SurroundSoundTraits::deserialize(root, config); 787 788 return android::OK; 789 } 790 791 } // namespace 792 793 status_t deserializeAudioPolicyFile(const char *fileName, AudioPolicyConfig *config) 794 { 795 PolicySerializer serializer; 796 return serializer.deserialize(fileName, config); 797 } 798 799 } // namespace android 800