blob: a04bdc8fc5d263e3bd924f6585584d8b973fd872 [file] [log] [blame]
Jean-Michel Trivi56ec4ff2015-01-23 16:45:18 -08001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "APM::HwModule"
18//#define LOG_NDEBUG 0
19
20#include "AudioPolicyManager.h"
21#include "audio_policy_conf.h"
22#include <hardware/audio.h>
23
24namespace android {
25
26HwModule::HwModule(const char *name)
27 : mName(strndup(name, AUDIO_HARDWARE_MODULE_ID_MAX_LEN)),
28 mHalVersion(AUDIO_DEVICE_API_VERSION_MIN), mHandle(0)
29{
30}
31
32HwModule::~HwModule()
33{
34 for (size_t i = 0; i < mOutputProfiles.size(); i++) {
35 mOutputProfiles[i]->mSupportedDevices.clear();
36 }
37 for (size_t i = 0; i < mInputProfiles.size(); i++) {
38 mInputProfiles[i]->mSupportedDevices.clear();
39 }
40 free((void *)mName);
41}
42
43status_t HwModule::loadInput(cnode *root)
44{
45 cnode *node = root->first_child;
46
47 sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SINK, this);
48
49 while (node) {
50 if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
51 profile->loadSamplingRates((char *)node->value);
52 } else if (strcmp(node->name, FORMATS_TAG) == 0) {
53 profile->loadFormats((char *)node->value);
54 } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
55 profile->loadInChannels((char *)node->value);
56 } else if (strcmp(node->name, DEVICES_TAG) == 0) {
57 profile->mSupportedDevices.loadDevicesFromName((char *)node->value,
58 mDeclaredDevices);
59 } else if (strcmp(node->name, FLAGS_TAG) == 0) {
60 profile->mFlags = ConfigParsingUtils::parseInputFlagNames((char *)node->value);
61 } else if (strcmp(node->name, GAINS_TAG) == 0) {
62 profile->loadGains(node);
63 }
64 node = node->next;
65 }
66 ALOGW_IF(profile->mSupportedDevices.isEmpty(),
67 "loadInput() invalid supported devices");
68 ALOGW_IF(profile->mChannelMasks.size() == 0,
69 "loadInput() invalid supported channel masks");
70 ALOGW_IF(profile->mSamplingRates.size() == 0,
71 "loadInput() invalid supported sampling rates");
72 ALOGW_IF(profile->mFormats.size() == 0,
73 "loadInput() invalid supported formats");
74 if (!profile->mSupportedDevices.isEmpty() &&
75 (profile->mChannelMasks.size() != 0) &&
76 (profile->mSamplingRates.size() != 0) &&
77 (profile->mFormats.size() != 0)) {
78
79 ALOGV("loadInput() adding input Supported Devices %04x",
80 profile->mSupportedDevices.types());
81
82 mInputProfiles.add(profile);
83 return NO_ERROR;
84 } else {
85 return BAD_VALUE;
86 }
87}
88
89status_t HwModule::loadOutput(cnode *root)
90{
91 cnode *node = root->first_child;
92
93 sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SOURCE, this);
94
95 while (node) {
96 if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
97 profile->loadSamplingRates((char *)node->value);
98 } else if (strcmp(node->name, FORMATS_TAG) == 0) {
99 profile->loadFormats((char *)node->value);
100 } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
101 profile->loadOutChannels((char *)node->value);
102 } else if (strcmp(node->name, DEVICES_TAG) == 0) {
103 profile->mSupportedDevices.loadDevicesFromName((char *)node->value,
104 mDeclaredDevices);
105 } else if (strcmp(node->name, FLAGS_TAG) == 0) {
106 profile->mFlags = ConfigParsingUtils::parseOutputFlagNames((char *)node->value);
107 } else if (strcmp(node->name, GAINS_TAG) == 0) {
108 profile->loadGains(node);
109 }
110 node = node->next;
111 }
112 ALOGW_IF(profile->mSupportedDevices.isEmpty(),
113 "loadOutput() invalid supported devices");
114 ALOGW_IF(profile->mChannelMasks.size() == 0,
115 "loadOutput() invalid supported channel masks");
116 ALOGW_IF(profile->mSamplingRates.size() == 0,
117 "loadOutput() invalid supported sampling rates");
118 ALOGW_IF(profile->mFormats.size() == 0,
119 "loadOutput() invalid supported formats");
120 if (!profile->mSupportedDevices.isEmpty() &&
121 (profile->mChannelMasks.size() != 0) &&
122 (profile->mSamplingRates.size() != 0) &&
123 (profile->mFormats.size() != 0)) {
124
125 ALOGV("loadOutput() adding output Supported Devices %04x, mFlags %04x",
126 profile->mSupportedDevices.types(), profile->mFlags);
127
128 mOutputProfiles.add(profile);
129 return NO_ERROR;
130 } else {
131 return BAD_VALUE;
132 }
133}
134
135status_t HwModule::loadDevice(cnode *root)
136{
137 cnode *node = root->first_child;
138
139 audio_devices_t type = AUDIO_DEVICE_NONE;
140 while (node) {
141 if (strcmp(node->name, DEVICE_TYPE) == 0) {
142 type = ConfigParsingUtils::parseDeviceNames((char *)node->value);
143 break;
144 }
145 node = node->next;
146 }
147 if (type == AUDIO_DEVICE_NONE ||
148 (!audio_is_input_device(type) && !audio_is_output_device(type))) {
149 ALOGW("loadDevice() bad type %08x", type);
150 return BAD_VALUE;
151 }
152 sp<DeviceDescriptor> deviceDesc = new DeviceDescriptor(String8(root->name), type);
153 deviceDesc->mModule = this;
154
155 node = root->first_child;
156 while (node) {
157 if (strcmp(node->name, DEVICE_ADDRESS) == 0) {
158 deviceDesc->mAddress = String8((char *)node->value);
159 } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
160 if (audio_is_input_device(type)) {
161 deviceDesc->loadInChannels((char *)node->value);
162 } else {
163 deviceDesc->loadOutChannels((char *)node->value);
164 }
165 } else if (strcmp(node->name, GAINS_TAG) == 0) {
166 deviceDesc->loadGains(node);
167 }
168 node = node->next;
169 }
170
171 ALOGV("loadDevice() adding device name %s type %08x address %s",
172 deviceDesc->mName.string(), type, deviceDesc->mAddress.string());
173
174 mDeclaredDevices.add(deviceDesc);
175
176 return NO_ERROR;
177}
178
179status_t HwModule::addOutputProfile(String8 name, const audio_config_t *config,
180 audio_devices_t device, String8 address)
181{
182 sp<IOProfile> profile = new IOProfile(name, AUDIO_PORT_ROLE_SOURCE, this);
183
184 profile->mSamplingRates.add(config->sample_rate);
185 profile->mChannelMasks.add(config->channel_mask);
186 profile->mFormats.add(config->format);
187
188 sp<DeviceDescriptor> devDesc = new DeviceDescriptor(name, device);
189 devDesc->mAddress = address;
190 profile->mSupportedDevices.add(devDesc);
191
192 mOutputProfiles.add(profile);
193
194 return NO_ERROR;
195}
196
197status_t HwModule::removeOutputProfile(String8 name)
198{
199 for (size_t i = 0; i < mOutputProfiles.size(); i++) {
200 if (mOutputProfiles[i]->mName == name) {
201 mOutputProfiles.removeAt(i);
202 break;
203 }
204 }
205
206 return NO_ERROR;
207}
208
209status_t HwModule::addInputProfile(String8 name, const audio_config_t *config,
210 audio_devices_t device, String8 address)
211{
212 sp<IOProfile> profile = new IOProfile(name, AUDIO_PORT_ROLE_SINK, this);
213
214 profile->mSamplingRates.add(config->sample_rate);
215 profile->mChannelMasks.add(config->channel_mask);
216 profile->mFormats.add(config->format);
217
218 sp<DeviceDescriptor> devDesc = new DeviceDescriptor(name, device);
219 devDesc->mAddress = address;
220 profile->mSupportedDevices.add(devDesc);
221
222 ALOGV("addInputProfile() name %s rate %d mask 0x08", name.string(), config->sample_rate, config->channel_mask);
223
224 mInputProfiles.add(profile);
225
226 return NO_ERROR;
227}
228
229status_t HwModule::removeInputProfile(String8 name)
230{
231 for (size_t i = 0; i < mInputProfiles.size(); i++) {
232 if (mInputProfiles[i]->mName == name) {
233 mInputProfiles.removeAt(i);
234 break;
235 }
236 }
237
238 return NO_ERROR;
239}
240
241
242void HwModule::dump(int fd)
243{
244 const size_t SIZE = 256;
245 char buffer[SIZE];
246 String8 result;
247
248 snprintf(buffer, SIZE, " - name: %s\n", mName);
249 result.append(buffer);
250 snprintf(buffer, SIZE, " - handle: %d\n", mHandle);
251 result.append(buffer);
252 snprintf(buffer, SIZE, " - version: %u.%u\n", mHalVersion >> 8, mHalVersion & 0xFF);
253 result.append(buffer);
254 write(fd, result.string(), result.size());
255 if (mOutputProfiles.size()) {
256 write(fd, " - outputs:\n", strlen(" - outputs:\n"));
257 for (size_t i = 0; i < mOutputProfiles.size(); i++) {
258 snprintf(buffer, SIZE, " output %zu:\n", i);
259 write(fd, buffer, strlen(buffer));
260 mOutputProfiles[i]->dump(fd);
261 }
262 }
263 if (mInputProfiles.size()) {
264 write(fd, " - inputs:\n", strlen(" - inputs:\n"));
265 for (size_t i = 0; i < mInputProfiles.size(); i++) {
266 snprintf(buffer, SIZE, " input %zu:\n", i);
267 write(fd, buffer, strlen(buffer));
268 mInputProfiles[i]->dump(fd);
269 }
270 }
271 if (mDeclaredDevices.size()) {
272 write(fd, " - devices:\n", strlen(" - devices:\n"));
273 for (size_t i = 0; i < mDeclaredDevices.size(); i++) {
274 mDeclaredDevices[i]->dump(fd, 4, i);
275 }
276 }
277}
278
279} //namespace android