156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi/*
256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * Copyright (C) 2015 The Android Open Source Project
356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi *
456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * you may not use this file except in compliance with the License.
656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * You may obtain a copy of the License at
756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi *
856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi *
1056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
1156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
1256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * See the License for the specific language governing permissions and
1456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * limitations under the License.
1556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi */
1656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
1756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi#define LOG_TAG "APM::ConfigParsingUtils"
1856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi//#define LOG_NDEBUG 0
1956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
20ad3183e2d4cecd02f6261270a7ea1c68be0efa0fFrançois Gaffie#include "ConfigParsingUtils.h"
21a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie#include <convert/convert.h>
2253615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie#include "AudioGain.h"
23a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie#include "IOProfile.h"
24a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie#include "TypeConverter.h"
2553615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie#include <hardware/audio.h>
26ad3183e2d4cecd02f6261270a7ea1c68be0efa0fFrançois Gaffie#include <utils/Log.h>
2753615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie#include <cutils/misc.h>
2856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
2956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivinamespace android {
3056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
31a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie// --- audio_policy.conf file parsing
3256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
3356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi//static
34a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffievoid ConfigParsingUtils::loadAudioPortGain(cnode *root, AudioPort &audioPort, int index)
3556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
36a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    cnode *node = root->first_child;
37a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie
38a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    sp<AudioGain> gain = new AudioGain(index, audioPort.useInputChannelMask());
39a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie
40a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    while (node) {
41a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        if (strcmp(node->name, GAIN_MODE) == 0) {
42a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            gain->setMode(GainModeConverter::maskFromString(node->value));
43a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        } else if (strcmp(node->name, GAIN_CHANNELS) == 0) {
44a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            audio_channel_mask_t mask;
45a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            if (audioPort.useInputChannelMask()) {
46a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                if (InputChannelConverter::fromString(node->value, mask)) {
47a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                    gain->setChannelMask(mask);
48a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                }
49a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            } else {
50a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                if (OutputChannelConverter::fromString(node->value, mask)) {
51a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                    gain->setChannelMask(mask);
52a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                }
53a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            }
54a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        } else if (strcmp(node->name, GAIN_MIN_VALUE) == 0) {
55a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            gain->setMinValueInMb(atoi(node->value));
56a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        } else if (strcmp(node->name, GAIN_MAX_VALUE) == 0) {
57a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            gain->setMaxValueInMb(atoi(node->value));
58a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        } else if (strcmp(node->name, GAIN_DEFAULT_VALUE) == 0) {
59a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            gain->setDefaultValueInMb(atoi(node->value));
60a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        } else if (strcmp(node->name, GAIN_STEP_VALUE) == 0) {
61a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            gain->setStepValueInMb(atoi(node->value));
62a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        } else if (strcmp(node->name, GAIN_MIN_RAMP_MS) == 0) {
63a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            gain->setMinRampInMs(atoi(node->value));
64a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        } else if (strcmp(node->name, GAIN_MAX_RAMP_MS) == 0) {
65a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            gain->setMaxRampInMs(atoi(node->value));
6656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
67a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        node = node->next;
68a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    }
69a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie
70a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    ALOGV("loadGain() adding new gain mode %08x channel mask %08x min mB %d max mB %d",
71a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie          gain->getMode(), gain->getChannelMask(), gain->getMinValueInMb(),
72a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie          gain->getMaxValueInMb());
73a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie
74a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    if (gain->getMode() == 0) {
75a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        return;
7656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
77a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    audioPort.mGains.add(gain);
7856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
7956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
80a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffievoid ConfigParsingUtils::loadAudioPortGains(cnode *root, AudioPort &audioPort)
8156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
82a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    cnode *node = root->first_child;
83a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    int index = 0;
84a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    while (node) {
85a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        ALOGV("loadGains() loading gain %s", node->name);
86a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        loadAudioPortGain(node, audioPort, index++);
87a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        node = node->next;
88a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    }
8956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
9056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
91a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie//static
92a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffievoid ConfigParsingUtils::loadDeviceDescriptorGains(cnode *root, sp<DeviceDescriptor> &deviceDesc)
93a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie{
94a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    loadAudioPortGains(root, *deviceDesc);
95a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    if (deviceDesc->mGains.size() > 0) {
96a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        deviceDesc->mGains[0]->getDefaultConfig(&deviceDesc->mGain);
97a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    }
98a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie}
9956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
10056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi//static
101a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffiestatus_t ConfigParsingUtils::loadHwModuleDevice(cnode *root, DeviceVector &devices)
10256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
103a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    cnode *node = root->first_child;
104a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie
105a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    audio_devices_t type = AUDIO_DEVICE_NONE;
106a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    while (node) {
107a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        if (strcmp(node->name, APM_DEVICE_TYPE) == 0) {
108a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            DeviceConverter::fromString(node->value, type);
109a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            break;
11056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
111a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        node = node->next;
11256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
113a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    if (type == AUDIO_DEVICE_NONE ||
114a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            (!audio_is_input_device(type) && !audio_is_output_device(type))) {
115a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        ALOGW("loadDevice() bad type %08x", type);
116a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        return BAD_VALUE;
11756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
1181d4481fb9cb1ea149f79f2a5d22110af84fbc90bFrançois Gaffie    sp<DeviceDescriptor> deviceDesc = new DeviceDescriptor(type, String8(root->name));
11956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
120a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    node = root->first_child;
121a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    while (node) {
122a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        if (strcmp(node->name, APM_DEVICE_ADDRESS) == 0) {
123a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            deviceDesc->mAddress = String8((char *)node->value);
124a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
125a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            if (audio_is_input_device(type)) {
126112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                deviceDesc->addAudioProfile(
127112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                        new AudioProfile(gDynamicFormat,
128112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                         inputChannelMasksFromString(node->value),
129112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                         SampleRateVector()));
130a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            } else {
131112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                deviceDesc->addAudioProfile(
132112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                        new AudioProfile(gDynamicFormat,
133112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                         outputChannelMasksFromString(node->value),
134112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                         SampleRateVector()));
135a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            }
136a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        } else if (strcmp(node->name, GAINS_TAG) == 0) {
137a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            loadDeviceDescriptorGains(node, deviceDesc);
138a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        }
139a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        node = node->next;
140a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    }
141a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie
1421d4481fb9cb1ea149f79f2a5d22110af84fbc90bFrançois Gaffie    ALOGV("loadDevice() adding device tag (literal type) %s type %08x address %s",
1431d4481fb9cb1ea149f79f2a5d22110af84fbc90bFrançois Gaffie          deviceDesc->getTagName().string(), type, deviceDesc->mAddress.string());
144a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie
145a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    devices.add(deviceDesc);
146a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    return NO_ERROR;
14756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
14856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
14956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi//static
150112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffiestatus_t ConfigParsingUtils::loadHwModuleProfile(cnode *root, sp<HwModule> &module,
151112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                                 audio_port_role_t role)
15256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
153a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    cnode *node = root->first_child;
154a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie
155112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    sp<IOProfile> profile = new IOProfile(String8(root->name), role);
156112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
157112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    AudioProfileVector audioProfiles;
158112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    SampleRateVector sampleRates;
159112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    ChannelsVector channels;
160112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    FormatVector formats;
161a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie
162a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    while (node) {
163112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        if (strcmp(node->name, FORMATS_TAG) == 0 &&
164112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                strcmp(node->value, DYNAMIC_VALUE_TAG) != 0) {
165112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            formats = formatsFromString(node->value);
166112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        } else if (strcmp(node->name, SAMPLING_RATES_TAG) == 0 &&
167112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                  strcmp(node->value, DYNAMIC_VALUE_TAG) != 0) {
168112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            collectionFromString<SampleRateTraits>(node->value, sampleRates);
169112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        } else if (strcmp(node->name, CHANNELS_TAG) == 0 &&
170112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                   strcmp(node->value, DYNAMIC_VALUE_TAG) != 0) {
171112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            if (role == AUDIO_PORT_ROLE_SINK) {
172112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                channels = inputChannelMasksFromString(node->value);
173112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            } else {
174112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                channels = outputChannelMasksFromString(node->value);
175112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            }
176a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        } else if (strcmp(node->name, DEVICES_TAG) == 0) {
177a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            DeviceVector devices;
178a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            loadDevicesFromTag(node->value, devices, module->getDeclaredDevices());
179a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            profile->setSupportedDevices(devices);
180a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        } else if (strcmp(node->name, FLAGS_TAG) == 0) {
181112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            if (role == AUDIO_PORT_ROLE_SINK) {
182112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                profile->setFlags(InputFlagConverter::maskFromString(node->value));
183112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            } else {
184f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie                profile->setFlags(OutputFlagConverter::maskFromString(node->value));
185112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            }
186a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        } else if (strcmp(node->name, GAINS_TAG) == 0) {
187a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            loadAudioPortGains(node, *profile);
18856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
189a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        node = node->next;
190a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    }
191112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    if (formats.isEmpty()) {
192112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        sp<AudioProfile> profileToAdd = new AudioProfile(gDynamicFormat, channels, sampleRates);
193112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        profileToAdd->setDynamicFormat(true);
194112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        profileToAdd->setDynamicChannels(channels.isEmpty());
195112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        profileToAdd->setDynamicRate(sampleRates.isEmpty());
196112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        audioProfiles.add(profileToAdd);
197a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    } else {
198112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        for (size_t i = 0; i < formats.size(); i++) {
199112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            // For compatibility reason, for each format, creates a profile with the same
200112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            // collection of rate and channels.
201112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            sp<AudioProfile> profileToAdd = new AudioProfile(formats[i], channels, sampleRates);
202112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            profileToAdd->setDynamicFormat(formats[i] == gDynamicFormat);
203112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            profileToAdd->setDynamicChannels(channels.isEmpty());
204112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            profileToAdd->setDynamicRate(sampleRates.isEmpty());
205112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            audioProfiles.add(profileToAdd);
206a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        }
207a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    }
208112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    profile->setAudioProfiles(audioProfiles);
209112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    ALOGW_IF(!profile->hasSupportedDevices(), "load%s() invalid supported devices",
210112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie             role == AUDIO_PORT_ROLE_SINK ? "Input" : "Output");
211112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    if (profile->hasSupportedDevices()) {
212112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        ALOGV("load%s() adding Supported Devices %04x, mFlags %04x",
213112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie              role == AUDIO_PORT_ROLE_SINK ? "Input" : "Output",
214112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie              profile->getSupportedDevicesType(), profile->getFlags());
215112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        return module->addProfile(profile);
216a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    }
217112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    return BAD_VALUE;
21856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
21956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
22053615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie//static
221a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffiestatus_t ConfigParsingUtils::loadHwModule(cnode *root, sp<HwModule> &module,
222a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                                          AudioPolicyConfig &config)
22353615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie{
22453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    status_t status = NAME_NOT_FOUND;
225a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    cnode *node = config_find(root, DEVICES_TAG);
22653615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    if (node != NULL) {
22753615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        node = node->first_child;
228a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        DeviceVector devices;
22953615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        while (node) {
23053615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            ALOGV("loadHwModule() loading device %s", node->name);
231a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            status_t tmpStatus = loadHwModuleDevice(node, devices);
23253615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            if (status == NAME_NOT_FOUND || status == NO_ERROR) {
23353615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie                status = tmpStatus;
23453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            }
23553615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            node = node->next;
23653615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        }
237a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        module->setDeclaredDevices(devices);
23853615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    }
23953615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    node = config_find(root, OUTPUTS_TAG);
24053615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    if (node != NULL) {
24153615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        node = node->first_child;
24253615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        while (node) {
24353615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            ALOGV("loadHwModule() loading output %s", node->name);
244112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            status_t tmpStatus = loadHwModuleProfile(node, module, AUDIO_PORT_ROLE_SOURCE);
24553615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            if (status == NAME_NOT_FOUND || status == NO_ERROR) {
24653615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie                status = tmpStatus;
24753615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            }
24853615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            node = node->next;
24953615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        }
25053615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    }
25153615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    node = config_find(root, INPUTS_TAG);
25253615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    if (node != NULL) {
25353615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        node = node->first_child;
25453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        while (node) {
25553615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            ALOGV("loadHwModule() loading input %s", node->name);
256112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            status_t tmpStatus = loadHwModuleProfile(node, module, AUDIO_PORT_ROLE_SINK);
25753615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            if (status == NAME_NOT_FOUND || status == NO_ERROR) {
25853615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie                status = tmpStatus;
25953615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            }
26053615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            node = node->next;
26153615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        }
26253615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    }
263a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    loadModuleGlobalConfig(root, module, config);
264a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    return status;
26553615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie}
26653615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
26753615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie//static
26853615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffievoid ConfigParsingUtils::loadHwModules(cnode *root, HwModuleCollection &hwModules,
269a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                                       AudioPolicyConfig &config)
27053615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie{
27153615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    cnode *node = config_find(root, AUDIO_HW_MODULE_TAG);
27253615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    if (node == NULL) {
27353615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        return;
27453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    }
27553615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
27653615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    node = node->first_child;
27753615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    while (node) {
27853615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        ALOGV("loadHwModules() loading module %s", node->name);
279a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        sp<HwModule> module = new HwModule(node->name);
280a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        if (loadHwModule(node, module, config) == NO_ERROR) {
281a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            hwModules.add(module);
282a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        }
28353615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        node = node->next;
28453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    }
28553615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie}
28653615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
28753615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie//static
288a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffievoid ConfigParsingUtils::loadDevicesFromTag(const char *tag, DeviceVector &devices,
289a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                                            const DeviceVector &declaredDevices)
290a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie{
291a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    char *tagLiteral = strndup(tag, strlen(tag));
292a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    char *devTag = strtok(tagLiteral, "|");
293a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    while (devTag != NULL) {
294a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        if (strlen(devTag) != 0) {
295a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            audio_devices_t type;
296a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            if (DeviceConverter::fromString(devTag, type)) {
297e0db30868d9734f95a02df516dd0dc6a7226474bEric Laurent                uint32_t inBit = type & AUDIO_DEVICE_BIT_IN;
298e0db30868d9734f95a02df516dd0dc6a7226474bEric Laurent                type &= ~AUDIO_DEVICE_BIT_IN;
299e0db30868d9734f95a02df516dd0dc6a7226474bEric Laurent                while (type) {
300e0db30868d9734f95a02df516dd0dc6a7226474bEric Laurent                  audio_devices_t singleType =
301e0db30868d9734f95a02df516dd0dc6a7226474bEric Laurent                        inBit | (1 << (31 - __builtin_clz(type)));
302e0db30868d9734f95a02df516dd0dc6a7226474bEric Laurent                    type &= ~singleType;
303e0db30868d9734f95a02df516dd0dc6a7226474bEric Laurent                    sp<DeviceDescriptor> dev = new DeviceDescriptor(singleType);
304e0db30868d9734f95a02df516dd0dc6a7226474bEric Laurent                    devices.add(dev);
305e0db30868d9734f95a02df516dd0dc6a7226474bEric Laurent                }
306a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            } else {
307a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                sp<DeviceDescriptor> deviceDesc =
3081d4481fb9cb1ea149f79f2a5d22110af84fbc90bFrançois Gaffie                        declaredDevices.getDeviceFromTagName(String8(devTag));
309a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                if (deviceDesc != 0) {
310a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                    devices.add(deviceDesc);
311a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                }
312a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            }
313a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        }
314a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        devTag = strtok(NULL, "|");
315a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    }
316a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    free(tagLiteral);
317a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie}
318a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie
319a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie//static
320a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffievoid ConfigParsingUtils::loadModuleGlobalConfig(cnode *root, const sp<HwModule> &module,
321a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                                                AudioPolicyConfig &config)
32253615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie{
32353615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    cnode *node = config_find(root, GLOBAL_CONFIG_TAG);
32453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
32553615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    if (node == NULL) {
32653615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        return;
32753615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    }
32853615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    DeviceVector declaredDevices;
32953615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    if (module != NULL) {
330a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        declaredDevices = module->getDeclaredDevices();
33153615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    }
33253615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
33353615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    node = node->first_child;
33453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    while (node) {
33553615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        if (strcmp(ATTACHED_OUTPUT_DEVICES_TAG, node->name) == 0) {
336a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            DeviceVector availableOutputDevices;
337a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            loadDevicesFromTag(node->value, availableOutputDevices, declaredDevices);
33853615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            ALOGV("loadGlobalConfig() Attached Output Devices %08x",
33953615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie                  availableOutputDevices.types());
340a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            config.addAvailableOutputDevices(availableOutputDevices);
34153615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        } else if (strcmp(DEFAULT_OUTPUT_DEVICE_TAG, node->name) == 0) {
342a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            audio_devices_t device = AUDIO_DEVICE_NONE;
343a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            DeviceConverter::fromString(node->value, device);
34453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            if (device != AUDIO_DEVICE_NONE) {
345a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                sp<DeviceDescriptor> defaultOutputDevice = new DeviceDescriptor(device);
346a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                config.setDefaultOutputDevice(defaultOutputDevice);
347a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                ALOGV("loadGlobalConfig() mDefaultOutputDevice %08x", defaultOutputDevice->type());
34853615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            } else {
34953615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie                ALOGW("loadGlobalConfig() default device not specified");
35053615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            }
35153615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        } else if (strcmp(ATTACHED_INPUT_DEVICES_TAG, node->name) == 0) {
352a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            DeviceVector availableInputDevices;
353a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            loadDevicesFromTag(node->value, availableInputDevices, declaredDevices);
35453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            ALOGV("loadGlobalConfig() Available InputDevices %08x", availableInputDevices.types());
355a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            config.addAvailableInputDevices(availableInputDevices);
35653615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        } else if (strcmp(AUDIO_HAL_VERSION_TAG, node->name) == 0) {
35753615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            uint32_t major, minor;
35853615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            sscanf((char *)node->value, "%u.%u", &major, &minor);
359a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            module->setHalVersion(HARDWARE_DEVICE_API_VERSION(major, minor));
36053615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            ALOGV("loadGlobalConfig() mHalVersion = %04x major %u minor %u",
361a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                  module->getHalVersion(), major, minor);
362a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        }
363a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        node = node->next;
364a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    }
365a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie}
366a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie
367a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie//static
368a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffievoid ConfigParsingUtils::loadGlobalConfig(cnode *root, AudioPolicyConfig &config,
369a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                                          const sp<HwModule>& primaryModule)
370a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie{
371a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    cnode *node = config_find(root, GLOBAL_CONFIG_TAG);
372a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie
373a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    if (node == NULL) {
374a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        return;
375a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    }
376a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    node = node->first_child;
377a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    while (node) {
378a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        if (strcmp(SPEAKER_DRC_ENABLED_TAG, node->name) == 0) {
379a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            bool speakerDrcEnabled;
380a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            if (utilities::convertTo<std::string, bool>(node->value, speakerDrcEnabled)) {
381a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                ALOGV("loadGlobalConfig() mSpeakerDrcEnabled = %d", speakerDrcEnabled);
382a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                config.setSpeakerDrcEnabled(speakerDrcEnabled);
383a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            }
38453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        }
38553615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        node = node->next;
38653615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    }
387a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    loadModuleGlobalConfig(root, primaryModule, config);
38853615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie}
38953615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
39053615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie//static
391a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffiestatus_t ConfigParsingUtils::loadConfig(const char *path, AudioPolicyConfig &config)
39253615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie{
39353615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    cnode *root;
39453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    char *data;
39553615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
39653615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    data = (char *)load_file(path, NULL);
39753615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    if (data == NULL) {
39853615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        return -ENODEV;
39953615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    }
40053615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    root = config_node("", "");
40153615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    config_load(root, data);
40253615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
403a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    HwModuleCollection hwModules;
404a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    loadHwModules(root, hwModules, config);
405a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie
406a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    // legacy audio_policy.conf files have one global_configuration section, attached to primary.
407a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    loadGlobalConfig(root, config, hwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY));
408a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie
409a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    config.setHwModules(hwModules);
410a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie
41153615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    config_free(root);
41253615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    free(root);
41353615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    free(data);
41453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
41553615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    ALOGI("loadAudioPolicyConfig() loaded %s\n", path);
41653615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
41753615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    return NO_ERROR;
41853615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie}
41953615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
42056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}; // namespace android
421