Audio policy: implement configuration file in XML
This patch introduces configuration file of the policy in XML.
Legacy configuration file is used by default and
compilation flag USE_XML_AUDIO_POLICY_CONF must be defined to
use XML file format.
Change-Id: I352b788b5829d42ed82c851a4faef0e526be582e
Signed-off-by: François Gaffie <francois.gaffie@intel.com>
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index 671d7fb..0f3f138 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -67,12 +67,16 @@
ifeq ($(USE_CONFIGURABLE_AUDIO_POLICY), 1)
+ifneq ($(USE_XML_AUDIO_POLICY_CONF), 1)
+$(error Configurable policy does not support legacy conf file)
+endif #ifneq ($(USE_XML_AUDIO_POLICY_CONF), 1)
+
LOCAL_REQUIRED_MODULES := \
parameter-framework.policy \
audio_policy_criteria.conf \
LOCAL_C_INCLUDES += \
- $(TOPDIR)frameworks/av/services/audiopolicy/engineconfigurable/include \
+ $(TOPDIR)frameworks/av/services/audiopolicy/engineconfigurable/include
LOCAL_SHARED_LIBRARIES += libaudiopolicyengineconfigurable
@@ -85,12 +89,20 @@
LOCAL_C_INCLUDES += \
$(TOPDIR)frameworks/av/services/audiopolicy/common/include \
$(TOPDIR)frameworks/av/services/audiopolicy/engine/interface \
- $(TOPDIR)frameworks/av/services/audiopolicy/utilities \
+ $(TOPDIR)frameworks/av/services/audiopolicy/utilities
LOCAL_STATIC_LIBRARIES := \
libmedia_helper \
libaudiopolicycomponents
+ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
+LOCAL_STATIC_LIBRARIES += libxml2
+
+LOCAL_SHARED_LIBRARIES += libicuuc
+
+LOCAL_CFLAGS += -DUSE_XML_AUDIO_POLICY_CONF
+endif #ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
+
LOCAL_MODULE:= libaudiopolicymanagerdefault
include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audiopolicy/common/managerdefinitions/Android.mk b/services/audiopolicy/common/managerdefinitions/Android.mk
index 0c28fc9..429f20a 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.mk
+++ b/services/audiopolicy/common/managerdefinitions/Android.mk
@@ -17,7 +17,6 @@
src/AudioOutputDescriptor.cpp \
src/AudioCollections.cpp \
src/EffectDescriptor.cpp \
- src/ConfigParsingUtils.cpp \
src/SoundTriggerSession.cpp \
src/SessionRoute.cpp \
src/AudioSourceDescriptor.cpp \
@@ -29,12 +28,27 @@
libutils \
liblog \
-LOCAL_C_INCLUDES += \
+LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/include \
$(TOPDIR)frameworks/av/services/audiopolicy/common/include \
$(TOPDIR)frameworks/av/services/audiopolicy \
$(TOPDIR)frameworks/av/services/audiopolicy/utilities \
+ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
+LOCAL_SRC_FILES += src/Serializer.cpp
+
+LOCAL_STATIC_LIBRARIES := libxml2
+
+LOCAL_SHARED_LIBRARIES += libicuuc
+
+LOCAL_C_INCLUDES += \
+ $(TOPDIR)external/libxml2/include \
+ $(TOPDIR)external/icu/icu4c/source/common
+
+else
+LOCAL_SRC_FILES += src/ConfigParsingUtils.cpp
+endif #ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
+
LOCAL_EXPORT_C_INCLUDE_DIRS := \
$(LOCAL_PATH)/include
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h b/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h
index 814c5c2..8f00d22 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h
@@ -38,7 +38,7 @@
class AudioRouteVector : public Vector<sp<AudioRoute> >
{
public:
- status_t dump(int fd) const;
+ status_t dump(int fd, int spaces) const;
};
}; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index 20c0e36..6959420 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -17,6 +17,7 @@
#pragma once
#include <AudioGain.h>
+#include <VolumeCurve.h>
#include <AudioPort.h>
#include <AudioPatch.h>
#include <DeviceDescriptor.h>
@@ -52,6 +53,15 @@
mHwModules = hwModules;
}
+ void addAvailableDevice(const sp<DeviceDescriptor> &availableDevice)
+ {
+ if (audio_is_output_device(availableDevice->type())) {
+ mAvailableOutputDevices.add(availableDevice);
+ } else if (audio_is_input_device(availableDevice->type())) {
+ mAvailableInputDevices.add(availableDevice);
+ }
+ }
+
void addAvailableInputDevices(const DeviceVector &availableInputDevices)
{
mAvailableInputDevices.add(availableInputDevices);
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
index 12e42ea..32cb600 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
@@ -51,7 +51,16 @@
void setGains(const AudioGainCollection &gains) { mGains = gains; }
const AudioGainCollection &getGains() const { return mGains; }
- void setFlags(uint32_t flags) { mFlags = flags; }
+ void setFlags(uint32_t flags)
+ {
+ //force direct flag if offload flag is set: offloading implies a direct output stream
+ // and all common behaviors are driven by checking only the direct flag
+ // this should normally be set appropriately in the policy configuration file
+ if (mRole == AUDIO_PORT_ROLE_SOURCE && (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
+ flags |= AUDIO_OUTPUT_FLAG_DIRECT;
+ }
+ mFlags = flags;
+ }
uint32_t getFlags() const { return mFlags; }
virtual void attach(const sp<HwModule>& module);
diff --git a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
index ab23105..ee95ceb 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
@@ -40,7 +40,6 @@
static status_t loadConfig(const char *path, AudioPolicyConfig &config);
private:
- static uint32_t parseOutputFlagNames(const char *name);
static void loadAudioPortGain(cnode *root, AudioPort &audioPort, int index);
static void loadAudioPortGains(cnode *root, AudioPort &audioPort);
static void loadDeviceDescriptorGains(cnode *root, sp<DeviceDescriptor> &deviceDesc);
diff --git a/services/audiopolicy/common/managerdefinitions/include/Serializer.h b/services/audiopolicy/common/managerdefinitions/include/Serializer.h
new file mode 100644
index 0000000..b152dd5
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/Serializer.h
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "AudioPolicyConfig.h"
+#include <utils/StrongPointer.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <string>
+#include <sstream>
+#include <fstream>
+
+struct _xmlNode;
+struct _xmlDoc;
+
+namespace android {
+
+struct AudioGainTraits
+{
+ static const char *const tag;
+ static const char *const collectionTag;
+
+ struct Attributes
+ {
+ static const char mode[]; /**< gain modes supported, e.g. AUDIO_GAIN_MODE_CHANNELS. */
+ /** controlled channels, needed if mode AUDIO_GAIN_MODE_CHANNELS. */
+ static const char channelMask[];
+ static const char minValueMB[]; /**< min value in millibel. */
+ static const char maxValueMB[]; /**< max value in millibel. */
+ static const char defaultValueMB[]; /**< default value in millibel. */
+ static const char stepValueMB[]; /**< step value in millibel. */
+ static const char minRampMs[]; /**< needed if mode AUDIO_GAIN_MODE_RAMP. */
+ static const char maxRampMs[]; /**< .needed if mode AUDIO_GAIN_MODE_RAMP */
+ };
+
+ typedef AudioGain Element;
+ typedef sp<Element> PtrElement;
+ typedef AudioGainCollection Collection;
+ typedef void *PtrSerializingCtx;
+
+ static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
+ PtrSerializingCtx serializingContext);
+
+ // Gain has no child
+};
+
+// A profile section contains a name, one audio format and the list of supported sampling rates
+// and channel masks for this format
+struct AudioProfileTraits
+{
+ static const char *const tag;
+ static const char *const collectionTag;
+
+ struct Attributes
+ {
+ static const char name[];
+ static const char samplingRates[];
+ static const char format[];
+ static const char channelMasks[];
+ };
+
+ typedef AudioProfile Element;
+ typedef sp<AudioProfile> PtrElement;
+ typedef AudioProfileVector Collection;
+ typedef void *PtrSerializingCtx;
+
+ static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
+ PtrSerializingCtx serializingContext);
+};
+
+struct MixPortTraits
+{
+ static const char *const tag;
+ static const char *const collectionTag;
+
+ struct Attributes
+ {
+ static const char name[];
+ static const char role[];
+ static const char flags[];
+ };
+
+ typedef IOProfile Element;
+ typedef sp<Element> PtrElement;
+ typedef IOProfileCollection Collection;
+ typedef void *PtrSerializingCtx;
+
+ static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
+ PtrSerializingCtx serializingContext);
+
+ // Children are: GainTraits
+};
+
+struct DevicePortTraits
+{
+ static const char *const tag;
+ static const char *const collectionTag;
+
+ struct Attributes
+ {
+ static const char tagName[]; /**< <device tag name>: any string without space. */
+ static const char type[]; /**< <device type>. */
+ static const char role[]; /**< <device role: sink or source>. */
+ static const char roleSource[]; /**< <attribute role source value>. */
+ static const char address[]; /**< optional: device address, char string less than 64. */
+ };
+ typedef DeviceDescriptor Element;
+ typedef sp<DeviceDescriptor> PtrElement;
+ typedef DeviceVector Collection;
+ typedef void *PtrSerializingCtx;
+
+ static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
+ PtrSerializingCtx serializingContext);
+ // Children are: GainTraits (optionnal)
+};
+
+struct RouteTraits
+{
+ static const char *const tag;
+ static const char *const collectionTag;
+
+ struct Attributes
+ {
+ static const char type[]; /**< <route type>: mix or mux. */
+ static const char typeMix[]; /**< type attribute mix value. */
+ static const char sink[]; /**< <sink: involved in this route>. */
+ static const char sources[]; /**< sources: all source that can be involved in this route. */
+ };
+ typedef AudioRoute Element;
+ typedef sp<AudioRoute> PtrElement;
+ typedef AudioRouteVector Collection;
+ typedef HwModule *PtrSerializingCtx;
+
+ static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
+ PtrSerializingCtx ctx);
+};
+
+struct ModuleTraits
+{
+ static const char *const tag;
+ static const char *const collectionTag;
+
+ static const char *const childAttachedDevicesTag;
+ static const char *const childAttachedDeviceTag;
+ static const char *const childDefaultOutputDeviceTag;
+
+ struct Attributes
+ {
+ static const char name[];
+ static const char version[];
+ };
+
+ typedef HwModule Element;
+ typedef sp<Element> PtrElement;
+ typedef HwModuleCollection Collection;
+ typedef AudioPolicyConfig *PtrSerializingCtx;
+
+ static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
+ PtrSerializingCtx serializingContext);
+
+ // Children are: mixPortTraits, devicePortTraits and routeTraits
+ // Need to call deserialize on each child
+};
+
+struct GlobalConfigTraits
+{
+ static const char *const tag;
+
+ struct Attributes
+ {
+ static const char speakerDrcEnabled[];
+ };
+
+ static status_t deserialize(const _xmlNode *root, AudioPolicyConfig &config);
+};
+
+struct VolumeTraits
+{
+ static const char *const tag;
+ static const char *const collectionTag;
+ static const char *const volumePointTag;
+
+ struct Attributes
+ {
+ static const char stream[];
+ static const char deviceCategory[];
+ };
+
+ typedef VolumeCurve Element;
+ typedef sp<VolumeCurve> PtrElement;
+ typedef VolumeCurveCollection Collection;
+ typedef void *PtrSerializingCtx;
+
+ static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
+ PtrSerializingCtx serializingContext);
+
+ // No Child
+};
+
+class PolicySerializer
+{
+private:
+ static const char *const rootName;
+
+ static const char *const versionAttribute;
+ static const uint32_t gMajor; /**< the major number of the policy xml format version. */
+ static const uint32_t gMinor; /**< the minor number of the policy xml format version. */
+
+public:
+ PolicySerializer();
+ status_t deserialize(const char *str, AudioPolicyConfig &config);
+
+private:
+ typedef AudioPolicyConfig Element;
+
+ std::string mRootElementName;
+ std::string mVersion;
+
+ // Children are: ModulesTraits, VolumeTraits
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h b/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h
index 14e2ecc..b828f81 100644
--- a/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h
+++ b/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h
@@ -149,6 +149,9 @@
static audio_format_t formatFromString(const std::string &literalFormat)
{
audio_format_t format;
+ if (literalFormat.empty()) {
+ return gDynamicFormat;
+ }
FormatConverter::fromString(literalFormat, format);
return format;
}
diff --git a/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h b/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
new file mode 100644
index 0000000..cccf1c8
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <Volume.h>
+#include <hardware/audio.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/Errors.h>
+#include <utils/Vector.h>
+#include <system/audio.h>
+#include <cutils/config_utils.h>
+#include <string>
+#include <utility>
+
+namespace android {
+
+typedef std::pair<uint32_t, uint32_t> CurvePoint;
+typedef Vector<CurvePoint> CurvePoints;
+
+class VolumeCurve : public RefBase
+{
+public:
+ void setStreamType(audio_stream_type_t streamType) { mStreamType = streamType; }
+ audio_stream_type_t getStreamType() const { return mStreamType; }
+
+ void setDeviceCategory(device_category devCat) { mDeviceCategory = devCat; }
+ device_category getDeviceCategory() const { return mDeviceCategory; }
+
+ void setCurvePoints(const CurvePoints &points) { mCurvePoints = points; }
+
+private:
+ CurvePoints mCurvePoints;
+ device_category mDeviceCategory;
+ audio_stream_type_t mStreamType;
+};
+
+typedef Vector<sp<VolumeCurve> > VolumeCurveCollection;
+
+}; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp
index f66af6b..635fe4d 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp
@@ -37,15 +37,18 @@
return port;
}
-status_t AudioRouteVector::dump(int fd) const
+status_t AudioRouteVector::dump(int fd, int spaces) const
{
+ if (isEmpty()) {
+ return NO_ERROR;
+ }
const size_t SIZE = 256;
char buffer[SIZE];
- snprintf(buffer, SIZE, "\nAudio Route dump (%zu):\n", size());
+ snprintf(buffer, SIZE, "\n%*sAudio Routes (%zu):\n", spaces, "", size());
write(fd, buffer, strlen(buffer));
for (size_t i = 0; i < size(); i++) {
- snprintf(buffer, SIZE, "- Route %zu:\n", i + 1);
+ snprintf(buffer, SIZE, "%*s- Route %zu:\n", spaces, "", i + 1);
write(fd, buffer, strlen(buffer));
itemAt(i)->dump(fd, 4);
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
index cde0923..191439e 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
@@ -308,6 +308,8 @@
}
}
}
+ ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__, mName.string(),
+ samplingRate, channelMask, format);
}
status_t AudioPort::checkGain(const struct audio_gain_config *gainConfig, int index) const
@@ -324,7 +326,7 @@
char buffer[SIZE];
String8 result;
- if (mName.length() != 0) {
+ if (!mName.isEmpty()) {
snprintf(buffer, SIZE, "%*s- name: %s\n", spaces, "", mName.string());
result.append(buffer);
write(fd, result.string(), result.size());
@@ -334,7 +336,8 @@
if (mGains.size() != 0) {
snprintf(buffer, SIZE, "%*s- gains:\n", spaces, "");
- write(fd, buffer, strlen(buffer) + 1);
+ result = buffer;
+ write(fd, result.string(), result.size());
for (size_t i = 0; i < mGains.size(); i++) {
mGains[i]->dump(fd, spaces + 2, i);
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp b/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
index b187857..e3ff9ae 100644
--- a/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
@@ -29,18 +29,6 @@
namespace android {
// --- audio_policy.conf file parsing
-//static
-uint32_t ConfigParsingUtils::parseOutputFlagNames(const char *name)
-{
- uint32_t flag = OutputFlagConverter::maskFromString(name);
- //force direct flag if offload flag is set: offloading implies a direct output stream
- // and all common behaviors are driven by checking only the direct flag
- // this should normally be set appropriately in the policy configuration file
- if ((flag & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
- flag |= AUDIO_OUTPUT_FLAG_DIRECT;
- }
- return flag;
-}
//static
void ConfigParsingUtils::loadAudioPortGain(cnode *root, AudioPort &audioPort, int index)
@@ -193,7 +181,7 @@
if (role == AUDIO_PORT_ROLE_SINK) {
profile->setFlags(InputFlagConverter::maskFromString(node->value));
} else {
- profile->setFlags(ConfigParsingUtils::parseOutputFlagNames(node->value));
+ profile->setFlags(OutputFlagConverter::maskFromString(node->value));
}
} else if (strcmp(node->name, GAINS_TAG) == 0) {
loadAudioPortGains(node, *profile);
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 538876c..787f53f 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -215,10 +215,10 @@
const size_t SIZE = 256;
char buffer[SIZE];
- snprintf(buffer, SIZE, "%*s %s devices:\n", spaces, "", tag.string());
+ snprintf(buffer, SIZE, "%*s- %s devices:\n", spaces, "", tag.string());
write(fd, buffer, strlen(buffer));
for (size_t i = 0; i < size(); i++) {
- itemAt(i)->dump(fd, spaces + 4, i, verbose);
+ itemAt(i)->dump(fd, spaces + 2, i, verbose);
}
return NO_ERROR;
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 93ab9c7..5bfe957 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -247,10 +247,7 @@
}
}
mDeclaredDevices.dump(fd, String8("Declared"), 2, true);
- if (!mRoutes.empty()) {
- write(fd, " - Audio Route:\n", strlen(" - Audio Route:\n"));
- mRoutes.dump(fd);
- }
+ mRoutes.dump(fd, 2);
}
sp <HwModule> HwModuleCollection::getModuleFromName(const char *name) const
diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index 6e0a071..204eb04 100644
--- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -111,7 +111,7 @@
snprintf(buffer, SIZE, " - flags: 0x%04x\n", getFlags());
result.append(buffer);
write(fd, result.string(), result.size());
- mSupportedDevices.dump(fd, String8("- Supported"), 2, false);
+ mSupportedDevices.dump(fd, String8("Supported"), 4, false);
}
void IOProfile::log()
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
new file mode 100644
index 0000000..77824df
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -0,0 +1,604 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "APM::Serializer"
+//#define LOG_NDEBUG 0
+
+#include "Serializer.h"
+#include <convert/convert.h>
+#include "TypeConverter.h"
+#include <libxml/parser.h>
+#include <libxml/xinclude.h>
+#include <string>
+#include <sstream>
+#include <istream>
+
+using std::string;
+
+namespace android {
+
+string getXmlAttribute(const xmlNode *cur, const char *attribute)
+{
+ xmlChar *xmlValue = xmlGetProp(cur, (const xmlChar*)attribute);
+ if (xmlValue == NULL) {
+ return "";
+ }
+ string value((const char*)xmlValue);
+ xmlFree(xmlValue);
+ return value;
+}
+
+using utilities::convertTo;
+
+const char *const PolicySerializer::rootName = "audioPolicyConfiguration";
+const char *const PolicySerializer::versionAttribute = "version";
+const uint32_t PolicySerializer::gMajor = 1;
+const uint32_t PolicySerializer::gMinor = 0;
+
+template <class Trait>
+static status_t deserializeCollection(_xmlDoc *doc, const _xmlNode *cur,
+ typename Trait::Collection &collection,
+ typename Trait::PtrSerializingCtx serializingContext)
+{
+ const xmlNode *root = cur->xmlChildrenNode;
+ while (root != NULL) {
+ if (xmlStrcmp(root->name, (const xmlChar *)Trait::collectionTag) &&
+ xmlStrcmp(root->name, (const xmlChar *)Trait::tag)) {
+ root = root->next;
+ continue;
+ }
+ if (!xmlStrcmp(root->name, (const xmlChar *)Trait::collectionTag)) {
+ root = root->xmlChildrenNode;
+ }
+ while (root != NULL) {
+ if (!xmlStrcmp(root->name, (const xmlChar *)Trait::tag)) {
+ typename Trait::PtrElement element;
+ status_t status = Trait::deserialize(doc, root, element, serializingContext);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ if (collection.add(element) < 0) {
+ ALOGE("%s: could not add element to %s collection", __FUNCTION__,
+ Trait::collectionTag);
+ }
+ }
+ root = root->next;
+ }
+ return NO_ERROR;
+ }
+ ALOGV("%s: No %s collection found", __FUNCTION__, Trait::collectionTag);
+ return BAD_VALUE;
+}
+
+const char *const AudioGainTraits::tag = "gain";
+const char *const AudioGainTraits::collectionTag = "gains";
+
+const char AudioGainTraits::Attributes::mode[] = "mode";
+const char AudioGainTraits::Attributes::channelMask[] = "channel_mask";
+const char AudioGainTraits::Attributes::minValueMB[] = "minValueMB";
+const char AudioGainTraits::Attributes::maxValueMB[] = "maxValueMB";
+const char AudioGainTraits::Attributes::defaultValueMB[] = "defaultValueMB";
+const char AudioGainTraits::Attributes::stepValueMB[] = "stepValueMB";
+const char AudioGainTraits::Attributes::minRampMs[] = "minRampMs";
+const char AudioGainTraits::Attributes::maxRampMs[] = "maxRampMs";
+
+status_t AudioGainTraits::deserialize(_xmlDoc */*doc*/, const _xmlNode *root, PtrElement &gain,
+ PtrSerializingCtx /*serializingContext*/)
+{
+ static uint32_t index = 0;
+ gain = new Element(index++, true);
+
+ string mode = getXmlAttribute(root, Attributes::mode);
+ if (!mode.empty()) {
+ gain->setMode(GainModeConverter::maskFromString(mode));
+ }
+
+ string channelsLiteral = getXmlAttribute(root, Attributes::channelMask);
+ if (!channelsLiteral.empty()) {
+ gain->setChannelMask(channelMaskFromString(channelsLiteral));
+ }
+
+ string minValueMBLiteral = getXmlAttribute(root, Attributes::minValueMB);
+ uint32_t minValueMB;
+ if (!minValueMBLiteral.empty() && convertTo(minValueMBLiteral, minValueMB)) {
+ gain->setMinValueInMb(minValueMB);
+ }
+
+ string maxValueMBLiteral = getXmlAttribute(root, Attributes::maxValueMB);
+ uint32_t maxValueMB;
+ if (!maxValueMBLiteral.empty() && convertTo(maxValueMBLiteral, maxValueMB)) {
+ gain->setMaxValueInMb(maxValueMB);
+ }
+
+ string defaultValueMBLiteral = getXmlAttribute(root, Attributes::defaultValueMB);
+ uint32_t defaultValueMB;
+ if (!defaultValueMBLiteral.empty() && convertTo(defaultValueMBLiteral, defaultValueMB)) {
+ gain->setDefaultValueInMb(defaultValueMB);
+ }
+
+ string stepValueMBLiteral = getXmlAttribute(root, Attributes::stepValueMB);
+ uint32_t stepValueMB;
+ if (!stepValueMBLiteral.empty() && convertTo(stepValueMBLiteral, stepValueMB)) {
+ gain->setStepValueInMb(stepValueMB);
+ }
+
+ string minRampMsLiteral = getXmlAttribute(root, Attributes::minRampMs);
+ uint32_t minRampMs;
+ if (!minRampMsLiteral.empty() && convertTo(minRampMsLiteral, minRampMs)) {
+ gain->setMinRampInMs(minRampMs);
+ }
+
+ string maxRampMsLiteral = getXmlAttribute(root, Attributes::maxRampMs);
+ uint32_t maxRampMs;
+ if (!maxRampMsLiteral.empty() && convertTo(maxRampMsLiteral, maxRampMs)) {
+ gain->setMaxRampInMs(maxRampMs);
+ }
+ ALOGV("%s: adding new gain mode %08x channel mask %08x min mB %d max mB %d", __FUNCTION__,
+ gain->getMode(), gain->getChannelMask(), gain->getMinValueInMb(),
+ gain->getMaxValueInMb());
+
+ if (gain->getMode() == 0) {
+ return BAD_VALUE;
+ }
+ return NO_ERROR;
+}
+
+const char *const AudioProfileTraits::collectionTag = "profiles";
+const char *const AudioProfileTraits::tag = "profile";
+
+const char AudioProfileTraits::Attributes::name[] = "name";
+const char AudioProfileTraits::Attributes::samplingRates[] = "samplingRates";
+const char AudioProfileTraits::Attributes::format[] = "format";
+const char AudioProfileTraits::Attributes::channelMasks[] = "channelMasks";
+
+status_t AudioProfileTraits::deserialize(_xmlDoc */*doc*/, const _xmlNode *root, PtrElement &profile,
+ PtrSerializingCtx /*serializingContext*/)
+{
+ string samplingRates = getXmlAttribute(root, Attributes::samplingRates);
+ string format = getXmlAttribute(root, Attributes::format);
+ string channels = getXmlAttribute(root, Attributes::channelMasks);
+
+ profile = new Element(formatFromString(format), channelMasksFromString(channels, ","),
+ samplingRatesFromString(samplingRates, ","));
+
+ profile->setDynamicFormat(profile->getFormat() == gDynamicFormat);
+ profile->setDynamicChannels(profile->getChannels().isEmpty());
+ profile->setDynamicRate(profile->getSampleRates().isEmpty());
+
+ return NO_ERROR;
+}
+
+
+const char *const MixPortTraits::collectionTag = "mixPorts";
+const char *const MixPortTraits::tag = "mixPort";
+
+const char MixPortTraits::Attributes::name[] = "name";
+const char MixPortTraits::Attributes::role[] = "role";
+const char MixPortTraits::Attributes::flags[] = "flags";
+
+status_t MixPortTraits::deserialize(_xmlDoc *doc, const _xmlNode *child, PtrElement &mixPort,
+ PtrSerializingCtx /*serializingContext*/)
+{
+ string name = getXmlAttribute(child, Attributes::name);
+ if (name.empty()) {
+ ALOGE("%s: No %s found", __FUNCTION__, Attributes::name);
+ return BAD_VALUE;
+ }
+ ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::name, name.c_str());
+ string role = getXmlAttribute(child, Attributes::role);
+ if (role.empty()) {
+ ALOGE("%s: No %s found", __FUNCTION__, Attributes::role);
+ return BAD_VALUE;
+ }
+ ALOGV("%s: Role=%s", __FUNCTION__, role.c_str());
+ audio_port_role_t portRole = role == "source" ? AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
+
+ mixPort = new Element(String8(name.c_str()), portRole);
+
+ AudioProfileTraits::Collection profiles;
+ deserializeCollection<AudioProfileTraits>(doc, child, profiles, NULL);
+ if (profiles.isEmpty()) {
+ sp <AudioProfile> dynamicProfile = new AudioProfile(gDynamicFormat,
+ ChannelsVector(), SampleRateVector());
+ dynamicProfile->setDynamicFormat(true);
+ dynamicProfile->setDynamicChannels(true);
+ dynamicProfile->setDynamicRate(true);
+ profiles.add(dynamicProfile);
+ }
+ mixPort->setAudioProfiles(profiles);
+
+ string flags = getXmlAttribute(child, Attributes::flags);
+ if (!flags.empty()) {
+ // Source role
+ if (portRole == AUDIO_PORT_ROLE_SOURCE) {
+ mixPort->setFlags(OutputFlagConverter::maskFromString(flags));
+ } else {
+ // Sink role
+ mixPort->setFlags(InputFlagConverter::maskFromString(flags));
+ }
+ }
+ // Deserialize children
+ AudioGainTraits::Collection gains;
+ deserializeCollection<AudioGainTraits>(doc, child, gains, NULL);
+ mixPort->setGains(gains);
+
+ return NO_ERROR;
+}
+
+const char *const DevicePortTraits::tag = "devicePort";
+const char *const DevicePortTraits::collectionTag = "devicePorts";
+
+const char DevicePortTraits::Attributes::tagName[] = "tagName";
+const char DevicePortTraits::Attributes::type[] = "type";
+const char DevicePortTraits::Attributes::role[] = "role";
+const char DevicePortTraits::Attributes::address[] = "address";
+const char DevicePortTraits::Attributes::roleSource[] = "source";
+
+status_t DevicePortTraits::deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &deviceDesc,
+ PtrSerializingCtx /*serializingContext*/)
+{
+ string name = getXmlAttribute(root, Attributes::tagName);
+ if (name.empty()) {
+ ALOGE("%s: No %s found", __FUNCTION__, Attributes::tagName);
+ return BAD_VALUE;
+ }
+ ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::tagName, name.c_str());
+ string typeName = getXmlAttribute(root, Attributes::type);
+ if (typeName.empty()) {
+ ALOGE("%s: no type for %s", __FUNCTION__, name.c_str());
+ return BAD_VALUE;
+ }
+ ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::type, typeName.c_str());
+ string role = getXmlAttribute(root, Attributes::role);
+ if (role.empty()) {
+ ALOGE("%s: No %s found", __FUNCTION__, Attributes::role);
+ return BAD_VALUE;
+ }
+ ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::role, role.c_str());
+ audio_port_role_t portRole = (role == Attributes::roleSource) ?
+ AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
+
+ audio_devices_t type = AUDIO_DEVICE_NONE;
+ if (!DeviceConverter::fromString(typeName, type) ||
+ (!audio_is_input_device(type) && portRole == AUDIO_PORT_ROLE_SOURCE) ||
+ (!audio_is_output_devices(type) && portRole == AUDIO_PORT_ROLE_SINK)) {
+ ALOGW("%s: bad type %08x", __FUNCTION__, type);
+ return BAD_VALUE;
+ }
+ deviceDesc = new Element(type, String8(name.c_str()));
+
+ string address = getXmlAttribute(root, Attributes::address);
+ if (!address.empty()) {
+ ALOGV("%s: address=%s for %s", __FUNCTION__, address.c_str(), name.c_str());
+ deviceDesc->mAddress = String8(address.c_str());
+ }
+
+ AudioProfileTraits::Collection profiles;
+ deserializeCollection<AudioProfileTraits>(doc, root, profiles, NULL);
+ if (profiles.isEmpty()) {
+ sp <AudioProfile> dynamicProfile = new AudioProfile(gDynamicFormat,
+ ChannelsVector(), SampleRateVector());
+ dynamicProfile->setDynamicFormat(true);
+ dynamicProfile->setDynamicChannels(true);
+ dynamicProfile->setDynamicRate(true);
+ profiles.add(dynamicProfile);
+ }
+ deviceDesc->setAudioProfiles(profiles);
+
+ // Deserialize AudioGain children
+ deserializeCollection<AudioGainTraits>(doc, root, deviceDesc->mGains, NULL);
+ ALOGV("%s: adding device tag %s type %08x address %s", __FUNCTION__,
+ deviceDesc->getName().string(), type, deviceDesc->mAddress.string());
+ return NO_ERROR;
+}
+
+const char *const RouteTraits::tag = "route";
+const char *const RouteTraits::collectionTag = "routes";
+
+const char RouteTraits::Attributes::type[] = "type";
+const char RouteTraits::Attributes::typeMix[] = "mix";
+const char RouteTraits::Attributes::sink[] = "sink";
+const char RouteTraits::Attributes::sources[] = "sources";
+
+
+status_t RouteTraits::deserialize(_xmlDoc */*doc*/, const _xmlNode *root, PtrElement &element,
+ PtrSerializingCtx ctx)
+{
+ string type = getXmlAttribute(root, Attributes::type);
+ if (type.empty()) {
+ ALOGE("%s: No %s found", __FUNCTION__, Attributes::type);
+ return BAD_VALUE;
+ }
+ audio_route_type_t routeType = (type == Attributes::typeMix) ?
+ AUDIO_ROUTE_MIX : AUDIO_ROUTE_MUX;
+
+ ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::type, type.c_str());
+ element = new Element(routeType);
+
+ string sinkAttr = getXmlAttribute(root, Attributes::sink);
+ if (sinkAttr.empty()) {
+ ALOGE("%s: No %s found", __FUNCTION__, Attributes::sink);
+ return BAD_VALUE;
+ }
+ // Convert Sink name to port pointer
+ sp<AudioPort> sink = ctx->findPortByTagName(String8(sinkAttr.c_str()));
+ if (sink == NULL) {
+ ALOGE("%s: no sink found with name=%s", __FUNCTION__, sinkAttr.c_str());
+ return BAD_VALUE;
+ }
+ element->setSink(sink);
+
+ string sourcesAttr = getXmlAttribute(root, Attributes::sources);
+ if (sourcesAttr.empty()) {
+ ALOGE("%s: No %s found", __FUNCTION__, Attributes::sources);
+ return BAD_VALUE;
+ }
+ // Tokenize and Convert Sources name to port pointer
+ AudioPortVector sources;
+ char *sourcesLiteral = strndup(sourcesAttr.c_str(), strlen(sourcesAttr.c_str()));
+ char *devTag = strtok(sourcesLiteral, ",");
+ while (devTag != NULL) {
+ if (strlen(devTag) != 0) {
+ sp<AudioPort> source = ctx->findPortByTagName(String8(devTag));
+ if (source == NULL) {
+ ALOGE("%s: no source found with name=%s", __FUNCTION__, devTag);
+ return BAD_VALUE;
+ }
+ sources.add(source);
+ }
+ devTag = strtok(NULL, ",");
+ }
+ free(sourcesLiteral);
+
+ sink->addRoute(element);
+ for (size_t i = 0; i < sources.size(); i++) {
+ sp<AudioPort> source = sources.itemAt(i);
+ source->addRoute(element);
+ }
+ element->setSources(sources);
+ return NO_ERROR;
+}
+
+const char *const ModuleTraits::childAttachedDevicesTag = "attachedDevices";
+const char *const ModuleTraits::childAttachedDeviceTag = "item";
+const char *const ModuleTraits::childDefaultOutputDeviceTag = "defaultOutputDevice";
+
+const char *const ModuleTraits::tag = "module";
+const char *const ModuleTraits::collectionTag = "modules";
+
+const char ModuleTraits::Attributes::name[] = "name";
+const char ModuleTraits::Attributes::version[] = "halVersion";
+
+status_t ModuleTraits::deserialize(xmlDocPtr doc, const xmlNode *root, PtrElement &module,
+ PtrSerializingCtx ctx)
+{
+ string name = getXmlAttribute(root, Attributes::name);
+ if (name.empty()) {
+ ALOGE("%s: No %s found", __FUNCTION__, Attributes::name);
+ return BAD_VALUE;
+ }
+ uint32_t version = AUDIO_DEVICE_API_VERSION_MIN;
+ string versionLiteral = getXmlAttribute(root, Attributes::version);
+ if (!versionLiteral.empty()) {
+ uint32_t major, minor;
+ sscanf(versionLiteral.c_str(), "%u.%u", &major, &minor);
+ version = HARDWARE_DEVICE_API_VERSION(major, minor);
+ ALOGV("%s: mHalVersion = %04x major %u minor %u", __FUNCTION__,
+ version, major, minor);
+ }
+
+ ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::name, name.c_str());
+
+ module = new Element(name.c_str(), version);
+
+ // Deserialize childrens: Audio Mix Port, Audio Device Ports (Source/Sink), Audio Routes
+ MixPortTraits::Collection mixPorts;
+ deserializeCollection<MixPortTraits>(doc, root, mixPorts, NULL);
+ module->setProfiles(mixPorts);
+
+ DevicePortTraits::Collection devicePorts;
+ deserializeCollection<DevicePortTraits>(doc, root, devicePorts, NULL);
+ module->setDeclaredDevices(devicePorts);
+
+ RouteTraits::Collection routes;
+ deserializeCollection<RouteTraits>(doc, root, routes, module.get());
+ module->setRoutes(routes);
+
+ const xmlNode *children = root->xmlChildrenNode;
+ while (children != NULL) {
+ if (!xmlStrcmp(children->name, (const xmlChar *)childAttachedDevicesTag)) {
+ ALOGV("%s: %s %s found", __FUNCTION__, tag, childAttachedDevicesTag);
+ const xmlNode *child = children->xmlChildrenNode;
+ while (child != NULL) {
+ if (!xmlStrcmp(child->name, (const xmlChar *)childAttachedDeviceTag)) {
+ xmlChar *attachedDevice = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
+ if (attachedDevice != NULL) {
+ ALOGV("%s: %s %s=%s", __FUNCTION__, tag, childAttachedDeviceTag,
+ (const char*)attachedDevice);
+ sp<DeviceDescriptor> device =
+ module->getDeclaredDevices().getDeviceFromTagName(String8((const char*)attachedDevice));
+ ctx->addAvailableDevice(device);
+ xmlFree(attachedDevice);
+ }
+ }
+ child = child->next;
+ }
+ }
+ if (!xmlStrcmp(children->name, (const xmlChar *)childDefaultOutputDeviceTag)) {
+ xmlChar *defaultOutputDevice = xmlNodeListGetString(doc, children->xmlChildrenNode, 1);;
+ if (defaultOutputDevice != NULL) {
+ ALOGV("%s: %s %s=%s", __FUNCTION__, tag, childDefaultOutputDeviceTag,
+ (const char*)defaultOutputDevice);
+ sp<DeviceDescriptor> device =
+ module->getDeclaredDevices().getDeviceFromTagName(String8((const char*)defaultOutputDevice));
+ if (device != 0 && ctx->getDefaultOutputDevice() == 0) {
+ ctx->setDefaultOutputDevice(device);
+ ALOGV("%s: default is %08x", __FUNCTION__, ctx->getDefaultOutputDevice()->type());
+ }
+ xmlFree(defaultOutputDevice);
+ }
+ }
+ children = children->next;
+ }
+ return NO_ERROR;
+}
+
+const char *const GlobalConfigTraits::tag = "globalConfiguration";
+
+const char GlobalConfigTraits::Attributes::speakerDrcEnabled[] = "speaker_drc_enabled";
+
+
+status_t GlobalConfigTraits::deserialize(const xmlNode *cur, AudioPolicyConfig &config)
+{
+ const xmlNode *root = cur->xmlChildrenNode;
+ while (root != NULL) {
+ if (!xmlStrcmp(root->name, (const xmlChar *)tag)) {
+ string speakerDrcEnabled =
+ getXmlAttribute(root, Attributes::speakerDrcEnabled);
+ bool isSpeakerDrcEnabled;
+ if (!speakerDrcEnabled.empty() &&
+ convertTo<string, bool>(speakerDrcEnabled, isSpeakerDrcEnabled)) {
+ config.setSpeakerDrcEnabled(isSpeakerDrcEnabled);
+ }
+ return NO_ERROR;
+ }
+ root = root->next;
+ }
+ return NO_ERROR;
+}
+
+
+const char *const VolumeTraits::tag = "volume";
+const char *const VolumeTraits::collectionTag = "volumes";
+const char *const VolumeTraits::volumePointTag = "point";
+
+const char VolumeTraits::Attributes::stream[] = "stream";
+const char VolumeTraits::Attributes::deviceCategory[] = "deviceCategory";
+
+
+status_t VolumeTraits::deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
+ PtrSerializingCtx /*serializingContext*/)
+{
+ string streamTypeLiteral = getXmlAttribute(root, Attributes::stream);
+ if (streamTypeLiteral.empty()) {
+ ALOGE("%s: No %s found", __FUNCTION__, Attributes::stream);
+ return BAD_VALUE;
+ }
+ audio_stream_type_t streamType;
+ if (!StreamTypeConverter::fromString(streamTypeLiteral, streamType)) {
+ ALOGE("%s: Invalid %s", __FUNCTION__, Attributes::stream);
+ return BAD_VALUE;
+ }
+ string deviceCategoryLiteral = getXmlAttribute(root, Attributes::deviceCategory);
+ if (deviceCategoryLiteral.empty()) {
+ ALOGE("%s: No %s found", __FUNCTION__, Attributes::deviceCategory);
+ return BAD_VALUE;
+ }
+ device_category deviceCategory;
+ if (!DeviceCategoryConverter::fromString(deviceCategoryLiteral, deviceCategory)) {
+ ALOGE("%s: Invalid %s=%s", __FUNCTION__, Attributes::deviceCategory,
+ deviceCategoryLiteral.c_str());
+ return BAD_VALUE;
+ }
+ CurvePoints points;
+ const xmlNode *child = root->xmlChildrenNode;
+ while (child != NULL) {
+ if (!xmlStrcmp(child->name, (const xmlChar *)volumePointTag)) {
+ xmlChar *pointDefinition = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);;
+ if (pointDefinition == NULL) {
+ return BAD_VALUE;
+ }
+ ALOGV("%s: %s=%s", __FUNCTION__, tag, (const char*)pointDefinition);
+ Vector<int32_t> point;
+ collectionFromString<DefaultTraits<int32_t> >((const char*)pointDefinition, point, ",");
+ if (point.size() != 2) {
+ ALOGE("%s: Invalid %s: %s", __FUNCTION__, volumePointTag,
+ (const char*)pointDefinition);
+ return BAD_VALUE;
+ }
+ points.add(std::make_pair(point[0], point[1]));
+ xmlFree(pointDefinition);
+ }
+ child = child->next;
+ }
+ element = new Element();
+ element->setDeviceCategory(deviceCategory);
+ element->setStreamType(streamType);
+ element->setCurvePoints(points);
+ return NO_ERROR;
+}
+
+PolicySerializer::PolicySerializer() : mRootElementName(rootName)
+{
+ std::ostringstream oss;
+ oss << gMajor << "." << gMinor;
+ mVersion = oss.str();
+ ALOGV("%s: Version=%s Root=%s", __FUNCTION__, mVersion.c_str(), mRootElementName.c_str());
+}
+
+status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig &config)
+{
+ xmlDocPtr doc;
+ doc = xmlParseFile(configFile);
+ if (doc == NULL) {
+ ALOGE("%s: Could not parse %s document.", __FUNCTION__, configFile);
+ return BAD_VALUE;
+ }
+ xmlNodePtr cur = xmlDocGetRootElement(doc);
+ if (cur == NULL) {
+ ALOGE("%s: Could not parse %s document: empty.", __FUNCTION__, configFile);
+ xmlFreeDoc(doc);
+ return BAD_VALUE;
+ }
+ if (xmlXIncludeProcess(doc) < 0) {
+ ALOGE("%s: libxml failed to resolve XIncludes on %s document.", __FUNCTION__, configFile);
+ }
+
+ if (xmlStrcmp(cur->name, (const xmlChar *) mRootElementName.c_str())) {
+ ALOGE("%s: No %s root element found in xml data %s.", __FUNCTION__, mRootElementName.c_str(),
+ (const char *)cur->name);
+ xmlFreeDoc(doc);
+ return BAD_VALUE;
+ }
+
+ string version = getXmlAttribute(cur, versionAttribute);
+ if (version.empty()) {
+ ALOGE("%s: No version found in root node %s", __FUNCTION__, mRootElementName.c_str());
+ return BAD_VALUE;
+ }
+ if (version != mVersion) {
+ ALOGE("%s: Version does not match; expect %s got %s", __FUNCTION__, mVersion.c_str(),
+ version.c_str());
+ return BAD_VALUE;
+ }
+ // Lets deserialize children
+ // Modules
+ ModuleTraits::Collection modules;
+ deserializeCollection<ModuleTraits>(doc, cur, modules, &config);
+ config.setHwModules(modules);
+
+ // deserialize volume section
+ VolumeTraits::Collection volumes;
+ deserializeCollection<VolumeTraits>(doc, cur, volumes, NULL);
+
+ // Global Configuration
+ GlobalConfigTraits::deserialize(cur, config);
+
+ xmlFreeDoc(doc);
+ return android::OK;
+}
+
+}; // namespace android
diff --git a/services/audiopolicy/config/a2dp_audio_policy_configuration.xml b/services/audiopolicy/config/a2dp_audio_policy_configuration.xml
new file mode 100644
index 0000000..ced7463
--- /dev/null
+++ b/services/audiopolicy/config/a2dp_audio_policy_configuration.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- A2dp Audio HAL Audio Policy Configuration file -->
+<module name="a2dp" halVersion="2.0">
+ <mixPorts>
+ <mixPort name="a2dp output" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="a2dp input" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <devicePort tagName="BT A2DP Out" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BT A2DP Headphones" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BT A2DP Speaker" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BT A2DP In" type="AUDIO_DEVICE_IN_BLUETOOTH_A2DP" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
+ </devicePort>
+ </devicePorts>
+ <routes>
+ <route type="mix" sink="BT A2DP Out"
+ sources="a2dp output"/>
+ <route type="mix" sink="BT A2DP Headphones"
+ sources="a2dp output"/>
+ <route type="mix" sink="BT A2DP Speaker"
+ sources="a2dp output"/>
+ <route type="mix" sink="a2dp input"
+ sources="BT A2DP In"/>
+ </routes>
+</module>
diff --git a/services/audiopolicy/config/audio_policy_configuration.xml b/services/audiopolicy/config/audio_policy_configuration.xml
new file mode 100644
index 0000000..dccc3a8
--- /dev/null
+++ b/services/audiopolicy/config/audio_policy_configuration.xml
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <!-- version section contains a “version” tag in the form “major.minor” e.g version=”1.0” -->
+
+ <!-- Global configuration Decalaration -->
+ <globalConfiguration speaker_drc_enabled="true"/>
+
+
+ <!-- Modules section:
+ There is one section per audio HW module present on the platform.
+ Each module section will contains two mandatory tags for audio HAL “halVersion” and “name”.
+ The module names are the same as in current .conf file:
+ “primary”, “A2DP”, “remote_submix”, “USB”
+ Each module will contain the following sections:
+ “devicePorts”: a list of device descriptors for all input and output devices accessible via this
+ module.
+ This contains both permanently attached devices and removable devices.
+ “mixPorts”: listing all output and input streams exposed by the audio HAL
+ “routes”: list of possible connections between input and output devices or between stream and
+ devices.
+ "route": is defined by an attribute:
+ -"type": <mux|mix> means all sources are mutual exclusive (mux) or can be mixed (mix)
+ -"sink": the sink involved in this route
+ -"sources": all the sources than can be connected to the sink via vis route
+ “attachedDevices”: permanently attached devices.
+ The attachedDevices section is a list of devices names. The names correspond to device names
+ defined in <devicePorts> section.
+ “defaultOutputDevice”: device to be used by default when no policy rule applies
+ -->
+ <modules>
+ <!-- Primary Audio HAL -->
+ <module name="primary" halVersion="3.0">
+ <attachedDevices>
+ <item>Speaker</item>
+ <item>Built-In Mic</item>
+ <item>Built-In Back Mic</item>
+ </attachedDevices>
+ <defaultOutputDevice>Speaker</defaultOutputDevice>
+ <mixPorts>
+ <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="deep_buffer" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DEEP_BUFFER">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="compressed_offload" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING">
+ <profile name="" format="AUDIO_FORMAT_MP3"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_AAC"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_AAC_LC"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+ </mixPort>
+ <mixPort name="voice_tx" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+ </mixPort>
+ <mixPort name="primary input" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </mixPort>
+ <mixPort name="voice_rx" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <!-- Output devices declaration, i.e. Sink DEVICE PORT -->
+ <devicePort tagName="Earpiece" type="AUDIO_DEVICE_OUT_EARPIECE" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </devicePort>
+ <devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER" address="">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ <gains>
+ <gain name="gain_1" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-8400"
+ maxValueMB="4000"
+ defaultValueMB="0"
+ stepValueMB="100"/>
+ </gains>
+ </devicePort>
+ <devicePort tagName="Wired Headset" type="AUDIO_DEVICE_OUT_WIRED_HEADSET" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="Wired Headphones" type="AUDIO_DEVICE_OUT_WIRED_HEADPHONE" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+ </devicePort>
+ <devicePort tagName="BT SCO Headset" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+ </devicePort>
+ <devicePort tagName="BT SCO Car Kit" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+ </devicePort>
+ <devicePort tagName="Telephony Tx" type="AUDIO_DEVICE_OUT_TELEPHONY_TX" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+ </devicePort>
+
+ <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </devicePort>
+ <devicePort tagName="Built-In Back Mic" type="AUDIO_DEVICE_IN_BACK_MIC" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </devicePort>
+ <devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </devicePort>
+ <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </devicePort>
+ <devicePort tagName="Telephony Rx" type="AUDIO_DEVICE_IN_TELEPHONY_RX" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </devicePort>
+ </devicePorts>
+ <!-- route declaration, i.e. list all available sources for a given sink -->
+ <routes>
+ <route type="mix" sink="Earpiece"
+ sources="primary output,deep_buffer,BT SCO Headset Mic"/>
+ <route type="mix" sink="Speaker"
+ sources="primary output,deep_buffer,compressed_offload,BT SCO Headset Mic,Telephony Rx"/>
+ <route type="mix" sink="Wired Headset"
+ sources="primary output,deep_buffer,compressed_offload,BT SCO Headset Mic,Telephony Rx"/>
+ <route type="mix" sink="Wired Headphones"
+ sources="primary output,deep_buffer,compressed_offload,BT SCO Headset Mic,Telephony Rx"/>
+ <route type="mix" sink="Telephony Tx"
+ sources="voice_tx"/>
+ <route type="mix" sink="primary input"
+ sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic"/>
+ <route type="mix" sink="Telephony Tx"
+ sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic"/>
+ <route type="mix" sink="voice_rx"
+ sources="Telephony Rx"/>
+ </routes>
+
+ </module>
+
+ <!-- HDMI Audio HAL -->
+ <module description="HDMI Audio HAL" name="hdmi" version="2.0">
+ <mixPorts>
+ <mixPort name="hdmi output" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000"/>
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <devicePort tagName="HDMI Out" type="AUDIO_DEVICE_OUT_AUX_DIGITAL" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ </devicePorts>
+ <routes>
+ <route type="mix" sink="HDMI Out"
+ sources="hdmi output"/>
+ </routes>
+ </module>
+
+ <!-- A2dp Audio HAL -->
+ <xi:include href="a2dp_audio_policy_configuration.xml"/>
+
+ <!-- Usb Audio HAL -->
+ <xi:include href="usb_audio_policy_configuration.xml"/>
+
+ <!-- Remote Submix Audio HAL -->
+ <xi:include href="r_submix_audio_policy_configuration.xml"/>
+
+ </modules>
+ <!-- End of Modules section -->
+
+ <!-- Volume section defines a volume curve for a given use case and device category.
+ It contains a list of points of this curve expressing the attenuation in Millibels for a given
+ volume index from 0 to 100.
+ <volume stream=”AUDIO_STREAM_MUSIC” deviceCategory=””>
+ <point>0, -9600</point>
+ <point>100, 0</point>
+ </volume>
+ -->
+ <volumes>
+ <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-9600</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_EARPIECE">
+ <point>0,-9800</point>
+ <point>50,-1000</point>
+ <point>100,0</point>
+ </volume>
+ </volumes>
+
+ <!-- End of Volume section -->
+
+
+
+</audioPolicyConfiguration>
diff --git a/services/audiopolicy/config/r_submix_audio_policy_configuration.xml b/services/audiopolicy/config/r_submix_audio_policy_configuration.xml
new file mode 100644
index 0000000..dc2a5ec
--- /dev/null
+++ b/services/audiopolicy/config/r_submix_audio_policy_configuration.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- Remote Submix Audio Policy Configuration file -->
+<module name="r_submix" halVersion="2.0">
+ <attachedDevices>
+ <item>Remote Submix In</item>
+ </attachedDevices>
+ <mixPorts>
+ <mixPort name="r_submix output" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="r_submix input" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <devicePort tagName="Remote Submix Out" type="AUDIO_DEVICE_OUT_REMOTE_SUBMIX" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="Remote Submix In" type="AUDIO_DEVICE_IN_REMOTE_SUBMIX" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ </devicePort>
+ </devicePorts>
+ <routes>
+ <route type="mix" sink="Remote Submix Out"
+ sources="r_submix output"/>
+ <route type="mix" sink="r_submix input"
+ sources="Remote Submix In"/>
+ </routes>
+</module>
diff --git a/services/audiopolicy/config/usb_audio_policy_configuration.xml b/services/audiopolicy/config/usb_audio_policy_configuration.xml
new file mode 100644
index 0000000..1630a94
--- /dev/null
+++ b/services/audiopolicy/config/usb_audio_policy_configuration.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- USB Audio HAL Audio Policy Configuration file -->
+
+<module name="usb" halVersion="2.0">
+ <mixPorts>
+ <mixPort name="usb_accessory output" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="usb_device output" role="source"/>
+ <mixPort name="usb_device input" role="sink"/>
+ </mixPorts>
+ <devicePorts>
+ <devicePort tagName="USB Host Out" type="AUDIO_DEVICE_OUT_USB_ACCESSORY" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="USB Device Out" type="AUDIO_DEVICE_OUT_USB_DEVICE" role="sink"/>
+ <devicePort tagName="USB Device In" type="AUDIO_DEVICE_IN_USB_DEVICE" role="source"/>
+ </devicePorts>
+ <routes>
+ <route type="mix" sink="USB Host Out"
+ sources="usb_accessory output"/>
+ <route type="mix" sink="USB Device Out"
+ sources="usb_device output"/>
+ <route type="mix" sink="usb_device input"
+ sources="USB Device In"/>
+ </routes>
+</module>
diff --git a/services/audiopolicy/engineconfigurable/Android.mk b/services/audiopolicy/engineconfigurable/Android.mk
index b18c520..06d00ca 100755
--- a/services/audiopolicy/engineconfigurable/Android.mk
+++ b/services/audiopolicy/engineconfigurable/Android.mk
@@ -41,7 +41,11 @@
LOCAL_STATIC_LIBRARIES := \
libmedia_helper \
libaudiopolicypfwwrapper \
- libaudiopolicycomponents
+ libaudiopolicycomponents \
+
+ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
+LOCAL_STATIC_LIBRARIES += libxml2
+endif
LOCAL_SHARED_LIBRARIES := \
libcutils \
diff --git a/services/audiopolicy/enginedefault/Android.mk b/services/audiopolicy/enginedefault/Android.mk
index 8d43b89..b3b3dde 100755
--- a/services/audiopolicy/enginedefault/Android.mk
+++ b/services/audiopolicy/enginedefault/Android.mk
@@ -34,9 +34,15 @@
LOCAL_MODULE := libaudiopolicyenginedefault
LOCAL_MODULE_TAGS := optional
+
LOCAL_STATIC_LIBRARIES := \
libmedia_helper \
- libaudiopolicycomponents
+ libaudiopolicycomponents \
+
+ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
+LOCAL_STATIC_LIBRARIES += libxml2
+endif #ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
+
LOCAL_SHARED_LIBRARIES += \
libcutils \
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 04af88d..2aed7b1 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -24,6 +24,8 @@
#define ALOGVV(a...) do { } while(0)
#endif
+#define AUDIO_POLICY_XML_CONFIG_FILE "/system/etc/audio_policy_configuration.xml"
+
#include <inttypes.h>
#include <math.h>
@@ -37,7 +39,11 @@
#include <media/AudioPolicyHelper.h>
#include <soundtrigger/SoundTrigger.h>
#include "AudioPolicyManager.h"
+#ifdef USE_XML_AUDIO_POLICY_CONF
+#include <Serializer.h>
+#else
#include <ConfigParsingUtils.h>
+#endif
#include "TypeConverter.h"
#include <policy.h>
@@ -3014,9 +3020,13 @@
AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,
mDefaultOutputDevice, mSpeakerDrcEnabled);
+#ifdef USE_XML_AUDIO_POLICY_CONF
+ PolicySerializer serializer;
+ if (serializer.deserialize(AUDIO_POLICY_XML_CONFIG_FILE, config) != NO_ERROR) {
+#else
if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, config) != NO_ERROR) &&
- (ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, config) != NO_ERROR)) {
-
+ (ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, config) != NO_ERROR)) {
+#endif
ALOGE("could not load audio policy configuration file, setting defaults");
config.setDefault();
}