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::Devices"
18 //#define LOG_NDEBUG 0
19
20 #include <audio_utils/string.h>
21 #include <media/TypeConverter.h>
22 #include <set>
23 #include "DeviceDescriptor.h"
24 #include "TypeConverter.h"
25 #include "AudioGain.h"
26 #include "HwModule.h"
27
28 namespace android {
29
DeviceDescriptor(audio_devices_t type,const String8 & tagName)30 DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const String8 &tagName) :
31 DeviceDescriptor(type, FormatVector{}, tagName)
32 {
33 }
34
DeviceDescriptor(audio_devices_t type,const FormatVector & encodedFormats,const String8 & tagName)35 DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const FormatVector &encodedFormats,
36 const String8 &tagName) :
37 AudioPort(String8(""), AUDIO_PORT_TYPE_DEVICE,
38 audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
39 AUDIO_PORT_ROLE_SOURCE),
40 mTagName(tagName), mDeviceType(type), mEncodedFormats(encodedFormats)
41 {
42 mCurrentEncodedFormat = AUDIO_FORMAT_DEFAULT;
43 if (audio_is_remote_submix_device(type)) {
44 mAddress = String8("0");
45 }
46 /* If framework runs against a pre 5.0 Audio HAL, encoded formats are absent from the config.
47 * FIXME: APM should know the version of the HAL and don't add the formats for V5.0.
48 * For now, the workaround to remove AC3 and IEC61937 support on HDMI is to declare
49 * something like 'encodedFormats="AUDIO_FORMAT_PCM_16_BIT"' on the HDMI devicePort.
50 */
51 if (type == AUDIO_DEVICE_OUT_HDMI && mEncodedFormats.isEmpty()) {
52 mEncodedFormats.add(AUDIO_FORMAT_AC3);
53 mEncodedFormats.add(AUDIO_FORMAT_IEC61937);
54 }
55 }
56
getId() const57 audio_port_handle_t DeviceDescriptor::getId() const
58 {
59 return mId;
60 }
61
attach(const sp<HwModule> & module)62 void DeviceDescriptor::attach(const sp<HwModule>& module)
63 {
64 AudioPort::attach(module);
65 mId = getNextUniqueId();
66 }
67
detach()68 void DeviceDescriptor::detach() {
69 mId = AUDIO_PORT_HANDLE_NONE;
70 AudioPort::detach();
71 }
72
73 template<typename T>
checkEqual(const T & f1,const T & f2)74 bool checkEqual(const T& f1, const T& f2)
75 {
76 std::set<typename T::value_type> s1(f1.begin(), f1.end());
77 std::set<typename T::value_type> s2(f2.begin(), f2.end());
78 return s1 == s2;
79 }
80
equals(const sp<DeviceDescriptor> & other) const81 bool DeviceDescriptor::equals(const sp<DeviceDescriptor>& other) const
82 {
83 // Devices are considered equal if they:
84 // - are of the same type (a device type cannot be AUDIO_DEVICE_NONE)
85 // - have the same address
86 // - have the same encodingFormats (if device supports encoding)
87 if (other == 0) {
88 return false;
89 }
90
91 return (mDeviceType == other->mDeviceType) && (mAddress == other->mAddress) &&
92 checkEqual(mEncodedFormats, other->mEncodedFormats);
93 }
94
hasCurrentEncodedFormat() const95 bool DeviceDescriptor::hasCurrentEncodedFormat() const
96 {
97 if (!device_has_encoding_capability(type())) {
98 return true;
99 }
100 if (mEncodedFormats.isEmpty()) {
101 return true;
102 }
103
104 return (mCurrentEncodedFormat != AUDIO_FORMAT_DEFAULT);
105 }
106
supportsFormat(audio_format_t format)107 bool DeviceDescriptor::supportsFormat(audio_format_t format)
108 {
109 if (mEncodedFormats.isEmpty()) {
110 return true;
111 }
112
113 for (const auto& devFormat : mEncodedFormats) {
114 if (devFormat == format) {
115 return true;
116 }
117 }
118 return false;
119 }
120
refreshTypes()121 void DeviceVector::refreshTypes()
122 {
123 mDeviceTypes = AUDIO_DEVICE_NONE;
124 for (size_t i = 0; i < size(); i++) {
125 mDeviceTypes |= itemAt(i)->type();
126 }
127 ALOGV("DeviceVector::refreshTypes() mDeviceTypes %08x", mDeviceTypes);
128 }
129
indexOf(const sp<DeviceDescriptor> & item) const130 ssize_t DeviceVector::indexOf(const sp<DeviceDescriptor>& item) const
131 {
132 for (size_t i = 0; i < size(); i++) {
133 if (itemAt(i)->equals(item)) { // item may be null sp<>, i.e. AUDIO_DEVICE_NONE
134 return i;
135 }
136 }
137 return -1;
138 }
139
add(const DeviceVector & devices)140 void DeviceVector::add(const DeviceVector &devices)
141 {
142 bool added = false;
143 for (const auto& device : devices) {
144 if (indexOf(device) < 0 && SortedVector::add(device) >= 0) {
145 added = true;
146 }
147 }
148 if (added) {
149 refreshTypes();
150 }
151 }
152
add(const sp<DeviceDescriptor> & item)153 ssize_t DeviceVector::add(const sp<DeviceDescriptor>& item)
154 {
155 ssize_t ret = indexOf(item);
156
157 if (ret < 0) {
158 ret = SortedVector::add(item);
159 if (ret >= 0) {
160 refreshTypes();
161 }
162 } else {
163 ALOGW("DeviceVector::add device %08x already in", item->type());
164 ret = -1;
165 }
166 return ret;
167 }
168
remove(const sp<DeviceDescriptor> & item)169 ssize_t DeviceVector::remove(const sp<DeviceDescriptor>& item)
170 {
171 ssize_t ret = indexOf(item);
172
173 if (ret < 0) {
174 ALOGW("DeviceVector::remove device %08x not in", item->type());
175 } else {
176 ret = SortedVector::removeAt(ret);
177 if (ret >= 0) {
178 refreshTypes();
179 }
180 }
181 return ret;
182 }
183
remove(const DeviceVector & devices)184 void DeviceVector::remove(const DeviceVector &devices)
185 {
186 for (const auto& device : devices) {
187 remove(device);
188 }
189 }
190
getDevicesFromHwModule(audio_module_handle_t moduleHandle) const191 DeviceVector DeviceVector::getDevicesFromHwModule(audio_module_handle_t moduleHandle) const
192 {
193 DeviceVector devices;
194 for (const auto& device : *this) {
195 if (device->getModuleHandle() == moduleHandle) {
196 devices.add(device);
197 }
198 }
199 return devices;
200 }
201
getDeviceTypesFromHwModule(audio_module_handle_t moduleHandle) const202 audio_devices_t DeviceVector::getDeviceTypesFromHwModule(audio_module_handle_t moduleHandle) const
203 {
204 audio_devices_t deviceTypes = AUDIO_DEVICE_NONE;
205 for (const auto& device : *this) {
206 if (device->getModuleHandle() == moduleHandle) {
207 deviceTypes |= device->type();
208 }
209 }
210 return deviceTypes;
211 }
212
getDevice(audio_devices_t type,const String8 & address,audio_format_t format) const213 sp<DeviceDescriptor> DeviceVector::getDevice(audio_devices_t type, const String8& address,
214 audio_format_t format) const
215 {
216 sp<DeviceDescriptor> device;
217 for (size_t i = 0; i < size(); i++) {
218 if (itemAt(i)->type() == type) {
219 // If format is specified, match it and ignore address
220 // Otherwise if address is specified match it
221 // Otherwise always match
222 if (((address == "" || itemAt(i)->address() == address) &&
223 format == AUDIO_FORMAT_DEFAULT) ||
224 (itemAt(i)->supportsFormat(format) && format != AUDIO_FORMAT_DEFAULT)) {
225 device = itemAt(i);
226 if (itemAt(i)->address() == address) {
227 break;
228 }
229 }
230 }
231 }
232 ALOGV("DeviceVector::%s() for type %08x address \"%s\" found %p format %08x",
233 __func__, type, address.string(), device.get(), format);
234 return device;
235 }
236
getDeviceFromId(audio_port_handle_t id) const237 sp<DeviceDescriptor> DeviceVector::getDeviceFromId(audio_port_handle_t id) const
238 {
239 if (id != AUDIO_PORT_HANDLE_NONE) {
240 for (const auto& device : *this) {
241 if (device->getId() == id) {
242 return device;
243 }
244 }
245 }
246 return nullptr;
247 }
248
getDevicesFromTypeMask(audio_devices_t type) const249 DeviceVector DeviceVector::getDevicesFromTypeMask(audio_devices_t type) const
250 {
251 DeviceVector devices;
252 bool isOutput = audio_is_output_devices(type);
253 type &= ~AUDIO_DEVICE_BIT_IN;
254 for (size_t i = 0; (i < size()) && (type != AUDIO_DEVICE_NONE); i++) {
255 bool curIsOutput = audio_is_output_devices(itemAt(i)->type());
256 audio_devices_t curType = itemAt(i)->type() & ~AUDIO_DEVICE_BIT_IN;
257 if ((isOutput == curIsOutput) && ((type & curType) != 0)) {
258 devices.add(itemAt(i));
259 type &= ~curType;
260 ALOGV("DeviceVector::%s() for type %08x found %p",
261 __func__, itemAt(i)->type(), itemAt(i).get());
262 }
263 }
264 return devices;
265 }
266
getDeviceFromTagName(const String8 & tagName) const267 sp<DeviceDescriptor> DeviceVector::getDeviceFromTagName(const String8 &tagName) const
268 {
269 for (const auto& device : *this) {
270 if (device->getTagName() == tagName) {
271 return device;
272 }
273 }
274 return nullptr;
275 }
276
dump(String8 * dst,const String8 & tag,int spaces,bool verbose) const277 void DeviceVector::dump(String8 *dst, const String8 &tag, int spaces, bool verbose) const
278 {
279 if (isEmpty()) {
280 return;
281 }
282 dst->appendFormat("%*s- %s devices:\n", spaces, "", tag.string());
283 for (size_t i = 0; i < size(); i++) {
284 itemAt(i)->dump(dst, spaces + 2, i, verbose);
285 }
286 }
287
toAudioPortConfig(struct audio_port_config * dstConfig,const struct audio_port_config * srcConfig) const288 void DeviceDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
289 const struct audio_port_config *srcConfig) const
290 {
291 dstConfig->config_mask = AUDIO_PORT_CONFIG_GAIN;
292 if (mSamplingRate != 0) {
293 dstConfig->config_mask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
294 }
295 if (mChannelMask != AUDIO_CHANNEL_NONE) {
296 dstConfig->config_mask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
297 }
298 if (mFormat != AUDIO_FORMAT_INVALID) {
299 dstConfig->config_mask |= AUDIO_PORT_CONFIG_FORMAT;
300 }
301
302 if (srcConfig != NULL) {
303 dstConfig->config_mask |= srcConfig->config_mask;
304 }
305
306 AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
307
308 dstConfig->id = mId;
309 dstConfig->role = audio_is_output_device(mDeviceType) ?
310 AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE;
311 dstConfig->type = AUDIO_PORT_TYPE_DEVICE;
312 dstConfig->ext.device.type = mDeviceType;
313
314 //TODO Understand why this test is necessary. i.e. why at boot time does it crash
315 // without the test?
316 // This has been demonstrated to NOT be true (at start up)
317 // ALOG_ASSERT(mModule != NULL);
318 dstConfig->ext.device.hw_module = getModuleHandle();
319 (void)audio_utils_strlcpy_zerofill(dstConfig->ext.device.address, mAddress.string());
320 }
321
toAudioPort(struct audio_port * port) const322 void DeviceDescriptor::toAudioPort(struct audio_port *port) const
323 {
324 ALOGV("DeviceDescriptor::toAudioPort() handle %d type %08x", mId, mDeviceType);
325 AudioPort::toAudioPort(port);
326 port->id = mId;
327 toAudioPortConfig(&port->active_config);
328 port->ext.device.type = mDeviceType;
329 port->ext.device.hw_module = getModuleHandle();
330 (void)audio_utils_strlcpy_zerofill(port->ext.device.address, mAddress.string());
331 }
332
importAudioPort(const sp<AudioPort> & port,bool force)333 void DeviceDescriptor::importAudioPort(const sp<AudioPort>& port, bool force) {
334 if (!force && !port->hasDynamicAudioProfile()) {
335 return;
336 }
337 AudioPort::importAudioPort(port);
338 port->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
339 }
340
dump(String8 * dst,int spaces,int index,bool verbose) const341 void DeviceDescriptor::dump(String8 *dst, int spaces, int index, bool verbose) const
342 {
343 dst->appendFormat("%*sDevice %d:\n", spaces, "", index + 1);
344 if (mId != 0) {
345 dst->appendFormat("%*s- id: %2d\n", spaces, "", mId);
346 }
347 if (!mTagName.isEmpty()) {
348 dst->appendFormat("%*s- tag name: %s\n", spaces, "", mTagName.string());
349 }
350
351 dst->appendFormat("%*s- type: %-48s\n", spaces, "", ::android::toString(mDeviceType).c_str());
352
353 if (mAddress.size() != 0) {
354 dst->appendFormat("%*s- address: %-32s\n", spaces, "", mAddress.string());
355 }
356 AudioPort::dump(dst, spaces, verbose);
357 }
358
toString() const359 std::string DeviceDescriptor::toString() const
360 {
361 std::stringstream sstream;
362 sstream << "type:0x" << std::hex << type() << ",@:" << mAddress;
363 return sstream.str();
364 }
365
toString() const366 std::string DeviceVector::toString() const
367 {
368 if (isEmpty()) {
369 return {"AUDIO_DEVICE_NONE"};
370 }
371 std::string result = {"{"};
372 for (const auto &device : *this) {
373 if (device != *begin()) {
374 result += ";";
375 }
376 result += device->toString();
377 }
378 return result + "}";
379 }
380
filter(const DeviceVector & devices) const381 DeviceVector DeviceVector::filter(const DeviceVector &devices) const
382 {
383 DeviceVector filteredDevices;
384 for (const auto &device : *this) {
385 if (devices.contains(device)) {
386 filteredDevices.add(device);
387 }
388 }
389 return filteredDevices;
390 }
391
containsAtLeastOne(const DeviceVector & devices) const392 bool DeviceVector::containsAtLeastOne(const DeviceVector &devices) const
393 {
394 return !filter(devices).isEmpty();
395 }
396
containsAllDevices(const DeviceVector & devices) const397 bool DeviceVector::containsAllDevices(const DeviceVector &devices) const
398 {
399 return filter(devices).size() == devices.size();
400 }
401
filterForEngine() const402 DeviceVector DeviceVector::filterForEngine() const
403 {
404 DeviceVector filteredDevices;
405 for (const auto &device : *this) {
406 if (audio_is_remote_submix_device(device->type()) && device->address() != "0") {
407 continue;
408 }
409 filteredDevices.add(device);
410 }
411 return filteredDevices;
412 }
413
log() const414 void DeviceDescriptor::log() const
415 {
416 ALOGI("Device id:%d type:0x%08X:%s, addr:%s", mId, mDeviceType,
417 ::android::toString(mDeviceType).c_str(),
418 mAddress.string());
419
420 AudioPort::log(" ");
421 }
422
423 } // namespace android
424