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