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 <set>
21
22 #include <android-base/stringprintf.h>
23 #include <audio_utils/string.h>
24 #include <media/AudioParameter.h>
25 #include <media/TypeConverter.h>
26 #include <AudioPolicyInterface.h>
27 #include "DeviceDescriptor.h"
28 #include "TypeConverter.h"
29 #include "HwModule.h"
30
31 namespace android {
32
DeviceDescriptor(audio_devices_t type)33 DeviceDescriptor::DeviceDescriptor(audio_devices_t type) :
34 DeviceDescriptor(type, "" /*tagName*/)
35 {
36 }
37
DeviceDescriptor(audio_devices_t type,const std::string & tagName,const FormatVector & encodedFormats)38 DeviceDescriptor::DeviceDescriptor(audio_devices_t type,
39 const std::string &tagName,
40 const FormatVector &encodedFormats) :
41 DeviceDescriptor(type, tagName, "" /*address*/, encodedFormats)
42 {
43 }
44
DeviceDescriptor(audio_devices_t type,const std::string & tagName,const std::string & address,const FormatVector & encodedFormats)45 DeviceDescriptor::DeviceDescriptor(audio_devices_t type,
46 const std::string &tagName,
47 const std::string &address,
48 const FormatVector &encodedFormats) :
49 DeviceDescriptor(AudioDeviceTypeAddr(type, address), tagName, encodedFormats)
50 {
51 }
52
53 // Let DeviceDescriptorBase initialize the address since it handles specific cases like
54 // legacy remote submix where "0" is added as default address.
DeviceDescriptor(const AudioDeviceTypeAddr & deviceTypeAddr,const std::string & tagName,const FormatVector & encodedFormats)55 DeviceDescriptor::DeviceDescriptor(const AudioDeviceTypeAddr &deviceTypeAddr,
56 const std::string &tagName,
57 const FormatVector &encodedFormats) :
58 DeviceDescriptorBase(deviceTypeAddr, encodedFormats), mTagName(tagName),
59 mDeclaredAddress(DeviceDescriptorBase::address())
60 {
61 mCurrentEncodedFormat = AUDIO_FORMAT_DEFAULT;
62 }
63
attach(const sp<HwModule> & module)64 void DeviceDescriptor::attach(const sp<HwModule>& module)
65 {
66 PolicyAudioPort::attach(module);
67 mId = getNextUniqueId();
68 }
69
detach()70 void DeviceDescriptor::detach() {
71 mId = AUDIO_PORT_HANDLE_NONE;
72 PolicyAudioPort::detach();
73 // The device address may have been overwritten on device connection
74 setAddress(mDeclaredAddress);
75 // Device Port does not have a name unless provided by setDeviceConnectionState
76 setName("");
77 }
78
79 template<typename T>
checkEqual(const T & f1,const T & f2)80 bool checkEqual(const T& f1, const T& f2)
81 {
82 std::set<typename T::value_type> s1(f1.begin(), f1.end());
83 std::set<typename T::value_type> s2(f2.begin(), f2.end());
84 return s1 == s2;
85 }
86
equals(const sp<DeviceDescriptor> & other) const87 bool DeviceDescriptor::equals(const sp<DeviceDescriptor>& other) const
88 {
89 // Devices are considered equal if they:
90 // - are of the same type (a device type cannot be AUDIO_DEVICE_NONE)
91 // - have the same address
92 // - have the same encodingFormats (if device supports encoding)
93 if (other == 0) {
94 return false;
95 }
96
97 return mDeviceTypeAddr.equals(other->mDeviceTypeAddr) &&
98 checkEqual(mEncodedFormats, other->mEncodedFormats);
99 }
100
hasCurrentEncodedFormat() const101 bool DeviceDescriptor::hasCurrentEncodedFormat() const
102 {
103 if (!device_has_encoding_capability(type())) {
104 return true;
105 }
106 if (mEncodedFormats.empty()) {
107 return true;
108 }
109
110 return (mCurrentEncodedFormat != AUDIO_FORMAT_DEFAULT);
111 }
112
applyAudioPortConfig(const struct audio_port_config * config,audio_port_config * backupConfig)113 status_t DeviceDescriptor::applyAudioPortConfig(const struct audio_port_config *config,
114 audio_port_config *backupConfig)
115 {
116 struct audio_port_config localBackupConfig = { .config_mask = config->config_mask };
117 status_t status = NO_ERROR;
118
119 toAudioPortConfig(&localBackupConfig);
120 if ((status = validationBeforeApplyConfig(config)) == NO_ERROR) {
121 AudioPortConfig::applyAudioPortConfig(config, backupConfig);
122 }
123
124 if (backupConfig != NULL) {
125 *backupConfig = localBackupConfig;
126 }
127 return status;
128 }
129
toAudioPortConfig(struct audio_port_config * dstConfig,const struct audio_port_config * srcConfig) const130 void DeviceDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
131 const struct audio_port_config *srcConfig) const
132 {
133 DeviceDescriptorBase::toAudioPortConfig(dstConfig, srcConfig);
134 dstConfig->ext.device.hw_module = getModuleHandle();
135 }
136
toAudioPort(struct audio_port * port) const137 void DeviceDescriptor::toAudioPort(struct audio_port *port) const
138 {
139 ALOGV("DeviceDescriptor::toAudioPort() handle %d type %08x", mId, mDeviceTypeAddr.mType);
140 toAudioPortInternal(port);
141 }
142
toAudioPort(struct audio_port_v7 * port) const143 void DeviceDescriptor::toAudioPort(struct audio_port_v7 *port) const {
144 ALOGV("DeviceDescriptor::toAudioPort() v7 handle %d type %08x", mId, mDeviceTypeAddr.mType);
145 toAudioPortInternal(port);
146 }
147
importAudioPortAndPickAudioProfile(const sp<PolicyAudioPort> & policyPort,bool force)148 void DeviceDescriptor::importAudioPortAndPickAudioProfile(
149 const sp<PolicyAudioPort>& policyPort, bool force) {
150 if (!force && !policyPort->asAudioPort()->hasDynamicAudioProfile()) {
151 return;
152 }
153 AudioPort::importAudioPort(policyPort->asAudioPort());
154 policyPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
155 }
156
setEncapsulationInfoFromHal(AudioPolicyClientInterface * clientInterface)157 void DeviceDescriptor::setEncapsulationInfoFromHal(
158 AudioPolicyClientInterface *clientInterface) {
159 AudioParameter param(String8(mDeviceTypeAddr.getAddress()));
160 param.addInt(String8(AudioParameter::keyRouting), mDeviceTypeAddr.mType);
161 param.addKey(String8(AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_MODES));
162 param.addKey(String8(AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_METADATA_TYPES));
163 String8 reply = clientInterface->getParameters(AUDIO_IO_HANDLE_NONE, param.toString());
164 AudioParameter repliedParameters(reply);
165 int value;
166 if (repliedParameters.getInt(
167 String8(AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_MODES), value) == NO_ERROR) {
168 if (setEncapsulationModes(value) != NO_ERROR) {
169 ALOGE("Failed to set encapsulation mode(%d)", value);
170 }
171 }
172 if (repliedParameters.getInt(
173 String8(AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_METADATA_TYPES), value) == NO_ERROR) {
174 if (setEncapsulationMetadataTypes(value) != NO_ERROR) {
175 ALOGE("Failed to set encapsulation metadata types(%d)", value);
176 }
177 }
178 }
179
dump(String8 * dst,int spaces,bool verbose) const180 void DeviceDescriptor::dump(String8 *dst, int spaces, bool verbose) const
181 {
182 String8 extraInfo;
183 if (!mTagName.empty()) {
184 extraInfo.appendFormat("\"%s\"", mTagName.c_str());
185 }
186
187 std::string descBaseDumpStr;
188 DeviceDescriptorBase::dump(&descBaseDumpStr, spaces, extraInfo.string(), verbose);
189 dst->append(descBaseDumpStr.c_str());
190 }
191
192
refreshTypes()193 void DeviceVector::refreshTypes()
194 {
195 mDeviceTypes.clear();
196 for (size_t i = 0; i < size(); i++) {
197 mDeviceTypes.insert(itemAt(i)->type());
198 }
199 ALOGV("DeviceVector::refreshTypes() mDeviceTypes %s", dumpDeviceTypes(mDeviceTypes).c_str());
200 }
201
refreshAudioProfiles()202 void DeviceVector::refreshAudioProfiles() {
203 if (empty()) {
204 mSupportedProfiles.clear();
205 return;
206 }
207 mSupportedProfiles = itemAt(0)->getAudioProfiles();
208 for (size_t i = 1; i < size(); ++i) {
209 mSupportedProfiles = intersectAudioProfiles(
210 mSupportedProfiles, itemAt(i)->getAudioProfiles());
211 }
212 }
213
indexOf(const sp<DeviceDescriptor> & item) const214 ssize_t DeviceVector::indexOf(const sp<DeviceDescriptor>& item) const
215 {
216 for (size_t i = 0; i < size(); i++) {
217 if (itemAt(i)->equals(item)) { // item may be null sp<>, i.e. AUDIO_DEVICE_NONE
218 return i;
219 }
220 }
221 return -1;
222 }
223
add(const DeviceVector & devices)224 void DeviceVector::add(const DeviceVector &devices)
225 {
226 bool added = false;
227 for (const auto& device : devices) {
228 ALOG_ASSERT(device != nullptr, "Null pointer found when adding DeviceVector");
229 if (indexOf(device) < 0 && SortedVector::add(device) >= 0) {
230 added = true;
231 }
232 }
233 if (added) {
234 refreshTypes();
235 refreshAudioProfiles();
236 }
237 }
238
add(const sp<DeviceDescriptor> & item)239 ssize_t DeviceVector::add(const sp<DeviceDescriptor>& item)
240 {
241 ALOG_ASSERT(item != nullptr, "Adding null pointer to DeviceVector");
242 ssize_t ret = indexOf(item);
243
244 if (ret < 0) {
245 ret = SortedVector::add(item);
246 if (ret >= 0) {
247 refreshTypes();
248 refreshAudioProfiles();
249 }
250 } else {
251 ALOGW("DeviceVector::add device %08x already in", item->type());
252 ret = -1;
253 }
254 return ret;
255 }
256
do_compare(const void * lhs,const void * rhs) const257 int DeviceVector::do_compare(const void* lhs, const void* rhs) const {
258 const auto ldevice = *reinterpret_cast<const sp<DeviceDescriptor>*>(lhs);
259 const auto rdevice = *reinterpret_cast<const sp<DeviceDescriptor>*>(rhs);
260 int ret = 0;
261
262 // sort by type.
263 ret = compare_type(ldevice->type(), rdevice->type());
264 if (ret != 0)
265 return ret;
266 // for same type higher priority for latest device.
267 ret = compare_type(rdevice->getId(), ldevice->getId());
268 if (ret != 0)
269 return ret;
270 // fallback to default sort using pointer address
271 return SortedVector::do_compare(lhs, rhs);
272 }
273
remove(const sp<DeviceDescriptor> & item)274 ssize_t DeviceVector::remove(const sp<DeviceDescriptor>& item)
275 {
276 ssize_t ret = indexOf(item);
277
278 if (ret < 0) {
279 ALOGW("DeviceVector::remove device %08x not in", item->type());
280 } else {
281 ret = SortedVector::removeAt(ret);
282 if (ret >= 0) {
283 refreshTypes();
284 refreshAudioProfiles();
285 }
286 }
287 return ret;
288 }
289
remove(const DeviceVector & devices)290 void DeviceVector::remove(const DeviceVector &devices)
291 {
292 for (const auto& device : devices) {
293 remove(device);
294 }
295 }
296
getDevicesFromHwModule(audio_module_handle_t moduleHandle) const297 DeviceVector DeviceVector::getDevicesFromHwModule(audio_module_handle_t moduleHandle) const
298 {
299 DeviceVector devices;
300 for (const auto& device : *this) {
301 if (device->getModuleHandle() == moduleHandle) {
302 devices.add(device);
303 }
304 }
305 return devices;
306 }
307
getDevice(audio_devices_t type,const String8 & address,audio_format_t format) const308 sp<DeviceDescriptor> DeviceVector::getDevice(audio_devices_t type, const String8& address,
309 audio_format_t format) const
310 {
311 sp<DeviceDescriptor> device;
312 for (size_t i = 0; i < size(); i++) {
313 if (itemAt(i)->type() == type) {
314 // If format is specified, match it and ignore address
315 // Otherwise if address is specified match it
316 // Otherwise always match
317 if (((address == "" || (itemAt(i)->address().compare(address.c_str()) == 0)) &&
318 format == AUDIO_FORMAT_DEFAULT) ||
319 (itemAt(i)->supportsFormat(format) && format != AUDIO_FORMAT_DEFAULT)) {
320 device = itemAt(i);
321 if (itemAt(i)->address().compare(address.c_str()) == 0) {
322 break;
323 }
324 }
325 }
326 }
327 ALOGV("DeviceVector::%s() for type %08x address \"%s\" found %p format %08x",
328 __func__, type, address.string(), device.get(), format);
329 return device;
330 }
331
getDeviceFromId(audio_port_handle_t id) const332 sp<DeviceDescriptor> DeviceVector::getDeviceFromId(audio_port_handle_t id) const
333 {
334 if (id != AUDIO_PORT_HANDLE_NONE) {
335 for (const auto& device : *this) {
336 if (device->getId() == id) {
337 return device;
338 }
339 }
340 }
341 return nullptr;
342 }
343
getDevicesFromTypes(const DeviceTypeSet & types) const344 DeviceVector DeviceVector::getDevicesFromTypes(const DeviceTypeSet& types) const
345 {
346 DeviceVector devices;
347 if (types.empty()) {
348 return devices;
349 }
350 for (size_t i = 0; i < size(); i++) {
351 if (types.count(itemAt(i)->type()) != 0) {
352 devices.add(itemAt(i));
353 ALOGV("DeviceVector::%s() for type %08x found %p",
354 __func__, itemAt(i)->type(), itemAt(i).get());
355 }
356 }
357 return devices;
358 }
359
getDeviceFromTagName(const std::string & tagName) const360 sp<DeviceDescriptor> DeviceVector::getDeviceFromTagName(const std::string &tagName) const
361 {
362 for (const auto& device : *this) {
363 if (device->getTagName() == tagName) {
364 return device;
365 }
366 }
367 return nullptr;
368 }
369
getFirstDevicesFromTypes(std::vector<audio_devices_t> orderedTypes) const370 DeviceVector DeviceVector::getFirstDevicesFromTypes(
371 std::vector<audio_devices_t> orderedTypes) const
372 {
373 DeviceVector devices;
374 for (auto deviceType : orderedTypes) {
375 if (!(devices = getDevicesFromType(deviceType)).isEmpty()) {
376 break;
377 }
378 }
379 return devices;
380 }
381
getFirstExistingDevice(std::vector<audio_devices_t> orderedTypes) const382 sp<DeviceDescriptor> DeviceVector::getFirstExistingDevice(
383 std::vector<audio_devices_t> orderedTypes) const {
384 sp<DeviceDescriptor> device;
385 for (auto deviceType : orderedTypes) {
386 if ((device = getDevice(deviceType, String8(""), AUDIO_FORMAT_DEFAULT)) != nullptr) {
387 break;
388 }
389 }
390 return device;
391 }
392
getDeviceForOpening() const393 sp<DeviceDescriptor> DeviceVector::getDeviceForOpening() const
394 {
395 if (isEmpty()) {
396 // Return nullptr if this collection is empty.
397 return nullptr;
398 } else if (areAllOfSameDeviceType(types(), audio_call_is_input_device)) {
399 // For input case, return the first one when there is only one device.
400 return size() > 1 ? nullptr : *begin();
401 } else if (areAllOfSameDeviceType(types(), audio_is_output_device)) {
402 // For output case, return the device descriptor according to apm strategy.
403 audio_devices_t deviceType = apm_extract_one_audio_device(types());
404 return deviceType == AUDIO_DEVICE_NONE ? nullptr :
405 getDevice(deviceType, String8(""), AUDIO_FORMAT_DEFAULT);
406 }
407 // Return null pointer if the devices are not all input/output device.
408 return nullptr;
409 }
410
getDeviceFromDeviceTypeAddr(const AudioDeviceTypeAddr & deviceTypeAddr) const411 sp<DeviceDescriptor> DeviceVector::getDeviceFromDeviceTypeAddr(
412 const AudioDeviceTypeAddr& deviceTypeAddr) const {
413 return getDevice(deviceTypeAddr.mType, String8(deviceTypeAddr.getAddress()),
414 AUDIO_FORMAT_DEFAULT);
415 }
416
getDevicesFromDeviceTypeAddrVec(const AudioDeviceTypeAddrVector & deviceTypeAddrVector) const417 DeviceVector DeviceVector::getDevicesFromDeviceTypeAddrVec(
418 const AudioDeviceTypeAddrVector& deviceTypeAddrVector) const {
419 DeviceVector devices;
420 for (const auto& deviceTypeAddr : deviceTypeAddrVector) {
421 sp<DeviceDescriptor> device = getDeviceFromDeviceTypeAddr(deviceTypeAddr);
422 if (device != nullptr) {
423 devices.add(device);
424 }
425 }
426 return devices;
427 }
428
toTypeAddrVector() const429 AudioDeviceTypeAddrVector DeviceVector::toTypeAddrVector() const {
430 AudioDeviceTypeAddrVector result;
431 for (const auto& device : *this) {
432 result.push_back(AudioDeviceTypeAddr(device->type(), device->address()));
433 }
434 return result;
435 }
436
replaceDevicesByType(audio_devices_t typeToRemove,const DeviceVector & devicesToAdd)437 void DeviceVector::replaceDevicesByType(
438 audio_devices_t typeToRemove, const DeviceVector &devicesToAdd) {
439 DeviceVector devicesToRemove = getDevicesFromType(typeToRemove);
440 if (!devicesToRemove.isEmpty() && !devicesToAdd.isEmpty()) {
441 remove(devicesToRemove);
442 add(devicesToAdd);
443 }
444 }
445
dump(String8 * dst,const String8 & tag,int spaces,bool verbose) const446 void DeviceVector::dump(String8 *dst, const String8 &tag, int spaces, bool verbose) const
447 {
448 if (isEmpty()) {
449 return;
450 }
451 dst->appendFormat("%*s%s devices (%zu):\n", spaces, "", tag.string(), size());
452 for (size_t i = 0; i < size(); i++) {
453 const std::string prefix = base::StringPrintf("%*s %zu. ", spaces, "", i + 1);
454 dst->appendFormat("%s", prefix.c_str());
455 itemAt(i)->dump(dst, prefix.size(), verbose);
456 }
457 }
458
toString(bool includeSensitiveInfo) const459 std::string DeviceVector::toString(bool includeSensitiveInfo) const
460 {
461 if (isEmpty()) {
462 return {"AUDIO_DEVICE_NONE"};
463 }
464 std::string result = {"{"};
465 for (const auto &device : *this) {
466 if (device != *begin()) {
467 result += ";";
468 }
469 result += device->toString(includeSensitiveInfo);
470 }
471 return result + "}";
472 }
473
filter(const DeviceVector & devices) const474 DeviceVector DeviceVector::filter(const DeviceVector &devices) const
475 {
476 DeviceVector filteredDevices;
477 for (const auto &device : *this) {
478 if (devices.contains(device)) {
479 filteredDevices.add(device);
480 }
481 }
482 return filteredDevices;
483 }
484
containsAtLeastOne(const DeviceVector & devices) const485 bool DeviceVector::containsAtLeastOne(const DeviceVector &devices) const
486 {
487 return !filter(devices).isEmpty();
488 }
489
containsAllDevices(const DeviceVector & devices) const490 bool DeviceVector::containsAllDevices(const DeviceVector &devices) const
491 {
492 return filter(devices).size() == devices.size();
493 }
494
filterForEngine() const495 DeviceVector DeviceVector::filterForEngine() const
496 {
497 DeviceVector filteredDevices;
498 for (const auto &device : *this) {
499 if (audio_is_remote_submix_device(device->type()) && device->address() != "0") {
500 continue;
501 }
502 filteredDevices.add(device);
503 }
504 return filteredDevices;
505 }
506
507 } // namespace android
508