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
DeviceDescriptor(const AudioDeviceTypeAddr & deviceTypeAddr,const std::string & tagName,const FormatVector & encodedFormats)52 DeviceDescriptor::DeviceDescriptor(const AudioDeviceTypeAddr &deviceTypeAddr,
53 const std::string &tagName,
54 const FormatVector &encodedFormats) :
55 DeviceDescriptorBase(deviceTypeAddr), mTagName(tagName), mEncodedFormats(encodedFormats)
56 {
57 mCurrentEncodedFormat = AUDIO_FORMAT_DEFAULT;
58 /* If framework runs against a pre 5.0 Audio HAL, encoded formats are absent from the config.
59 * FIXME: APM should know the version of the HAL and don't add the formats for V5.0.
60 * For now, the workaround to remove AC3 and IEC61937 support on HDMI is to declare
61 * something like 'encodedFormats="AUDIO_FORMAT_PCM_16_BIT"' on the HDMI devicePort.
62 */
63 if (mDeviceTypeAddr.mType == AUDIO_DEVICE_OUT_HDMI && mEncodedFormats.empty()) {
64 mEncodedFormats.push_back(AUDIO_FORMAT_AC3);
65 mEncodedFormats.push_back(AUDIO_FORMAT_IEC61937);
66 }
67 }
68
attach(const sp<HwModule> & module)69 void DeviceDescriptor::attach(const sp<HwModule>& module)
70 {
71 PolicyAudioPort::attach(module);
72 mId = getNextUniqueId();
73 }
74
detach()75 void DeviceDescriptor::detach() {
76 mId = AUDIO_PORT_HANDLE_NONE;
77 PolicyAudioPort::detach();
78 }
79
80 template<typename T>
checkEqual(const T & f1,const T & f2)81 bool checkEqual(const T& f1, const T& f2)
82 {
83 std::set<typename T::value_type> s1(f1.begin(), f1.end());
84 std::set<typename T::value_type> s2(f2.begin(), f2.end());
85 return s1 == s2;
86 }
87
equals(const sp<DeviceDescriptor> & other) const88 bool DeviceDescriptor::equals(const sp<DeviceDescriptor>& other) const
89 {
90 // Devices are considered equal if they:
91 // - are of the same type (a device type cannot be AUDIO_DEVICE_NONE)
92 // - have the same address
93 // - have the same encodingFormats (if device supports encoding)
94 if (other == 0) {
95 return false;
96 }
97
98 return mDeviceTypeAddr.equals(other->mDeviceTypeAddr) &&
99 checkEqual(mEncodedFormats, other->mEncodedFormats);
100 }
101
hasCurrentEncodedFormat() const102 bool DeviceDescriptor::hasCurrentEncodedFormat() const
103 {
104 if (!device_has_encoding_capability(type())) {
105 return true;
106 }
107 if (mEncodedFormats.empty()) {
108 return true;
109 }
110
111 return (mCurrentEncodedFormat != AUDIO_FORMAT_DEFAULT);
112 }
113
supportsFormat(audio_format_t format)114 bool DeviceDescriptor::supportsFormat(audio_format_t format)
115 {
116 if (mEncodedFormats.empty()) {
117 return true;
118 }
119
120 for (const auto& devFormat : mEncodedFormats) {
121 if (devFormat == format) {
122 return true;
123 }
124 }
125 return false;
126 }
127
applyAudioPortConfig(const struct audio_port_config * config,audio_port_config * backupConfig)128 status_t DeviceDescriptor::applyAudioPortConfig(const struct audio_port_config *config,
129 audio_port_config *backupConfig)
130 {
131 struct audio_port_config localBackupConfig = { .config_mask = config->config_mask };
132 status_t status = NO_ERROR;
133
134 toAudioPortConfig(&localBackupConfig);
135 if ((status = validationBeforeApplyConfig(config)) == NO_ERROR) {
136 AudioPortConfig::applyAudioPortConfig(config, backupConfig);
137 applyPolicyAudioPortConfig(config);
138 }
139
140 if (backupConfig != NULL) {
141 *backupConfig = localBackupConfig;
142 }
143 return status;
144 }
145
toAudioPortConfig(struct audio_port_config * dstConfig,const struct audio_port_config * srcConfig) const146 void DeviceDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
147 const struct audio_port_config *srcConfig) const
148 {
149 DeviceDescriptorBase::toAudioPortConfig(dstConfig, srcConfig);
150 toPolicyAudioPortConfig(dstConfig, srcConfig);
151
152 dstConfig->ext.device.hw_module = getModuleHandle();
153 }
154
toAudioPort(struct audio_port * port) const155 void DeviceDescriptor::toAudioPort(struct audio_port *port) const
156 {
157 ALOGV("DeviceDescriptor::toAudioPort() handle %d type %08x", mId, mDeviceTypeAddr.mType);
158 DeviceDescriptorBase::toAudioPort(port);
159 port->ext.device.hw_module = getModuleHandle();
160 }
161
importAudioPortAndPickAudioProfile(const sp<PolicyAudioPort> & policyPort,bool force)162 void DeviceDescriptor::importAudioPortAndPickAudioProfile(
163 const sp<PolicyAudioPort>& policyPort, bool force) {
164 if (!force && !policyPort->asAudioPort()->hasDynamicAudioProfile()) {
165 return;
166 }
167 AudioPort::importAudioPort(policyPort->asAudioPort());
168 policyPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
169 }
170
setEncapsulationInfoFromHal(AudioPolicyClientInterface * clientInterface)171 void DeviceDescriptor::setEncapsulationInfoFromHal(
172 AudioPolicyClientInterface *clientInterface) {
173 AudioParameter param(String8(mDeviceTypeAddr.getAddress()));
174 param.addInt(String8(AudioParameter::keyRouting), mDeviceTypeAddr.mType);
175 param.addKey(String8(AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_MODES));
176 param.addKey(String8(AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_METADATA_TYPES));
177 String8 reply = clientInterface->getParameters(AUDIO_IO_HANDLE_NONE, param.toString());
178 AudioParameter repliedParameters(reply);
179 int value;
180 if (repliedParameters.getInt(
181 String8(AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_MODES), value) == NO_ERROR) {
182 if (setEncapsulationModes(value) != NO_ERROR) {
183 ALOGE("Failed to set encapsulation mode(%d)", value);
184 }
185 }
186 if (repliedParameters.getInt(
187 String8(AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_METADATA_TYPES), value) == NO_ERROR) {
188 if (setEncapsulationMetadataTypes(value) != NO_ERROR) {
189 ALOGE("Failed to set encapsulation metadata types(%d)", value);
190 }
191 }
192 }
193
dump(String8 * dst,int spaces,int index,bool verbose) const194 void DeviceDescriptor::dump(String8 *dst, int spaces, int index, bool verbose) const
195 {
196 String8 extraInfo;
197 if (!mTagName.empty()) {
198 extraInfo.appendFormat("%*s- tag name: %s\n", spaces, "", mTagName.c_str());
199 }
200
201 std::string descBaseDumpStr;
202 DeviceDescriptorBase::dump(&descBaseDumpStr, spaces, index, extraInfo.string(), verbose);
203 dst->append(descBaseDumpStr.c_str());
204 }
205
206
refreshTypes()207 void DeviceVector::refreshTypes()
208 {
209 mDeviceTypes.clear();
210 for (size_t i = 0; i < size(); i++) {
211 mDeviceTypes.insert(itemAt(i)->type());
212 }
213 ALOGV("DeviceVector::refreshTypes() mDeviceTypes %s", dumpDeviceTypes(mDeviceTypes).c_str());
214 }
215
indexOf(const sp<DeviceDescriptor> & item) const216 ssize_t DeviceVector::indexOf(const sp<DeviceDescriptor>& item) const
217 {
218 for (size_t i = 0; i < size(); i++) {
219 if (itemAt(i)->equals(item)) { // item may be null sp<>, i.e. AUDIO_DEVICE_NONE
220 return i;
221 }
222 }
223 return -1;
224 }
225
add(const DeviceVector & devices)226 void DeviceVector::add(const DeviceVector &devices)
227 {
228 bool added = false;
229 for (const auto& device : devices) {
230 if (indexOf(device) < 0 && SortedVector::add(device) >= 0) {
231 added = true;
232 }
233 }
234 if (added) {
235 refreshTypes();
236 }
237 }
238
add(const sp<DeviceDescriptor> & item)239 ssize_t DeviceVector::add(const sp<DeviceDescriptor>& item)
240 {
241 ssize_t ret = indexOf(item);
242
243 if (ret < 0) {
244 ret = SortedVector::add(item);
245 if (ret >= 0) {
246 refreshTypes();
247 }
248 } else {
249 ALOGW("DeviceVector::add device %08x already in", item->type());
250 ret = -1;
251 }
252 return ret;
253 }
254
remove(const sp<DeviceDescriptor> & item)255 ssize_t DeviceVector::remove(const sp<DeviceDescriptor>& item)
256 {
257 ssize_t ret = indexOf(item);
258
259 if (ret < 0) {
260 ALOGW("DeviceVector::remove device %08x not in", item->type());
261 } else {
262 ret = SortedVector::removeAt(ret);
263 if (ret >= 0) {
264 refreshTypes();
265 }
266 }
267 return ret;
268 }
269
remove(const DeviceVector & devices)270 void DeviceVector::remove(const DeviceVector &devices)
271 {
272 for (const auto& device : devices) {
273 remove(device);
274 }
275 }
276
getDevicesFromHwModule(audio_module_handle_t moduleHandle) const277 DeviceVector DeviceVector::getDevicesFromHwModule(audio_module_handle_t moduleHandle) const
278 {
279 DeviceVector devices;
280 for (const auto& device : *this) {
281 if (device->getModuleHandle() == moduleHandle) {
282 devices.add(device);
283 }
284 }
285 return devices;
286 }
287
getDevice(audio_devices_t type,const String8 & address,audio_format_t format) const288 sp<DeviceDescriptor> DeviceVector::getDevice(audio_devices_t type, const String8& address,
289 audio_format_t format) const
290 {
291 sp<DeviceDescriptor> device;
292 for (size_t i = 0; i < size(); i++) {
293 if (itemAt(i)->type() == type) {
294 // If format is specified, match it and ignore address
295 // Otherwise if address is specified match it
296 // Otherwise always match
297 if (((address == "" || (itemAt(i)->address().compare(address.c_str()) == 0)) &&
298 format == AUDIO_FORMAT_DEFAULT) ||
299 (itemAt(i)->supportsFormat(format) && format != AUDIO_FORMAT_DEFAULT)) {
300 device = itemAt(i);
301 if (itemAt(i)->address().compare(address.c_str()) == 0) {
302 break;
303 }
304 }
305 }
306 }
307 ALOGV("DeviceVector::%s() for type %08x address \"%s\" found %p format %08x",
308 __func__, type, address.string(), device.get(), format);
309 return device;
310 }
311
getDeviceFromId(audio_port_handle_t id) const312 sp<DeviceDescriptor> DeviceVector::getDeviceFromId(audio_port_handle_t id) const
313 {
314 if (id != AUDIO_PORT_HANDLE_NONE) {
315 for (const auto& device : *this) {
316 if (device->getId() == id) {
317 return device;
318 }
319 }
320 }
321 return nullptr;
322 }
323
getDevicesFromTypes(const DeviceTypeSet & types) const324 DeviceVector DeviceVector::getDevicesFromTypes(const DeviceTypeSet& types) const
325 {
326 DeviceVector devices;
327 if (types.empty()) {
328 return devices;
329 }
330 for (size_t i = 0; i < size(); i++) {
331 if (types.count(itemAt(i)->type()) != 0) {
332 devices.add(itemAt(i));
333 ALOGV("DeviceVector::%s() for type %08x found %p",
334 __func__, itemAt(i)->type(), itemAt(i).get());
335 }
336 }
337 return devices;
338 }
339
getDeviceFromTagName(const std::string & tagName) const340 sp<DeviceDescriptor> DeviceVector::getDeviceFromTagName(const std::string &tagName) const
341 {
342 for (const auto& device : *this) {
343 if (device->getTagName() == tagName) {
344 return device;
345 }
346 }
347 return nullptr;
348 }
349
getFirstDevicesFromTypes(std::vector<audio_devices_t> orderedTypes) const350 DeviceVector DeviceVector::getFirstDevicesFromTypes(
351 std::vector<audio_devices_t> orderedTypes) const
352 {
353 DeviceVector devices;
354 for (auto deviceType : orderedTypes) {
355 if (!(devices = getDevicesFromType(deviceType)).isEmpty()) {
356 break;
357 }
358 }
359 return devices;
360 }
361
getFirstExistingDevice(std::vector<audio_devices_t> orderedTypes) const362 sp<DeviceDescriptor> DeviceVector::getFirstExistingDevice(
363 std::vector<audio_devices_t> orderedTypes) const {
364 sp<DeviceDescriptor> device;
365 for (auto deviceType : orderedTypes) {
366 if ((device = getDevice(deviceType, String8(""), AUDIO_FORMAT_DEFAULT)) != nullptr) {
367 break;
368 }
369 }
370 return device;
371 }
372
getDeviceForOpening() const373 sp<DeviceDescriptor> DeviceVector::getDeviceForOpening() const
374 {
375 if (isEmpty()) {
376 // Return nullptr if this collection is empty.
377 return nullptr;
378 } else if (areAllOfSameDeviceType(types(), audio_is_input_device)) {
379 // For input case, return the first one when there is only one device.
380 return size() > 1 ? nullptr : *begin();
381 } else if (areAllOfSameDeviceType(types(), audio_is_output_device)) {
382 // For output case, return the device descriptor according to apm strategy.
383 audio_devices_t deviceType = apm_extract_one_audio_device(types());
384 return deviceType == AUDIO_DEVICE_NONE ? nullptr :
385 getDevice(deviceType, String8(""), AUDIO_FORMAT_DEFAULT);
386 }
387 // Return null pointer if the devices are not all input/output device.
388 return nullptr;
389 }
390
replaceDevicesByType(audio_devices_t typeToRemove,const DeviceVector & devicesToAdd)391 void DeviceVector::replaceDevicesByType(
392 audio_devices_t typeToRemove, const DeviceVector &devicesToAdd) {
393 DeviceVector devicesToRemove = getDevicesFromType(typeToRemove);
394 if (!devicesToRemove.isEmpty() && !devicesToAdd.isEmpty()) {
395 remove(devicesToRemove);
396 add(devicesToAdd);
397 }
398 }
399
dump(String8 * dst,const String8 & tag,int spaces,bool verbose) const400 void DeviceVector::dump(String8 *dst, const String8 &tag, int spaces, bool verbose) const
401 {
402 if (isEmpty()) {
403 return;
404 }
405 dst->appendFormat("%*s- %s devices:\n", spaces, "", tag.string());
406 for (size_t i = 0; i < size(); i++) {
407 itemAt(i)->dump(dst, spaces + 2, i, verbose);
408 }
409 }
410
toString() const411 std::string DeviceVector::toString() const
412 {
413 if (isEmpty()) {
414 return {"AUDIO_DEVICE_NONE"};
415 }
416 std::string result = {"{"};
417 for (const auto &device : *this) {
418 if (device != *begin()) {
419 result += ";";
420 }
421 result += device->toString();
422 }
423 return result + "}";
424 }
425
filter(const DeviceVector & devices) const426 DeviceVector DeviceVector::filter(const DeviceVector &devices) const
427 {
428 DeviceVector filteredDevices;
429 for (const auto &device : *this) {
430 if (devices.contains(device)) {
431 filteredDevices.add(device);
432 }
433 }
434 return filteredDevices;
435 }
436
containsAtLeastOne(const DeviceVector & devices) const437 bool DeviceVector::containsAtLeastOne(const DeviceVector &devices) const
438 {
439 return !filter(devices).isEmpty();
440 }
441
containsAllDevices(const DeviceVector & devices) const442 bool DeviceVector::containsAllDevices(const DeviceVector &devices) const
443 {
444 return filter(devices).size() == devices.size();
445 }
446
filterForEngine() const447 DeviceVector DeviceVector::filterForEngine() const
448 {
449 DeviceVector filteredDevices;
450 for (const auto &device : *this) {
451 if (audio_is_remote_submix_device(device->type()) && device->address() != "0") {
452 continue;
453 }
454 filteredDevices.add(device);
455 }
456 return filteredDevices;
457 }
458
459 } // namespace android
460