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