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