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