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::AudioPolicyEngine"
18 //#define LOG_NDEBUG 0
19
20 //#define VERY_VERBOSE_LOGGING
21 #ifdef VERY_VERBOSE_LOGGING
22 #define ALOGVV ALOGV
23 #else
24 #define ALOGVV(a...) do { } while(0)
25 #endif
26
27 #include "Engine.h"
28 #include "Stream.h"
29 #include "InputSource.h"
30
31 #include <EngineConfig.h>
32 #include <policy.h>
33 #include <AudioIODescriptorInterface.h>
34 #include <com_android_media_audioserver.h>
35 #include <media/AudioContainers.h>
36
37 #include <media/TypeConverter.h>
38
39 #include <cinttypes>
40
41 using std::string;
42 using std::map;
43
44 namespace android {
45 namespace audio_policy {
46
47 template <>
getCollection()48 StreamCollection &Engine::getCollection<audio_stream_type_t>()
49 {
50 return mStreamCollection;
51 }
52 template <>
getCollection()53 InputSourceCollection &Engine::getCollection<audio_source_t>()
54 {
55 return mInputSourceCollection;
56 }
57
58 template <>
getCollection() const59 const StreamCollection &Engine::getCollection<audio_stream_type_t>() const
60 {
61 return mStreamCollection;
62 }
63 template <>
getCollection() const64 const InputSourceCollection &Engine::getCollection<audio_source_t>() const
65 {
66 return mInputSourceCollection;
67 }
68
loadFromHalConfigWithFallback(const media::audio::common::AudioHalEngineConfig & aidlConfig)69 status_t Engine::loadFromHalConfigWithFallback(
70 const media::audio::common::AudioHalEngineConfig& aidlConfig) {
71 #ifdef DISABLE_CAP_AIDL
72 (void) aidlConfig;
73 ALOGE("%s CapEngine Config disabled, falling back on vendor XML for engine", __func__);
74 return loadFromXmlConfigWithFallback(engineConfig::DEFAULT_PATH);
75 #else
76 #ifdef ENABLE_CAP_AIDL_HYBRID_MODE
77 if (!aidlConfig.capSpecificConfig.value().domains.has_value()) {
78 ALOGE("%s CapEngine Config missing, falling back on vendor XML for engine", __func__);
79 return loadFromXmlConfigWithFallback(engineConfig::DEFAULT_PATH);
80 }
81 #endif
82 mPolicyParameterMgr = std::make_unique<ParameterManagerWrapper>();
83 auto capResult = capEngineConfig::convert(aidlConfig);
84 if (capResult.parsedConfig == nullptr) {
85 ALOGE("%s CapEngine Config invalid", __func__);
86 return BAD_VALUE;
87 }
88 status_t ret = loadWithFallback(aidlConfig);
89 if (ret != NO_ERROR) {
90 return ret;
91 }
92 auto loadCriteria= [this](const auto& capCriteria) {
93 for (auto& capCriterion : capCriteria) {
94 mPolicyParameterMgr->addCriterion(capCriterion.criterion.name,
95 capCriterion.criterionType.isInclusive,
96 capCriterion.criterionType.valuePairs,
97 capCriterion.criterion.defaultLiteralValue);
98 }
99 };
100 loadCriteria(capResult.parsedConfig->capCriteria);
101 std::string error;
102 if (mPolicyParameterMgr->start(error) != NO_ERROR) {
103 ALOGE("%s: could not start Policy PFW: %s, fallback on default", __func__ , error.c_str());
104 auto result = parseAndSetDefaultConfiguration();
105 return result.nbSkippedElement == 0 ? NO_ERROR : BAD_VALUE;
106 }
107 return mPolicyParameterMgr->setConfiguration(capResult);
108 #endif
109 }
110
loadFromXmlConfigWithFallback(const std::string & xmlFilePath)111 status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath)
112 {
113 mPolicyParameterMgr = std::make_unique<ParameterManagerWrapper>(true /*useLegacyVendorFile*/);
114 status_t status = loadWithFallback(xmlFilePath);
115 std::string error;
116 if (mPolicyParameterMgr->start(error) != NO_ERROR) {
117 ALOGE("%s: could not start Policy PFW: %s, fallback on default", __func__ , error.c_str());
118 auto result = parseAndSetDefaultConfiguration();
119 return result.nbSkippedElement == 0 ? NO_ERROR : BAD_VALUE;
120 }
121 return status;
122 }
123
124 template<typename T>
loadWithFallback(const T & configSource)125 status_t Engine::loadWithFallback(const T& configSource) {
126 auto result = EngineBase::loadAudioPolicyEngineConfig(configSource, true /*isConfigurable*/);
127 ALOGE_IF(result.nbSkippedElement != 0,
128 "Policy Engine configuration is partially invalid, skipped %zu elements",
129 result.nbSkippedElement);
130
131 auto loadCriteria= [this](const auto& configCriteria, const auto& configCriterionTypes) {
132 for (auto& criterion : configCriteria) {
133 engineConfig::CriterionType criterionType;
134 for (auto &configCriterionType : configCriterionTypes) {
135 if (configCriterionType.name == criterion.typeName) {
136 criterionType = configCriterionType;
137 break;
138 }
139 }
140 ALOG_ASSERT(not criterionType.name.empty(), "Invalid criterion type for %s",
141 criterion.name.c_str());
142 mPolicyParameterMgr->addCriterion(criterion.name, criterionType.isInclusive,
143 criterionType.valuePairs,
144 criterion.defaultLiteralValue);
145 }
146 };
147
148 loadCriteria(result.parsedConfig->criteria, result.parsedConfig->criterionTypes);
149 return result.nbSkippedElement == 0? NO_ERROR : BAD_VALUE;
150 }
151
initCheck()152 status_t Engine::initCheck()
153 {
154 return EngineBase::initCheck();
155 }
156
157 template <typename Key>
getFromCollection(const Key & key) const158 Element<Key> *Engine::getFromCollection(const Key &key) const
159 {
160 const Collection<Key> &collection = getCollection<Key>();
161 return collection.get(key);
162 }
163
164 template <typename Key>
add(const std::string & name,const Key & key)165 status_t Engine::add(const std::string &name, const Key &key)
166 {
167 Collection<Key> &collection = getCollection<Key>();
168 return collection.add(name, key);
169 }
170
171 template <typename Property, typename Key>
getPropertyForKey(Key key) const172 Property Engine::getPropertyForKey(Key key) const
173 {
174 Element<Key> *element = getFromCollection<Key>(key);
175 if (element == NULL) {
176 ALOGE("%s: Element not found within collection", __FUNCTION__);
177 return static_cast<Property>(0);
178 }
179 return element->template get<Property>();
180 }
181
setVolumeProfileForStream(const audio_stream_type_t & stream,const audio_stream_type_t & profile)182 bool Engine::setVolumeProfileForStream(const audio_stream_type_t &stream,
183 const audio_stream_type_t &profile)
184 {
185 if (setPropertyForKey<audio_stream_type_t, audio_stream_type_t>(stream, profile)) {
186 switchVolumeCurve(profile, stream);
187 return true;
188 }
189 return false;
190 }
191
192 template <typename Property, typename Key>
setPropertyForKey(const Property & property,const Key & key)193 bool Engine::setPropertyForKey(const Property &property, const Key &key)
194 {
195 Element<Key> *element = getFromCollection<Key>(key);
196 if (element == NULL) {
197 ALOGE("%s: Element not found within collection", __FUNCTION__);
198 return false;
199 }
200 return element->template set<Property>(property) == NO_ERROR;
201 }
202
setPhoneState(audio_mode_t mode)203 status_t Engine::setPhoneState(audio_mode_t mode)
204 {
205 if (mPolicyParameterMgr == nullptr) {
206 ALOGE("%s: failed, Cap not initialized", __func__);
207 return NO_INIT;
208 }
209 status_t status = mPolicyParameterMgr->setPhoneState(mode);
210 if (status != NO_ERROR) {
211 return status;
212 }
213 return EngineBase::setPhoneState(mode);
214 }
215
getPhoneState() const216 audio_mode_t Engine::getPhoneState() const
217 {
218 if (mPolicyParameterMgr == nullptr) {
219 ALOGE("%s: failed, Cap not initialized", __func__);
220 return AUDIO_MODE_NORMAL;
221 }
222 return mPolicyParameterMgr->getPhoneState();
223 }
224
setForceUse(audio_policy_force_use_t usage,audio_policy_forced_cfg_t config)225 status_t Engine::setForceUse(audio_policy_force_use_t usage,
226 audio_policy_forced_cfg_t config)
227 {
228 if (mPolicyParameterMgr == nullptr) {
229 ALOGE("%s: failed, Cap not initialized", __func__);
230 return NO_INIT;
231 }
232 status_t status = mPolicyParameterMgr->setForceUse(usage, config);
233 if (status != NO_ERROR) {
234 return status;
235 }
236 return EngineBase::setForceUse(usage, config);
237 }
238
getForceUse(audio_policy_force_use_t usage) const239 audio_policy_forced_cfg_t Engine::getForceUse(audio_policy_force_use_t usage) const
240 {
241 if (mPolicyParameterMgr == nullptr) {
242 ALOGE("%s: failed, Cap not initialized", __func__);
243 return AUDIO_POLICY_FORCE_NONE;
244 }
245 return mPolicyParameterMgr->getForceUse(usage);
246 }
247
setOutputDevicesConnectionState(const DeviceVector & devices,audio_policy_dev_state_t state)248 status_t Engine::setOutputDevicesConnectionState(const DeviceVector &devices,
249 audio_policy_dev_state_t state)
250 {
251 if (mPolicyParameterMgr == nullptr) {
252 ALOGE("%s: failed, Cap not initialized", __func__);
253 return NO_INIT;
254 }
255 for (const auto &device : devices) {
256 mPolicyParameterMgr->setDeviceConnectionState(device->type(), device->address(), state);
257 }
258 DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
259 if (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
260 availableOutputDevices.remove(devices);
261 } else {
262 availableOutputDevices.add(devices);
263 }
264 return mPolicyParameterMgr->setAvailableOutputDevices(availableOutputDevices.types());
265 }
266
setDeviceConnectionState(const sp<DeviceDescriptor> device,audio_policy_dev_state_t state)267 status_t Engine::setDeviceConnectionState(const sp<DeviceDescriptor> device,
268 audio_policy_dev_state_t state)
269 {
270 if (mPolicyParameterMgr == nullptr) {
271 ALOGE("%s: failed, Cap not initialized", __func__);
272 return NO_INIT;
273 }
274 mPolicyParameterMgr->setDeviceConnectionState(device->type(), device->address(), state);
275 if (audio_is_output_device(device->type())) {
276 return mPolicyParameterMgr->setAvailableOutputDevices(
277 getApmObserver()->getAvailableOutputDevices().types());
278 } else if (audio_is_input_device(device->type())) {
279 return mPolicyParameterMgr->setAvailableInputDevices(
280 getApmObserver()->getAvailableInputDevices().types());
281 }
282 return EngineBase::setDeviceConnectionState(device, state);
283 }
284
setDevicesRoleForStrategy(product_strategy_t strategy,device_role_t role,const AudioDeviceTypeAddrVector & devices)285 status_t Engine::setDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role,
286 const AudioDeviceTypeAddrVector &devices)
287 {
288 DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
289 DeviceVector prevDisabledDevices =
290 getDisabledDevicesForProductStrategy(availableOutputDevices, strategy);
291 status_t status = EngineBase::setDevicesRoleForStrategy(strategy, role, devices);
292 if (status != NO_ERROR) {
293 return status;
294 }
295 DeviceVector newDisabledDevices =
296 getDisabledDevicesForProductStrategy(availableOutputDevices, strategy);
297 if (role == DEVICE_ROLE_PREFERRED) {
298 DeviceVector reenabledDevices = prevDisabledDevices;
299 reenabledDevices.remove(newDisabledDevices);
300 if (reenabledDevices.empty()) {
301 ALOGD("%s DEVICE_ROLE_PREFERRED empty renabled devices", __func__);
302 return status;
303 }
304 // some devices were moved from disabled to preferred, need to force a resync for these
305 enableDevicesForStrategy(strategy, prevDisabledDevices);
306 }
307 if (newDisabledDevices.empty()) {
308 return status;
309 }
310 return disableDevicesForStrategy(strategy, newDisabledDevices);
311 }
312
removeDevicesRoleForStrategy(product_strategy_t strategy,device_role_t role,const AudioDeviceTypeAddrVector & devices)313 status_t Engine::removeDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role,
314 const AudioDeviceTypeAddrVector &devices)
315 {
316 const auto productStrategies = getProductStrategies();
317 if (productStrategies.find(strategy) == end(productStrategies)) {
318 ALOGE("%s invalid %d", __func__, strategy);
319 return BAD_VALUE;
320 }
321 DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
322 DeviceVector prevDisabledDevices =
323 getDisabledDevicesForProductStrategy(availableOutputDevices, strategy);
324 status_t status = EngineBase::removeDevicesRoleForStrategy(strategy, role, devices);
325 if (status != NO_ERROR || role == DEVICE_ROLE_PREFERRED) {
326 return status;
327 }
328 // Removing ROLE_DISABLED for given devices, need to force a resync for these
329 enableDevicesForStrategy(strategy, prevDisabledDevices);
330
331 DeviceVector remainingDisabledDevices = getDisabledDevicesForProductStrategy(
332 availableOutputDevices, strategy);
333 if (remainingDisabledDevices.empty()) {
334 return status;
335 }
336 return disableDevicesForStrategy(strategy, remainingDisabledDevices);
337 }
338
clearDevicesRoleForStrategy(product_strategy_t strategy,device_role_t role)339 status_t Engine::clearDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role)
340 {
341 const auto productStrategies = getProductStrategies();
342 if (productStrategies.find(strategy) == end(productStrategies)) {
343 ALOGE("%s invalid %d", __func__, strategy);
344 return BAD_VALUE;
345 }
346 DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
347 DeviceVector prevDisabledDevices =
348 getDisabledDevicesForProductStrategy(availableOutputDevices, strategy);
349 status_t status = EngineBase::clearDevicesRoleForStrategy(strategy, role);
350 if (status != NO_ERROR || role == DEVICE_ROLE_PREFERRED || prevDisabledDevices.empty()) {
351 return status;
352 }
353 // Disabled devices were removed, need to force a resync for these
354 enableDevicesForStrategy(strategy, prevDisabledDevices);
355 return NO_ERROR;
356 }
357
enableDevicesForStrategy(product_strategy_t strategy __unused,const DeviceVector & devicesToEnable)358 void Engine::enableDevicesForStrategy(product_strategy_t strategy __unused,
359 const DeviceVector &devicesToEnable) {
360 // devices were (re)enabled, need to force a resync for these
361 setOutputDevicesConnectionState(devicesToEnable, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);
362 setOutputDevicesConnectionState(devicesToEnable, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
363 }
364
disableDevicesForStrategy(product_strategy_t strategy,const DeviceVector & devicesToDisable)365 status_t Engine::disableDevicesForStrategy(product_strategy_t strategy,
366 const DeviceVector &devicesToDisable) {
367 // Filter out disabled devices for this strategy.
368 // However, to update the output device decision, availability criterion shall be updated,
369 // which may impact other strategies. So, as a WA, reconsider now and later to prevent from
370 // altering decision for other strategies;
371 setOutputDevicesConnectionState(devicesToDisable, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);
372
373 DeviceTypeSet deviceTypes = getProductStrategies().getDeviceTypesForProductStrategy(strategy);
374 const std::string address(getProductStrategies().getDeviceAddressForProductStrategy(strategy));
375
376 setOutputDevicesConnectionState(devicesToDisable, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
377
378 // Force reapply devices for given strategy
379 getProductStrategies().at(strategy)->setDeviceTypes(deviceTypes);
380 setDeviceAddressForProductStrategy(strategy, address);
381 return NO_ERROR;
382 }
383
getDevicesForProductStrategy(product_strategy_t ps) const384 DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t ps) const
385 {
386 DeviceVector selectedDevices = {};
387 DeviceVector disabledDevices = {};
388 const auto productStrategies = getProductStrategies();
389 if (productStrategies.find(ps) == productStrategies.end()) {
390 ALOGE("%s: Trying to get device on invalid strategy %d", __FUNCTION__, ps);
391 return selectedDevices;
392 }
393 DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
394 const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs();
395 DeviceTypeSet availableOutputDevicesTypes = availableOutputDevices.types();
396
397 // check if this strategy has a preferred device that is available,
398 // if yes, give priority to it.
399 DeviceVector preferredAvailableDevVec =
400 getPreferredAvailableDevicesForProductStrategy(availableOutputDevices, ps);
401 if (!preferredAvailableDevVec.isEmpty()) {
402 return preferredAvailableDevVec;
403 }
404
405 /** This is the only case handled programmatically because the PFW is unable to know the
406 * activity of streams.
407 *
408 * -While media is playing on a remote device, use the the sonification behavior.
409 * Note that we test this usecase before testing if media is playing because
410 * the isStreamActive() method only informs about the activity of a stream, not
411 * if it's for local playback. Note also that we use the same delay between both tests
412 *
413 * -When media is not playing anymore, fall back on the sonification behavior
414 */
415 DeviceTypeSet deviceTypes;
416 product_strategy_t psOrFallback = ps;
417 if (ps == getProductStrategyForStream(AUDIO_STREAM_NOTIFICATION) &&
418 !is_state_in_call(getPhoneState()) &&
419 !outputs.isActiveRemotely(toVolumeSource(AUDIO_STREAM_MUSIC),
420 SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY) &&
421 outputs.isActive(toVolumeSource(AUDIO_STREAM_MUSIC),
422 SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
423 psOrFallback = getProductStrategyForStream(AUDIO_STREAM_MUSIC);
424 } else if (ps == getProductStrategyForStream(AUDIO_STREAM_ACCESSIBILITY) &&
425 (outputs.isActive(toVolumeSource(AUDIO_STREAM_RING)) ||
426 outputs.isActive(toVolumeSource(AUDIO_STREAM_ALARM)))) {
427 // do not route accessibility prompts to a digital output currently configured with a
428 // compressed format as they would likely not be mixed and dropped.
429 // Device For Sonification conf file has HDMI, SPDIF and HDMI ARC unreacheable.
430 psOrFallback = getProductStrategyForStream(AUDIO_STREAM_RING);
431 }
432 disabledDevices = getDisabledDevicesForProductStrategy(availableOutputDevices, psOrFallback);
433 deviceTypes = productStrategies.getDeviceTypesForProductStrategy(psOrFallback);
434 // In case a fallback is decided on other strategy, prevent from selecting this device if
435 // disabled for current strategy.
436 availableOutputDevices.remove(disabledDevices);
437
438 if (deviceTypes.empty() ||
439 Intersection(deviceTypes, availableOutputDevicesTypes).empty()) {
440 auto defaultDevice = getApmObserver()->getDefaultOutputDevice();
441 ALOG_ASSERT(defaultDevice != nullptr, "no valid default device defined");
442 selectedDevices = DeviceVector(defaultDevice);
443 } else if (/*device_distinguishes_on_address(*deviceTypes.begin())*/
444 isSingleDeviceType(deviceTypes, AUDIO_DEVICE_OUT_BUS) ||
445 isSingleDeviceType(deviceTypes, AUDIO_DEVICE_OUT_SPEAKER)) {
446 // We do expect only one device for these types of devices
447 // Criterion device address garantee this one is available
448 // If this criterion is not wished, need to ensure this device is available
449 const String8 address(productStrategies.getDeviceAddressForProductStrategy(ps).c_str());
450 ALOGV("%s:device %s %s %d",
451 __FUNCTION__, dumpDeviceTypes(deviceTypes).c_str(), address.c_str(), ps);
452 auto busDevice = availableOutputDevices.getDevice(
453 *deviceTypes.begin(), address, AUDIO_FORMAT_DEFAULT);
454 if (busDevice == nullptr) {
455 ALOGE("%s:unavailable device %s %s, fallback on default", __func__,
456 dumpDeviceTypes(deviceTypes).c_str(), address.c_str());
457 auto defaultDevice = getApmObserver()->getDefaultOutputDevice();
458 ALOG_ASSERT(defaultDevice != nullptr, "Default Output Device NOT available");
459 selectedDevices = DeviceVector(defaultDevice);
460 } else {
461 selectedDevices = DeviceVector(busDevice);
462 }
463 } else {
464 ALOGV("%s:device %s %d", __FUNCTION__, dumpDeviceTypes(deviceTypes).c_str(), ps);
465 selectedDevices = availableOutputDevices.getDevicesFromTypes(deviceTypes);
466 }
467 return selectedDevices;
468 }
469
getOutputDevicesForAttributes(const audio_attributes_t & attributes,const sp<DeviceDescriptor> & preferredDevice,bool fromCache) const470 DeviceVector Engine::getOutputDevicesForAttributes(const audio_attributes_t &attributes,
471 const sp<DeviceDescriptor> &preferredDevice,
472 bool fromCache) const
473 {
474 // First check for explict routing device
475 if (preferredDevice != nullptr) {
476 ALOGV("%s explicit Routing on device %s", __func__, preferredDevice->toString().c_str());
477 return DeviceVector(preferredDevice);
478 }
479 product_strategy_t strategy = getProductStrategyForAttributes(attributes);
480 const DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
481 const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs();
482 //
483 // @TODO: what is the priority of explicit routing? Shall it be considered first as it used to
484 // be by APM?
485 //
486 // Honor explicit routing requests only if all active clients have a preferred route in which
487 // case the last active client route is used
488 sp<DeviceDescriptor> device = findPreferredDevice(outputs, strategy, availableOutputDevices);
489 if (device != nullptr) {
490 return DeviceVector(device);
491 }
492 return fromCache? getCachedDevices(strategy) : getDevicesForProductStrategy(strategy);
493 }
494
getCachedDevices(product_strategy_t ps) const495 DeviceVector Engine::getCachedDevices(product_strategy_t ps) const
496 {
497 return mDevicesForStrategies.find(ps) != mDevicesForStrategies.end() ?
498 mDevicesForStrategies.at(ps) : DeviceVector{};
499 }
500
getOutputDevicesForStream(audio_stream_type_t stream,bool fromCache) const501 DeviceVector Engine::getOutputDevicesForStream(audio_stream_type_t stream, bool fromCache) const
502 {
503 auto attributes = EngineBase::getAttributesForStreamType(stream);
504 return getOutputDevicesForAttributes(attributes, nullptr, fromCache);
505 }
506
getInputDeviceForAttributes(const audio_attributes_t & attr,bool ignorePreferredDevice,uid_t uid,audio_session_t session,sp<AudioPolicyMix> * mix) const507 sp<DeviceDescriptor> Engine::getInputDeviceForAttributes(const audio_attributes_t &attr,
508 bool ignorePreferredDevice,
509 uid_t uid,
510 audio_session_t session,
511 sp<AudioPolicyMix> *mix) const
512 {
513 const auto &policyMixes = getApmObserver()->getAudioPolicyMixCollection();
514 const auto availableInputDevices = getApmObserver()->getAvailableInputDevices();
515 const auto &inputs = getApmObserver()->getInputs();
516 std::string address;
517 //
518 // Explicit Routing ??? what is the priority of explicit routing? Shall it be considered
519 // first as it used to be by APM?
520 //
521 // Honor explicit routing requests only if all active clients have a preferred route in which
522 // case the last active client route is used
523 sp<DeviceDescriptor> device;
524 if (!com::android::media::audioserver::conditionally_ignore_preferred_input_device()
525 || !ignorePreferredDevice) {
526 device = findPreferredDevice(inputs, attr.source, availableInputDevices);
527 if (device != nullptr) {
528 return device;
529 }
530 }
531
532 device = policyMixes.getDeviceAndMixForInputSource(attr,
533 availableInputDevices,
534 uid,
535 session,
536 mix);
537 if (device != nullptr) {
538 return device;
539 }
540
541 audio_devices_t deviceType = getPropertyForKey<audio_devices_t, audio_source_t>(attr.source);
542
543 if (deviceType == AUDIO_DEVICE_IN_ECHO_REFERENCE) {
544 device = getInputDeviceForEchoRef(attr, availableInputDevices);
545 if (device != nullptr) {
546 return device;
547 }
548 }
549
550
551 if (audio_is_remote_submix_device(deviceType)) {
552 address = "0";
553 std::size_t pos;
554 std::string tags { attr.tags };
555 if ((pos = tags.find("addr=")) != std::string::npos) {
556 address = tags.substr(pos + std::strlen("addr="));
557 }
558 }
559 return availableInputDevices.getDevice(deviceType, String8(address.c_str()), AUDIO_FORMAT_DEFAULT);
560 }
561
setDeviceAddressForProductStrategy(product_strategy_t strategy,const std::string & address)562 void Engine::setDeviceAddressForProductStrategy(product_strategy_t strategy,
563 const std::string &address)
564 {
565 if (getProductStrategies().find(strategy) == getProductStrategies().end()) {
566 ALOGE("%s: Trying to set address %s on invalid strategy %d", __FUNCTION__, address.c_str(),
567 strategy);
568 return;
569 }
570 getProductStrategies().at(strategy)->setDeviceAddress(address);
571 }
572
setDeviceTypesForProductStrategy(product_strategy_t strategy,uint64_t devices)573 bool Engine::setDeviceTypesForProductStrategy(product_strategy_t strategy, uint64_t devices)
574 {
575 if (mPolicyParameterMgr == nullptr) {
576 ALOGE("%s: failed, Cap not initialized", __func__);
577 return false;
578 }
579 if (getProductStrategies().find(strategy) == getProductStrategies().end()) {
580 ALOGE("%s: set device %" PRId64 " on invalid strategy %d", __FUNCTION__, devices, strategy);
581 return false;
582 }
583 // Here device matches the criterion value, need to rebuitd android device types;
584 DeviceTypeSet types =
585 mPolicyParameterMgr->convertDeviceCriterionValueToDeviceTypes(devices, true /*isOut*/);
586 getProductStrategies().at(strategy)->setDeviceTypes(types);
587 return true;
588 }
589
setDeviceForInputSource(const audio_source_t & inputSource,uint64_t device)590 bool Engine::setDeviceForInputSource(const audio_source_t &inputSource, uint64_t device)
591 {
592 if (mPolicyParameterMgr == nullptr) {
593 ALOGE("%s: failed, Cap not initialized", __func__);
594 return false;
595 }
596 DeviceTypeSet types = mPolicyParameterMgr->convertDeviceCriterionValueToDeviceTypes(
597 device, false /*isOut*/);
598 ALOG_ASSERT(types.size() <= 1, "one input device expected at most");
599 audio_devices_t deviceType = types.empty() ? AUDIO_DEVICE_IN_DEFAULT : *types.begin();
600 return setPropertyForKey<audio_devices_t, audio_source_t>(deviceType, inputSource);
601 }
602
603 template <>
queryInterface()604 EngineInterface *Engine::queryInterface()
605 {
606 return this;
607 }
608
609 template <>
queryInterface()610 AudioPolicyPluginInterface *Engine::queryInterface()
611 {
612 return this;
613 }
614
615 } // namespace audio_policy
616 } // namespace android
617