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