HwModule.cpp revision 112b0af826aeca45855690b9c105b2cdf9938bbe
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 <hardware/audio.h>
24#include <policy.h>
25
26namespace android {
27
28HwModule::HwModule(const char *name, uint32_t halVersion)
29    : mName(String8(name)),
30      mHandle(0),
31      mHalVersion(halVersion)
32{
33}
34
35HwModule::~HwModule()
36{
37    for (size_t i = 0; i < mOutputProfiles.size(); i++) {
38        mOutputProfiles[i]->clearSupportedDevices();
39    }
40    for (size_t i = 0; i < mInputProfiles.size(); i++) {
41        mInputProfiles[i]->clearSupportedDevices();
42    }
43}
44
45status_t HwModule::addOutputProfile(String8 name, const audio_config_t *config,
46                                    audio_devices_t device, String8 address)
47{
48    sp<IOProfile> profile = new OutputProfile(name);
49
50    profile->addAudioProfile(new AudioProfile(config->format, config->channel_mask,
51                                              config->sample_rate));
52
53    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
54    devDesc->mAddress = address;
55    profile->addSupportedDevice(devDesc);
56
57    return addOutputProfile(profile);
58}
59
60status_t HwModule::addOutputProfile(const sp<IOProfile> &profile)
61{
62    profile->attach(this);
63    mOutputProfiles.add(profile);
64    return NO_ERROR;
65}
66
67status_t HwModule::addInputProfile(const sp<IOProfile> &profile)
68{
69    profile->attach(this);
70    mInputProfiles.add(profile);
71    return NO_ERROR;
72}
73
74status_t HwModule::addProfile(const sp<IOProfile> &profile)
75{
76    switch (profile->getRole()) {
77    case AUDIO_PORT_ROLE_SOURCE:
78        return addOutputProfile(profile);
79    case AUDIO_PORT_ROLE_SINK:
80        return addInputProfile(profile);
81    case AUDIO_PORT_ROLE_NONE:
82        return BAD_VALUE;
83    }
84    return BAD_VALUE;
85}
86
87void HwModule::setProfiles(const IOProfileCollection &profiles)
88{
89    for (size_t i = 0; i < profiles.size(); i++) {
90        addProfile(profiles[i]);
91    }
92}
93
94status_t HwModule::removeOutputProfile(String8 name)
95{
96    for (size_t i = 0; i < mOutputProfiles.size(); i++) {
97        if (mOutputProfiles[i]->getName() == name) {
98            mOutputProfiles.removeAt(i);
99            break;
100        }
101    }
102
103    return NO_ERROR;
104}
105
106status_t HwModule::addInputProfile(String8 name, const audio_config_t *config,
107                                   audio_devices_t device, String8 address)
108{
109    sp<IOProfile> profile = new InputProfile(name);
110    profile->addAudioProfile(new AudioProfile(config->format, config->channel_mask,
111                                              config->sample_rate));
112
113    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
114    devDesc->mAddress = address;
115    profile->addSupportedDevice(devDesc);
116
117    ALOGV("addInputProfile() name %s rate %d mask 0x%08x",
118          name.string(), config->sample_rate, config->channel_mask);
119
120    return addInputProfile(profile);
121}
122
123status_t HwModule::removeInputProfile(String8 name)
124{
125    for (size_t i = 0; i < mInputProfiles.size(); i++) {
126        if (mInputProfiles[i]->getName() == name) {
127            mInputProfiles.removeAt(i);
128            break;
129        }
130    }
131
132    return NO_ERROR;
133}
134
135
136void HwModule::dump(int fd)
137{
138    const size_t SIZE = 256;
139    char buffer[SIZE];
140    String8 result;
141
142    snprintf(buffer, SIZE, "  - name: %s\n", getName());
143    result.append(buffer);
144    snprintf(buffer, SIZE, "  - handle: %d\n", mHandle);
145    result.append(buffer);
146    snprintf(buffer, SIZE, "  - version: %u.%u\n", mHalVersion >> 8, mHalVersion & 0xFF);
147    result.append(buffer);
148    write(fd, result.string(), result.size());
149    if (mOutputProfiles.size()) {
150        write(fd, "  - outputs:\n", strlen("  - outputs:\n"));
151        for (size_t i = 0; i < mOutputProfiles.size(); i++) {
152            snprintf(buffer, SIZE, "    output %zu:\n", i);
153            write(fd, buffer, strlen(buffer));
154            mOutputProfiles[i]->dump(fd);
155        }
156    }
157    if (mInputProfiles.size()) {
158        write(fd, "  - inputs:\n", strlen("  - inputs:\n"));
159        for (size_t i = 0; i < mInputProfiles.size(); i++) {
160            snprintf(buffer, SIZE, "    input %zu:\n", i);
161            write(fd, buffer, strlen(buffer));
162            mInputProfiles[i]->dump(fd);
163        }
164    }
165    mDeclaredDevices.dump(fd, String8("Declared"),  2, true);
166}
167
168sp <HwModule> HwModuleCollection::getModuleFromName(const char *name) const
169{
170    sp <HwModule> module;
171
172    for (size_t i = 0; i < size(); i++)
173    {
174        if (strcmp(itemAt(i)->getName(), name) == 0) {
175            return itemAt(i);
176        }
177    }
178    return module;
179}
180
181
182sp <HwModule> HwModuleCollection::getModuleForDevice(audio_devices_t device) const
183{
184    sp <HwModule> module;
185
186    for (size_t i = 0; i < size(); i++) {
187        if (itemAt(i)->getHandle() == 0) {
188            continue;
189        }
190        if (audio_is_output_device(device)) {
191            for (size_t j = 0; j < itemAt(i)->mOutputProfiles.size(); j++)
192            {
193                if (itemAt(i)->mOutputProfiles[j]->supportDevice(device)) {
194                    return itemAt(i);
195                }
196            }
197        } else {
198            for (size_t j = 0; j < itemAt(i)->mInputProfiles.size(); j++) {
199                if (itemAt(i)->mInputProfiles[j]->supportDevice(device)) {
200                    return itemAt(i);
201                }
202            }
203        }
204    }
205    return module;
206}
207
208sp<DeviceDescriptor>  HwModuleCollection::getDeviceDescriptor(const audio_devices_t device,
209                                                              const char *device_address,
210                                                              const char *device_name) const
211{
212    String8 address = (device_address == NULL) ? String8("") : String8(device_address);
213    // handle legacy remote submix case where the address was not always specified
214    if (device_distinguishes_on_address(device) && (address.length() == 0)) {
215        address = String8("0");
216    }
217
218    for (size_t i = 0; i < size(); i++) {
219        const sp<HwModule> hwModule = itemAt(i);
220        if (hwModule->mHandle == 0) {
221            continue;
222        }
223        DeviceVector deviceList =
224                hwModule->getDeclaredDevices().getDevicesFromTypeAddr(device, address);
225        if (!deviceList.isEmpty()) {
226            return deviceList.itemAt(0);
227        }
228        deviceList = hwModule->getDeclaredDevices().getDevicesFromType(device);
229        if (!deviceList.isEmpty()) {
230            return deviceList.itemAt(0);
231        }
232    }
233
234    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
235    devDesc->setName(String8(device_name));
236    devDesc->mAddress = address;
237    return devDesc;
238}
239
240status_t HwModuleCollection::dump(int fd) const
241{
242    const size_t SIZE = 256;
243    char buffer[SIZE];
244
245    snprintf(buffer, SIZE, "\nHW Modules dump:\n");
246    write(fd, buffer, strlen(buffer));
247    for (size_t i = 0; i < size(); i++) {
248        snprintf(buffer, SIZE, "- HW Module %zu:\n", i + 1);
249        write(fd, buffer, strlen(buffer));
250        itemAt(i)->dump(fd);
251    }
252    return NO_ERROR;
253}
254
255} //namespace android
256