• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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