blob: 13c8bbc2e56cca1dba4157a3d2855cd242eb6d9c [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::Devices"
18//#define LOG_NDEBUG 0
19
20#include "AudioPolicyManager.h"
21
22namespace android {
23
24String8 DeviceDescriptor::emptyNameStr = String8("");
25
26DeviceDescriptor::DeviceDescriptor(const String8& name, audio_devices_t type) :
27 AudioPort(name, AUDIO_PORT_TYPE_DEVICE,
28 audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
29 AUDIO_PORT_ROLE_SOURCE,
30 NULL),
31 mDeviceType(type), mAddress("")
32{
33
34}
35
36bool DeviceDescriptor::equals(const sp<DeviceDescriptor>& other) const
37{
38 // Devices are considered equal if they:
39 // - are of the same type (a device type cannot be AUDIO_DEVICE_NONE)
40 // - have the same address or one device does not specify the address
41 // - have the same channel mask or one device does not specify the channel mask
42 return (mDeviceType == other->mDeviceType) &&
43 (mAddress == "" || other->mAddress == "" || mAddress == other->mAddress) &&
44 (mChannelMask == 0 || other->mChannelMask == 0 ||
45 mChannelMask == other->mChannelMask);
46}
47
48void DeviceDescriptor::loadGains(cnode *root)
49{
50 AudioPort::loadGains(root);
51 if (mGains.size() > 0) {
52 mGains[0]->getDefaultConfig(&mGain);
53 }
54}
55
56void DeviceVector::refreshTypes()
57{
58 mDeviceTypes = AUDIO_DEVICE_NONE;
59 for(size_t i = 0; i < size(); i++) {
60 mDeviceTypes |= itemAt(i)->mDeviceType;
61 }
62 ALOGV("DeviceVector::refreshTypes() mDeviceTypes %08x", mDeviceTypes);
63}
64
65ssize_t DeviceVector::indexOf(const sp<DeviceDescriptor>& item) const
66{
67 for(size_t i = 0; i < size(); i++) {
68 if (item->equals(itemAt(i))) {
69 return i;
70 }
71 }
72 return -1;
73}
74
75ssize_t DeviceVector::add(const sp<DeviceDescriptor>& item)
76{
77 ssize_t ret = indexOf(item);
78
79 if (ret < 0) {
80 ret = SortedVector::add(item);
81 if (ret >= 0) {
82 refreshTypes();
83 }
84 } else {
85 ALOGW("DeviceVector::add device %08x already in", item->mDeviceType);
86 ret = -1;
87 }
88 return ret;
89}
90
91ssize_t DeviceVector::remove(const sp<DeviceDescriptor>& item)
92{
93 size_t i;
94 ssize_t ret = indexOf(item);
95
96 if (ret < 0) {
97 ALOGW("DeviceVector::remove device %08x not in", item->mDeviceType);
98 } else {
99 ret = SortedVector::removeAt(ret);
100 if (ret >= 0) {
101 refreshTypes();
102 }
103 }
104 return ret;
105}
106
107void DeviceVector::loadDevicesFromType(audio_devices_t types)
108{
109 DeviceVector deviceList;
110
111 uint32_t role_bit = AUDIO_DEVICE_BIT_IN & types;
112 types &= ~role_bit;
113
114 while (types) {
115 uint32_t i = 31 - __builtin_clz(types);
116 uint32_t type = 1 << i;
117 types &= ~type;
118 add(new DeviceDescriptor(String8("device_type"), type | role_bit));
119 }
120}
121
122void DeviceVector::loadDevicesFromName(char *name,
123 const DeviceVector& declaredDevices)
124{
125 char *devName = strtok(name, "|");
126 while (devName != NULL) {
127 if (strlen(devName) != 0) {
128 audio_devices_t type = ConfigParsingUtils::stringToEnum(sDeviceNameToEnumTable,
129 ARRAY_SIZE(sDeviceNameToEnumTable),
130 devName);
131 if (type != AUDIO_DEVICE_NONE) {
132 sp<DeviceDescriptor> dev = new DeviceDescriptor(String8(name), type);
133 if (type == AUDIO_DEVICE_IN_REMOTE_SUBMIX ||
134 type == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ) {
135 dev->mAddress = String8("0");
136 }
137 add(dev);
138 } else {
139 sp<DeviceDescriptor> deviceDesc =
140 declaredDevices.getDeviceFromName(String8(devName));
141 if (deviceDesc != 0) {
142 add(deviceDesc);
143 }
144 }
145 }
146 devName = strtok(NULL, "|");
147 }
148}
149
150sp<DeviceDescriptor> DeviceVector::getDevice(audio_devices_t type, String8 address) const
151{
152 sp<DeviceDescriptor> device;
153 for (size_t i = 0; i < size(); i++) {
154 if (itemAt(i)->mDeviceType == type) {
155 if (address == "" || itemAt(i)->mAddress == address) {
156 device = itemAt(i);
157 if (itemAt(i)->mAddress == address) {
158 break;
159 }
160 }
161 }
162 }
163 ALOGV("DeviceVector::getDevice() for type %08x address %s found %p",
164 type, address.string(), device.get());
165 return device;
166}
167
168sp<DeviceDescriptor> DeviceVector::getDeviceFromId(audio_port_handle_t id) const
169{
170 sp<DeviceDescriptor> device;
171 for (size_t i = 0; i < size(); i++) {
172 if (itemAt(i)->getHandle() == id) {
173 device = itemAt(i);
174 break;
175 }
176 }
177 return device;
178}
179
180DeviceVector DeviceVector::getDevicesFromType(audio_devices_t type) const
181{
182 DeviceVector devices;
183 for (size_t i = 0; (i < size()) && (type != AUDIO_DEVICE_NONE); i++) {
184 if (itemAt(i)->mDeviceType & type & ~AUDIO_DEVICE_BIT_IN) {
185 devices.add(itemAt(i));
186 type &= ~itemAt(i)->mDeviceType;
187 ALOGV("DeviceVector::getDevicesFromType() for type %x found %p",
188 itemAt(i)->mDeviceType, itemAt(i).get());
189 }
190 }
191 return devices;
192}
193
194DeviceVector DeviceVector::getDevicesFromTypeAddr(
195 audio_devices_t type, String8 address) const
196{
197 DeviceVector devices;
198 for (size_t i = 0; i < size(); i++) {
199 if (itemAt(i)->mDeviceType == type) {
200 if (itemAt(i)->mAddress == address) {
201 devices.add(itemAt(i));
202 }
203 }
204 }
205 return devices;
206}
207
208sp<DeviceDescriptor> DeviceVector::getDeviceFromName(const String8& name) const
209{
210 sp<DeviceDescriptor> device;
211 for (size_t i = 0; i < size(); i++) {
212 if (itemAt(i)->mName == name) {
213 device = itemAt(i);
214 break;
215 }
216 }
217 return device;
218}
219
220void DeviceDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
221 const struct audio_port_config *srcConfig) const
222{
223 dstConfig->config_mask = AUDIO_PORT_CONFIG_CHANNEL_MASK|AUDIO_PORT_CONFIG_GAIN;
224 if (srcConfig != NULL) {
225 dstConfig->config_mask |= srcConfig->config_mask;
226 }
227
228 AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
229
230 dstConfig->id = mId;
231 dstConfig->role = audio_is_output_device(mDeviceType) ?
232 AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE;
233 dstConfig->type = AUDIO_PORT_TYPE_DEVICE;
234 dstConfig->ext.device.type = mDeviceType;
235
236 //TODO Understand why this test is necessary. i.e. why at boot time does it crash
237 // without the test?
238 // This has been demonstrated to NOT be true (at start up)
239 // ALOG_ASSERT(mModule != NULL);
240 dstConfig->ext.device.hw_module = mModule != NULL ? mModule->mHandle : NULL;
241 strncpy(dstConfig->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN);
242}
243
244void DeviceDescriptor::toAudioPort(struct audio_port *port) const
245{
246 ALOGV("DeviceDescriptor::toAudioPort() handle %d type %x", mId, mDeviceType);
247 AudioPort::toAudioPort(port);
248 port->id = mId;
249 toAudioPortConfig(&port->active_config);
250 port->ext.device.type = mDeviceType;
251 port->ext.device.hw_module = mModule->mHandle;
252 strncpy(port->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN);
253}
254
255status_t DeviceDescriptor::dump(int fd, int spaces, int index) const
256{
257 const size_t SIZE = 256;
258 char buffer[SIZE];
259 String8 result;
260
261 snprintf(buffer, SIZE, "%*sDevice %d:\n", spaces, "", index+1);
262 result.append(buffer);
263 if (mId != 0) {
264 snprintf(buffer, SIZE, "%*s- id: %2d\n", spaces, "", mId);
265 result.append(buffer);
266 }
267 snprintf(buffer, SIZE, "%*s- type: %-48s\n", spaces, "",
268 ConfigParsingUtils::enumToString(sDeviceNameToEnumTable,
269 ARRAY_SIZE(sDeviceNameToEnumTable),
270 mDeviceType));
271 result.append(buffer);
272 if (mAddress.size() != 0) {
273 snprintf(buffer, SIZE, "%*s- address: %-32s\n", spaces, "", mAddress.string());
274 result.append(buffer);
275 }
276 write(fd, result.string(), result.size());
277 AudioPort::dump(fd, spaces);
278
279 return NO_ERROR;
280}
281
282}; // namespace android