1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "APM::HwModule"
18 //#define LOG_NDEBUG 0
19 
20 #include "HwModule.h"
21 #include "IOProfile.h"
22 #include "AudioGain.h"
23 #include "ConfigParsingUtils.h"
24 #include "audio_policy_conf.h"
25 #include <hardware/audio.h>
26 #include <policy.h>
27 
28 namespace android {
29 
HwModule(const char * name)30 HwModule::HwModule(const char *name)
31     : mName(strndup(name, AUDIO_HARDWARE_MODULE_ID_MAX_LEN)),
32       mHalVersion(AUDIO_DEVICE_API_VERSION_MIN), mHandle(0)
33 {
34 }
35 
~HwModule()36 HwModule::~HwModule()
37 {
38     for (size_t i = 0; i < mOutputProfiles.size(); i++) {
39         mOutputProfiles[i]->mSupportedDevices.clear();
40     }
41     for (size_t i = 0; i < mInputProfiles.size(); i++) {
42         mInputProfiles[i]->mSupportedDevices.clear();
43     }
44     free((void *)mName);
45 }
46 
loadInput(cnode * root)47 status_t HwModule::loadInput(cnode *root)
48 {
49     cnode *node = root->first_child;
50 
51     sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SINK);
52 
53     while (node) {
54         if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
55             profile->loadSamplingRates((char *)node->value);
56         } else if (strcmp(node->name, FORMATS_TAG) == 0) {
57             profile->loadFormats((char *)node->value);
58         } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
59             profile->loadInChannels((char *)node->value);
60         } else if (strcmp(node->name, DEVICES_TAG) == 0) {
61             profile->mSupportedDevices.loadDevicesFromTag((char *)node->value,
62                                                            mDeclaredDevices);
63         } else if (strcmp(node->name, FLAGS_TAG) == 0) {
64             profile->mFlags = ConfigParsingUtils::parseInputFlagNames((char *)node->value);
65         } else if (strcmp(node->name, GAINS_TAG) == 0) {
66             profile->loadGains(node);
67         }
68         node = node->next;
69     }
70     ALOGW_IF(profile->mSupportedDevices.isEmpty(),
71             "loadInput() invalid supported devices");
72     ALOGW_IF(profile->mChannelMasks.size() == 0,
73             "loadInput() invalid supported channel masks");
74     ALOGW_IF(profile->mSamplingRates.size() == 0,
75             "loadInput() invalid supported sampling rates");
76     ALOGW_IF(profile->mFormats.size() == 0,
77             "loadInput() invalid supported formats");
78     if (!profile->mSupportedDevices.isEmpty() &&
79             (profile->mChannelMasks.size() != 0) &&
80             (profile->mSamplingRates.size() != 0) &&
81             (profile->mFormats.size() != 0)) {
82 
83         ALOGV("loadInput() adding input Supported Devices %04x",
84               profile->mSupportedDevices.types());
85 
86         profile->attach(this);
87         mInputProfiles.add(profile);
88         return NO_ERROR;
89     } else {
90         return BAD_VALUE;
91     }
92 }
93 
loadOutput(cnode * root)94 status_t HwModule::loadOutput(cnode *root)
95 {
96     cnode *node = root->first_child;
97 
98     sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SOURCE);
99 
100     while (node) {
101         if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
102             profile->loadSamplingRates((char *)node->value);
103         } else if (strcmp(node->name, FORMATS_TAG) == 0) {
104             profile->loadFormats((char *)node->value);
105         } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
106             profile->loadOutChannels((char *)node->value);
107         } else if (strcmp(node->name, DEVICES_TAG) == 0) {
108             profile->mSupportedDevices.loadDevicesFromTag((char *)node->value,
109                                                            mDeclaredDevices);
110         } else if (strcmp(node->name, FLAGS_TAG) == 0) {
111             profile->mFlags = ConfigParsingUtils::parseOutputFlagNames((char *)node->value);
112         } else if (strcmp(node->name, GAINS_TAG) == 0) {
113             profile->loadGains(node);
114         }
115         node = node->next;
116     }
117     ALOGW_IF(profile->mSupportedDevices.isEmpty(),
118             "loadOutput() invalid supported devices");
119     ALOGW_IF(profile->mChannelMasks.size() == 0,
120             "loadOutput() invalid supported channel masks");
121     ALOGW_IF(profile->mSamplingRates.size() == 0,
122             "loadOutput() invalid supported sampling rates");
123     ALOGW_IF(profile->mFormats.size() == 0,
124             "loadOutput() invalid supported formats");
125     if (!profile->mSupportedDevices.isEmpty() &&
126             (profile->mChannelMasks.size() != 0) &&
127             (profile->mSamplingRates.size() != 0) &&
128             (profile->mFormats.size() != 0)) {
129 
130         ALOGV("loadOutput() adding output Supported Devices %04x, mFlags %04x",
131               profile->mSupportedDevices.types(), profile->mFlags);
132         profile->attach(this);
133         mOutputProfiles.add(profile);
134         return NO_ERROR;
135     } else {
136         return BAD_VALUE;
137     }
138 }
139 
loadDevice(cnode * root)140 status_t HwModule::loadDevice(cnode *root)
141 {
142     cnode *node = root->first_child;
143 
144     audio_devices_t type = AUDIO_DEVICE_NONE;
145     while (node) {
146         if (strcmp(node->name, APM_DEVICE_TYPE) == 0) {
147             type = ConfigParsingUtils::parseDeviceNames((char *)node->value);
148             break;
149         }
150         node = node->next;
151     }
152     if (type == AUDIO_DEVICE_NONE ||
153             (!audio_is_input_device(type) && !audio_is_output_device(type))) {
154         ALOGW("loadDevice() bad type %08x", type);
155         return BAD_VALUE;
156     }
157     sp<DeviceDescriptor> deviceDesc = new DeviceDescriptor(type);
158     deviceDesc->mTag = String8(root->name);
159 
160     node = root->first_child;
161     while (node) {
162         if (strcmp(node->name, APM_DEVICE_ADDRESS) == 0) {
163             deviceDesc->mAddress = String8((char *)node->value);
164         } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
165             if (audio_is_input_device(type)) {
166                 deviceDesc->loadInChannels((char *)node->value);
167             } else {
168                 deviceDesc->loadOutChannels((char *)node->value);
169             }
170         } else if (strcmp(node->name, GAINS_TAG) == 0) {
171             deviceDesc->loadGains(node);
172         }
173         node = node->next;
174     }
175 
176     ALOGV("loadDevice() adding device tag %s type %08x address %s",
177           deviceDesc->mTag.string(), type, deviceDesc->mAddress.string());
178 
179     mDeclaredDevices.add(deviceDesc);
180 
181     return NO_ERROR;
182 }
183 
addOutputProfile(String8 name,const audio_config_t * config,audio_devices_t device,String8 address)184 status_t HwModule::addOutputProfile(String8 name, const audio_config_t *config,
185                                                   audio_devices_t device, String8 address)
186 {
187     sp<IOProfile> profile = new IOProfile(name, AUDIO_PORT_ROLE_SOURCE);
188 
189     profile->mSamplingRates.add(config->sample_rate);
190     profile->mChannelMasks.add(config->channel_mask);
191     profile->mFormats.add(config->format);
192 
193     sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
194     devDesc->mAddress = address;
195     profile->mSupportedDevices.add(devDesc);
196 
197     profile->attach(this);
198     mOutputProfiles.add(profile);
199 
200     return NO_ERROR;
201 }
202 
removeOutputProfile(String8 name)203 status_t HwModule::removeOutputProfile(String8 name)
204 {
205     for (size_t i = 0; i < mOutputProfiles.size(); i++) {
206         if (mOutputProfiles[i]->mName == name) {
207             mOutputProfiles.removeAt(i);
208             break;
209         }
210     }
211 
212     return NO_ERROR;
213 }
214 
addInputProfile(String8 name,const audio_config_t * config,audio_devices_t device,String8 address)215 status_t HwModule::addInputProfile(String8 name, const audio_config_t *config,
216                                                   audio_devices_t device, String8 address)
217 {
218     sp<IOProfile> profile = new IOProfile(name, AUDIO_PORT_ROLE_SINK);
219 
220     profile->mSamplingRates.add(config->sample_rate);
221     profile->mChannelMasks.add(config->channel_mask);
222     profile->mFormats.add(config->format);
223 
224     sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
225     devDesc->mAddress = address;
226     profile->mSupportedDevices.add(devDesc);
227 
228     ALOGV("addInputProfile() name %s rate %d mask 0x08", name.string(), config->sample_rate, config->channel_mask);
229 
230     profile->attach(this);
231     mInputProfiles.add(profile);
232 
233     return NO_ERROR;
234 }
235 
removeInputProfile(String8 name)236 status_t HwModule::removeInputProfile(String8 name)
237 {
238     for (size_t i = 0; i < mInputProfiles.size(); i++) {
239         if (mInputProfiles[i]->mName == name) {
240             mInputProfiles.removeAt(i);
241             break;
242         }
243     }
244 
245     return NO_ERROR;
246 }
247 
248 
dump(int fd)249 void HwModule::dump(int fd)
250 {
251     const size_t SIZE = 256;
252     char buffer[SIZE];
253     String8 result;
254 
255     snprintf(buffer, SIZE, "  - name: %s\n", mName);
256     result.append(buffer);
257     snprintf(buffer, SIZE, "  - handle: %d\n", mHandle);
258     result.append(buffer);
259     snprintf(buffer, SIZE, "  - version: %u.%u\n", mHalVersion >> 8, mHalVersion & 0xFF);
260     result.append(buffer);
261     write(fd, result.string(), result.size());
262     if (mOutputProfiles.size()) {
263         write(fd, "  - outputs:\n", strlen("  - outputs:\n"));
264         for (size_t i = 0; i < mOutputProfiles.size(); i++) {
265             snprintf(buffer, SIZE, "    output %zu:\n", i);
266             write(fd, buffer, strlen(buffer));
267             mOutputProfiles[i]->dump(fd);
268         }
269     }
270     if (mInputProfiles.size()) {
271         write(fd, "  - inputs:\n", strlen("  - inputs:\n"));
272         for (size_t i = 0; i < mInputProfiles.size(); i++) {
273             snprintf(buffer, SIZE, "    input %zu:\n", i);
274             write(fd, buffer, strlen(buffer));
275             mInputProfiles[i]->dump(fd);
276         }
277     }
278     if (mDeclaredDevices.size()) {
279         write(fd, "  - devices:\n", strlen("  - devices:\n"));
280         for (size_t i = 0; i < mDeclaredDevices.size(); i++) {
281             mDeclaredDevices[i]->dump(fd, 4, i);
282         }
283     }
284 }
285 
getModuleFromName(const char * name) const286 sp <HwModule> HwModuleCollection::getModuleFromName(const char *name) const
287 {
288     sp <HwModule> module;
289 
290     for (size_t i = 0; i < size(); i++)
291     {
292         if (strcmp(itemAt(i)->mName, name) == 0) {
293             return itemAt(i);
294         }
295     }
296     return module;
297 }
298 
299 
getModuleForDevice(audio_devices_t device) const300 sp <HwModule> HwModuleCollection::getModuleForDevice(audio_devices_t device) const
301 {
302     sp <HwModule> module;
303 
304     for (size_t i = 0; i < size(); i++) {
305         if (itemAt(i)->mHandle == 0) {
306             continue;
307         }
308         if (audio_is_output_device(device)) {
309             for (size_t j = 0; j < itemAt(i)->mOutputProfiles.size(); j++)
310             {
311                 if (itemAt(i)->mOutputProfiles[j]->mSupportedDevices.types() & device) {
312                     return itemAt(i);
313                 }
314             }
315         } else {
316             for (size_t j = 0; j < itemAt(i)->mInputProfiles.size(); j++) {
317                 if (itemAt(i)->mInputProfiles[j]->mSupportedDevices.types() &
318                         device & ~AUDIO_DEVICE_BIT_IN) {
319                     return itemAt(i);
320                 }
321             }
322         }
323     }
324     return module;
325 }
326 
getDeviceDescriptor(const audio_devices_t device,const char * device_address,const char * device_name) const327 sp<DeviceDescriptor>  HwModuleCollection::getDeviceDescriptor(const audio_devices_t device,
328                                                               const char *device_address,
329                                                               const char *device_name) const
330 {
331     String8 address = (device_address == NULL) ? String8("") : String8(device_address);
332     // handle legacy remote submix case where the address was not always specified
333     if (device_distinguishes_on_address(device) && (address.length() == 0)) {
334         address = String8("0");
335     }
336 
337     for (size_t i = 0; i < size(); i++) {
338         const sp<HwModule> hwModule = itemAt(i);
339         if (hwModule->mHandle == 0) {
340             continue;
341         }
342         DeviceVector deviceList =
343                 hwModule->mDeclaredDevices.getDevicesFromTypeAddr(device, address);
344         if (!deviceList.isEmpty()) {
345             return deviceList.itemAt(0);
346         }
347         deviceList = hwModule->mDeclaredDevices.getDevicesFromType(device);
348         if (!deviceList.isEmpty()) {
349             return deviceList.itemAt(0);
350         }
351     }
352 
353     sp<DeviceDescriptor> devDesc =
354             new DeviceDescriptor(device);
355     devDesc->mName = device_name;
356     devDesc->mAddress = address;
357     return devDesc;
358 }
359 
dump(int fd) const360 status_t HwModuleCollection::dump(int fd) const
361 {
362     const size_t SIZE = 256;
363     char buffer[SIZE];
364 
365     snprintf(buffer, SIZE, "\nHW Modules dump:\n");
366     write(fd, buffer, strlen(buffer));
367     for (size_t i = 0; i < size(); i++) {
368         snprintf(buffer, SIZE, "- HW Module %zu:\n", i + 1);
369         write(fd, buffer, strlen(buffer));
370         itemAt(i)->dump(fd);
371     }
372     return NO_ERROR;
373 }
374 
375 } //namespace android
376