HwModule.cpp revision 53615e29c99c5e9d2ca77aaefd7bf5c770513120
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
28namespace android {
29
30HwModule::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
36HwModule::~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
47status_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, this);
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.loadDevicesFromName((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        mInputProfiles.add(profile);
87        return NO_ERROR;
88    } else {
89        return BAD_VALUE;
90    }
91}
92
93status_t HwModule::loadOutput(cnode *root)
94{
95    cnode *node = root->first_child;
96
97    sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SOURCE, this);
98
99    while (node) {
100        if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
101            profile->loadSamplingRates((char *)node->value);
102        } else if (strcmp(node->name, FORMATS_TAG) == 0) {
103            profile->loadFormats((char *)node->value);
104        } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
105            profile->loadOutChannels((char *)node->value);
106        } else if (strcmp(node->name, DEVICES_TAG) == 0) {
107            profile->mSupportedDevices.loadDevicesFromName((char *)node->value,
108                                                           mDeclaredDevices);
109        } else if (strcmp(node->name, FLAGS_TAG) == 0) {
110            profile->mFlags = ConfigParsingUtils::parseOutputFlagNames((char *)node->value);
111        } else if (strcmp(node->name, GAINS_TAG) == 0) {
112            profile->loadGains(node);
113        }
114        node = node->next;
115    }
116    ALOGW_IF(profile->mSupportedDevices.isEmpty(),
117            "loadOutput() invalid supported devices");
118    ALOGW_IF(profile->mChannelMasks.size() == 0,
119            "loadOutput() invalid supported channel masks");
120    ALOGW_IF(profile->mSamplingRates.size() == 0,
121            "loadOutput() invalid supported sampling rates");
122    ALOGW_IF(profile->mFormats.size() == 0,
123            "loadOutput() invalid supported formats");
124    if (!profile->mSupportedDevices.isEmpty() &&
125            (profile->mChannelMasks.size() != 0) &&
126            (profile->mSamplingRates.size() != 0) &&
127            (profile->mFormats.size() != 0)) {
128
129        ALOGV("loadOutput() adding output Supported Devices %04x, mFlags %04x",
130              profile->mSupportedDevices.types(), profile->mFlags);
131
132        mOutputProfiles.add(profile);
133        return NO_ERROR;
134    } else {
135        return BAD_VALUE;
136    }
137}
138
139status_t HwModule::loadDevice(cnode *root)
140{
141    cnode *node = root->first_child;
142
143    audio_devices_t type = AUDIO_DEVICE_NONE;
144    while (node) {
145        if (strcmp(node->name, DEVICE_TYPE) == 0) {
146            type = ConfigParsingUtils::parseDeviceNames((char *)node->value);
147            break;
148        }
149        node = node->next;
150    }
151    if (type == AUDIO_DEVICE_NONE ||
152            (!audio_is_input_device(type) && !audio_is_output_device(type))) {
153        ALOGW("loadDevice() bad type %08x", type);
154        return BAD_VALUE;
155    }
156    sp<DeviceDescriptor> deviceDesc = new DeviceDescriptor(String8(root->name), type);
157    deviceDesc->mModule = this;
158
159    node = root->first_child;
160    while (node) {
161        if (strcmp(node->name, DEVICE_ADDRESS) == 0) {
162            deviceDesc->mAddress = String8((char *)node->value);
163        } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
164            if (audio_is_input_device(type)) {
165                deviceDesc->loadInChannels((char *)node->value);
166            } else {
167                deviceDesc->loadOutChannels((char *)node->value);
168            }
169        } else if (strcmp(node->name, GAINS_TAG) == 0) {
170            deviceDesc->loadGains(node);
171        }
172        node = node->next;
173    }
174
175    ALOGV("loadDevice() adding device name %s type %08x address %s",
176          deviceDesc->mName.string(), type, deviceDesc->mAddress.string());
177
178    mDeclaredDevices.add(deviceDesc);
179
180    return NO_ERROR;
181}
182
183status_t HwModule::addOutputProfile(String8 name, const audio_config_t *config,
184                                                  audio_devices_t device, String8 address)
185{
186    sp<IOProfile> profile = new IOProfile(name, AUDIO_PORT_ROLE_SOURCE, this);
187
188    profile->mSamplingRates.add(config->sample_rate);
189    profile->mChannelMasks.add(config->channel_mask);
190    profile->mFormats.add(config->format);
191
192    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(name, device);
193    devDesc->mAddress = address;
194    profile->mSupportedDevices.add(devDesc);
195
196    mOutputProfiles.add(profile);
197
198    return NO_ERROR;
199}
200
201status_t HwModule::removeOutputProfile(String8 name)
202{
203    for (size_t i = 0; i < mOutputProfiles.size(); i++) {
204        if (mOutputProfiles[i]->mName == name) {
205            mOutputProfiles.removeAt(i);
206            break;
207        }
208    }
209
210    return NO_ERROR;
211}
212
213status_t HwModule::addInputProfile(String8 name, const audio_config_t *config,
214                                                  audio_devices_t device, String8 address)
215{
216    sp<IOProfile> profile = new IOProfile(name, AUDIO_PORT_ROLE_SINK, this);
217
218    profile->mSamplingRates.add(config->sample_rate);
219    profile->mChannelMasks.add(config->channel_mask);
220    profile->mFormats.add(config->format);
221
222    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(name, device);
223    devDesc->mAddress = address;
224    profile->mSupportedDevices.add(devDesc);
225
226    ALOGV("addInputProfile() name %s rate %d mask 0x08", name.string(), config->sample_rate, config->channel_mask);
227
228    mInputProfiles.add(profile);
229
230    return NO_ERROR;
231}
232
233status_t HwModule::removeInputProfile(String8 name)
234{
235    for (size_t i = 0; i < mInputProfiles.size(); i++) {
236        if (mInputProfiles[i]->mName == name) {
237            mInputProfiles.removeAt(i);
238            break;
239        }
240    }
241
242    return NO_ERROR;
243}
244
245
246void HwModule::dump(int fd)
247{
248    const size_t SIZE = 256;
249    char buffer[SIZE];
250    String8 result;
251
252    snprintf(buffer, SIZE, "  - name: %s\n", mName);
253    result.append(buffer);
254    snprintf(buffer, SIZE, "  - handle: %d\n", mHandle);
255    result.append(buffer);
256    snprintf(buffer, SIZE, "  - version: %u.%u\n", mHalVersion >> 8, mHalVersion & 0xFF);
257    result.append(buffer);
258    write(fd, result.string(), result.size());
259    if (mOutputProfiles.size()) {
260        write(fd, "  - outputs:\n", strlen("  - outputs:\n"));
261        for (size_t i = 0; i < mOutputProfiles.size(); i++) {
262            snprintf(buffer, SIZE, "    output %zu:\n", i);
263            write(fd, buffer, strlen(buffer));
264            mOutputProfiles[i]->dump(fd);
265        }
266    }
267    if (mInputProfiles.size()) {
268        write(fd, "  - inputs:\n", strlen("  - inputs:\n"));
269        for (size_t i = 0; i < mInputProfiles.size(); i++) {
270            snprintf(buffer, SIZE, "    input %zu:\n", i);
271            write(fd, buffer, strlen(buffer));
272            mInputProfiles[i]->dump(fd);
273        }
274    }
275    if (mDeclaredDevices.size()) {
276        write(fd, "  - devices:\n", strlen("  - devices:\n"));
277        for (size_t i = 0; i < mDeclaredDevices.size(); i++) {
278            mDeclaredDevices[i]->dump(fd, 4, i);
279        }
280    }
281}
282
283sp <HwModule> HwModuleCollection::getModuleFromName(const char *name) const
284{
285    sp <HwModule> module;
286
287    for (size_t i = 0; i < size(); i++)
288    {
289        if (strcmp(itemAt(i)->mName, name) == 0) {
290            return itemAt(i);
291        }
292    }
293    return module;
294}
295
296
297sp <HwModule> HwModuleCollection::getModuleForDevice(audio_devices_t device) const
298{
299    sp <HwModule> module;
300
301    for (size_t i = 0; i < size(); i++) {
302        if (itemAt(i)->mHandle == 0) {
303            continue;
304        }
305        if (audio_is_output_device(device)) {
306            for (size_t j = 0; j < itemAt(i)->mOutputProfiles.size(); j++)
307            {
308                if (itemAt(i)->mOutputProfiles[j]->mSupportedDevices.types() & device) {
309                    return itemAt(i);
310                }
311            }
312        } else {
313            for (size_t j = 0; j < itemAt(i)->mInputProfiles.size(); j++) {
314                if (itemAt(i)->mInputProfiles[j]->mSupportedDevices.types() &
315                        device & ~AUDIO_DEVICE_BIT_IN) {
316                    return itemAt(i);
317                }
318            }
319        }
320    }
321    return module;
322}
323
324sp<DeviceDescriptor>  HwModuleCollection::getDeviceDescriptor(const audio_devices_t device,
325                                                              const char *device_address,
326                                                              const char *device_name) const
327{
328    String8 address = (device_address == NULL) ? String8("") : String8(device_address);
329    // handle legacy remote submix case where the address was not always specified
330    if (device_distinguishes_on_address(device) && (address.length() == 0)) {
331        address = String8("0");
332    }
333
334    for (size_t i = 0; i < size(); i++) {
335        const sp<HwModule> hwModule = itemAt(i);
336        if (hwModule->mHandle == 0) {
337            continue;
338        }
339        DeviceVector deviceList =
340                hwModule->mDeclaredDevices.getDevicesFromTypeAddr(device, address);
341        if (!deviceList.isEmpty()) {
342            return deviceList.itemAt(0);
343        }
344        deviceList = hwModule->mDeclaredDevices.getDevicesFromType(device);
345        if (!deviceList.isEmpty()) {
346            return deviceList.itemAt(0);
347        }
348    }
349
350    sp<DeviceDescriptor> devDesc =
351            new DeviceDescriptor(String8(device_name != NULL ? device_name : ""), device);
352    devDesc->mAddress = address;
353    return devDesc;
354}
355
356status_t HwModuleCollection::dump(int fd) const
357{
358    const size_t SIZE = 256;
359    char buffer[SIZE];
360
361    snprintf(buffer, SIZE, "\nHW Modules dump:\n");
362    write(fd, buffer, strlen(buffer));
363    for (size_t i = 0; i < size(); i++) {
364        snprintf(buffer, SIZE, "- HW Module %zu:\n", i + 1);
365        write(fd, buffer, strlen(buffer));
366        itemAt(i)->dump(fd);
367    }
368    return NO_ERROR;
369}
370
371} //namespace android
372