• 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 <ParameterManagerWrapper.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 
Engine()69 Engine::Engine() : mPolicyParameterMgr(new ParameterManagerWrapper())
70 {
71 }
72 
loadFromHalConfigWithFallback(const media::audio::common::AudioHalEngineConfig & config __unused)73 status_t Engine::loadFromHalConfigWithFallback(
74         const media::audio::common::AudioHalEngineConfig& config __unused) {
75     // b/242678729. Need to implement for the configurable engine.
76     return INVALID_OPERATION;
77 }
78 
loadFromXmlConfigWithFallback(const std::string & xmlFilePath)79 status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath)
80 {
81     status_t loadResult = loadAudioPolicyEngineConfig(xmlFilePath);
82     if (loadResult < 0) {
83         ALOGE("Policy Engine configuration is invalid.");
84     }
85     return loadResult;
86 }
87 
initCheck()88 status_t Engine::initCheck()
89 {
90     std::string error;
91     if (mPolicyParameterMgr == nullptr || mPolicyParameterMgr->start(error) != NO_ERROR) {
92         ALOGE("%s: could not start Policy PFW: %s", __FUNCTION__, error.c_str());
93         return NO_INIT;
94     }
95     return EngineBase::initCheck();
96 }
97 
98 template <typename Key>
getFromCollection(const Key & key) const99 Element<Key> *Engine::getFromCollection(const Key &key) const
100 {
101     const Collection<Key> &collection = getCollection<Key>();
102     return collection.get(key);
103 }
104 
105 template <typename Key>
add(const std::string & name,const Key & key)106 status_t Engine::add(const std::string &name, const Key &key)
107 {
108     Collection<Key> &collection = getCollection<Key>();
109     return collection.add(name, key);
110 }
111 
112 template <typename Property, typename Key>
getPropertyForKey(Key key) const113 Property Engine::getPropertyForKey(Key key) const
114 {
115     Element<Key> *element = getFromCollection<Key>(key);
116     if (element == NULL) {
117         ALOGE("%s: Element not found within collection", __FUNCTION__);
118         return static_cast<Property>(0);
119     }
120     return element->template get<Property>();
121 }
122 
setVolumeProfileForStream(const audio_stream_type_t & stream,const audio_stream_type_t & profile)123 bool Engine::setVolumeProfileForStream(const audio_stream_type_t &stream,
124                                        const audio_stream_type_t &profile)
125 {
126     if (setPropertyForKey<audio_stream_type_t, audio_stream_type_t>(stream, profile)) {
127         switchVolumeCurve(profile, stream);
128         return true;
129     }
130     return false;
131 }
132 
133 template <typename Property, typename Key>
setPropertyForKey(const Property & property,const Key & key)134 bool Engine::setPropertyForKey(const Property &property, const Key &key)
135 {
136     Element<Key> *element = getFromCollection<Key>(key);
137     if (element == NULL) {
138         ALOGE("%s: Element not found within collection", __FUNCTION__);
139         return false;
140     }
141     return element->template set<Property>(property) == NO_ERROR;
142 }
143 
setPhoneState(audio_mode_t mode)144 status_t Engine::setPhoneState(audio_mode_t mode)
145 {
146     status_t status = mPolicyParameterMgr->setPhoneState(mode);
147     if (status != NO_ERROR) {
148         return status;
149     }
150     return EngineBase::setPhoneState(mode);
151 }
152 
getPhoneState() const153 audio_mode_t Engine::getPhoneState() const
154 {
155     return mPolicyParameterMgr->getPhoneState();
156 }
157 
setForceUse(audio_policy_force_use_t usage,audio_policy_forced_cfg_t config)158 status_t Engine::setForceUse(audio_policy_force_use_t usage,
159                                       audio_policy_forced_cfg_t config)
160 {
161     status_t status = mPolicyParameterMgr->setForceUse(usage, config);
162     if (status != NO_ERROR) {
163         return status;
164     }
165     return EngineBase::setForceUse(usage, config);
166 }
167 
getForceUse(audio_policy_force_use_t usage) const168 audio_policy_forced_cfg_t Engine::getForceUse(audio_policy_force_use_t usage) const
169 {
170     return mPolicyParameterMgr->getForceUse(usage);
171 }
172 
setOutputDevicesConnectionState(const DeviceVector & devices,audio_policy_dev_state_t state)173 status_t Engine::setOutputDevicesConnectionState(const DeviceVector &devices,
174                                                  audio_policy_dev_state_t state)
175 {
176     for (const auto &device : devices) {
177         mPolicyParameterMgr->setDeviceConnectionState(device->type(), device->address(), state);
178     }
179     DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
180     if (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
181         availableOutputDevices.remove(devices);
182     } else {
183         availableOutputDevices.add(devices);
184     }
185     return mPolicyParameterMgr->setAvailableOutputDevices(availableOutputDevices.types());
186 }
187 
setDeviceConnectionState(const sp<DeviceDescriptor> device,audio_policy_dev_state_t state)188 status_t Engine::setDeviceConnectionState(const sp<DeviceDescriptor> device,
189                                           audio_policy_dev_state_t state)
190 {
191     mPolicyParameterMgr->setDeviceConnectionState(device->type(), device->address(), state);
192     if (audio_is_output_device(device->type())) {
193         return mPolicyParameterMgr->setAvailableOutputDevices(
194                     getApmObserver()->getAvailableOutputDevices().types());
195     } else if (audio_is_input_device(device->type())) {
196         return mPolicyParameterMgr->setAvailableInputDevices(
197                     getApmObserver()->getAvailableInputDevices().types());
198     }
199     return EngineBase::setDeviceConnectionState(device, state);
200 }
201 
loadAudioPolicyEngineConfig(const std::string & xmlFilePath)202 status_t Engine::loadAudioPolicyEngineConfig(const std::string& xmlFilePath)
203 {
204     auto result = EngineBase::loadAudioPolicyEngineConfig(xmlFilePath);
205 
206     // Custom XML Parsing
207     auto loadCriteria= [this](const auto& configCriteria, const auto& configCriterionTypes) {
208         for (auto& criterion : configCriteria) {
209             engineConfig::CriterionType criterionType;
210             for (auto &configCriterionType : configCriterionTypes) {
211                 if (configCriterionType.name == criterion.typeName) {
212                     criterionType = configCriterionType;
213                     break;
214                 }
215             }
216             ALOG_ASSERT(not criterionType.name.empty(), "Invalid criterion type for %s",
217                         criterion.name.c_str());
218             mPolicyParameterMgr->addCriterion(criterion.name, criterionType.isInclusive,
219                                               criterionType.valuePairs,
220                                               criterion.defaultLiteralValue);
221         }
222     };
223 
224     loadCriteria(result.parsedConfig->criteria, result.parsedConfig->criterionTypes);
225     return result.nbSkippedElement == 0? NO_ERROR : BAD_VALUE;
226 }
227 
setDevicesRoleForStrategy(product_strategy_t strategy,device_role_t role,const AudioDeviceTypeAddrVector & devices)228 status_t Engine::setDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role,
229                                            const AudioDeviceTypeAddrVector &devices)
230 {
231     DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
232     DeviceVector prevDisabledDevices =
233             getDisabledDevicesForProductStrategy(availableOutputDevices, strategy);
234     status_t status = EngineBase::setDevicesRoleForStrategy(strategy, role, devices);
235     if (status != NO_ERROR) {
236         return status;
237     }
238     DeviceVector newDisabledDevices =
239             getDisabledDevicesForProductStrategy(availableOutputDevices, strategy);
240     if (role == DEVICE_ROLE_PREFERRED) {
241         DeviceVector reenabledDevices = prevDisabledDevices;
242         reenabledDevices.remove(newDisabledDevices);
243         if (reenabledDevices.empty()) {
244             ALOGD("%s DEVICE_ROLE_PREFERRED empty renabled devices", __func__);
245             return status;
246         }
247         // some devices were moved from disabled to preferred, need to force a resync for these
248         enableDevicesForStrategy(strategy, prevDisabledDevices);
249     }
250     if (newDisabledDevices.empty()) {
251         return status;
252     }
253     return disableDevicesForStrategy(strategy, newDisabledDevices);
254 }
255 
removeDevicesRoleForStrategy(product_strategy_t strategy,device_role_t role,const AudioDeviceTypeAddrVector & devices)256 status_t Engine::removeDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role,
257         const AudioDeviceTypeAddrVector &devices)
258 {
259     const auto productStrategies = getProductStrategies();
260     if (productStrategies.find(strategy) == end(productStrategies)) {
261         ALOGE("%s invalid %d", __func__, strategy);
262         return BAD_VALUE;
263     }
264     DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
265     DeviceVector prevDisabledDevices =
266             getDisabledDevicesForProductStrategy(availableOutputDevices, strategy);
267     status_t status = EngineBase::removeDevicesRoleForStrategy(strategy, role, devices);
268     if (status != NO_ERROR || role == DEVICE_ROLE_PREFERRED) {
269         return status;
270     }
271     // Removing ROLE_DISABLED for given devices, need to force a resync for these
272     enableDevicesForStrategy(strategy, prevDisabledDevices);
273 
274     DeviceVector remainingDisabledDevices = getDisabledDevicesForProductStrategy(
275             availableOutputDevices, strategy);
276     if (remainingDisabledDevices.empty()) {
277         return status;
278     }
279     return disableDevicesForStrategy(strategy, remainingDisabledDevices);
280 }
281 
clearDevicesRoleForStrategy(product_strategy_t strategy,device_role_t role)282 status_t Engine::clearDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role)
283 {
284     const auto productStrategies = getProductStrategies();
285     if (productStrategies.find(strategy) == end(productStrategies)) {
286         ALOGE("%s invalid %d", __func__, strategy);
287         return BAD_VALUE;
288     }
289     DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
290     DeviceVector prevDisabledDevices =
291             getDisabledDevicesForProductStrategy(availableOutputDevices, strategy);
292     status_t status = EngineBase::clearDevicesRoleForStrategy(strategy, role);
293     if (status != NO_ERROR || role == DEVICE_ROLE_PREFERRED || prevDisabledDevices.empty()) {
294         return status;
295     }
296     // Disabled devices were removed, need to force a resync for these
297     enableDevicesForStrategy(strategy, prevDisabledDevices);
298     return NO_ERROR;
299 }
300 
enableDevicesForStrategy(product_strategy_t strategy __unused,const DeviceVector & devicesToEnable)301 void Engine::enableDevicesForStrategy(product_strategy_t strategy __unused,
302         const DeviceVector &devicesToEnable) {
303     // devices were (re)enabled, need to force a resync for these
304     setOutputDevicesConnectionState(devicesToEnable, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);
305     setOutputDevicesConnectionState(devicesToEnable, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
306 }
307 
disableDevicesForStrategy(product_strategy_t strategy,const DeviceVector & devicesToDisable)308 status_t Engine::disableDevicesForStrategy(product_strategy_t strategy,
309         const DeviceVector &devicesToDisable) {
310     // Filter out disabled devices for this strategy.
311     // However, to update the output device decision, availability criterion shall be updated,
312     // which may impact other strategies. So, as a WA, reconsider now and later to prevent from
313     // altering decision for other strategies;
314     setOutputDevicesConnectionState(devicesToDisable, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);
315 
316     DeviceTypeSet deviceTypes = getProductStrategies().getDeviceTypesForProductStrategy(strategy);
317     const std::string address(getProductStrategies().getDeviceAddressForProductStrategy(strategy));
318 
319     setOutputDevicesConnectionState(devicesToDisable, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
320 
321     // Force reapply devices for given strategy
322     getProductStrategies().at(strategy)->setDeviceTypes(deviceTypes);
323     setDeviceAddressForProductStrategy(strategy, address);
324     return NO_ERROR;
325 }
326 
getDevicesForProductStrategy(product_strategy_t ps) const327 DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t ps) const
328 {
329     DeviceVector selectedDevices = {};
330     DeviceVector disabledDevices = {};
331     const auto productStrategies = getProductStrategies();
332     if (productStrategies.find(ps) == productStrategies.end()) {
333         ALOGE("%s: Trying to get device on invalid strategy %d", __FUNCTION__, ps);
334         return selectedDevices;
335     }
336     DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
337     const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs();
338     DeviceTypeSet availableOutputDevicesTypes = availableOutputDevices.types();
339 
340     // check if this strategy has a preferred device that is available,
341     // if yes, give priority to it.
342     DeviceVector preferredAvailableDevVec =
343             getPreferredAvailableDevicesForProductStrategy(availableOutputDevices, ps);
344     if (!preferredAvailableDevVec.isEmpty()) {
345         return preferredAvailableDevVec;
346     }
347 
348     /** This is the only case handled programmatically because the PFW is unable to know the
349      * activity of streams.
350      *
351      * -While media is playing on a remote device, use the the sonification behavior.
352      * Note that we test this usecase before testing if media is playing because
353      * the isStreamActive() method only informs about the activity of a stream, not
354      * if it's for local playback. Note also that we use the same delay between both tests
355      *
356      * -When media is not playing anymore, fall back on the sonification behavior
357      */
358     DeviceTypeSet deviceTypes;
359     product_strategy_t psOrFallback = ps;
360     if (ps == getProductStrategyForStream(AUDIO_STREAM_NOTIFICATION) &&
361             !is_state_in_call(getPhoneState()) &&
362             !outputs.isActiveRemotely(toVolumeSource(AUDIO_STREAM_MUSIC),
363                                       SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY) &&
364             outputs.isActive(toVolumeSource(AUDIO_STREAM_MUSIC),
365                              SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
366         psOrFallback = getProductStrategyForStream(AUDIO_STREAM_MUSIC);
367     } else if (ps == getProductStrategyForStream(AUDIO_STREAM_ACCESSIBILITY) &&
368         (outputs.isActive(toVolumeSource(AUDIO_STREAM_RING)) ||
369          outputs.isActive(toVolumeSource(AUDIO_STREAM_ALARM)))) {
370             // do not route accessibility prompts to a digital output currently configured with a
371             // compressed format as they would likely not be mixed and dropped.
372             // Device For Sonification conf file has HDMI, SPDIF and HDMI ARC unreacheable.
373         psOrFallback = getProductStrategyForStream(AUDIO_STREAM_RING);
374     }
375     disabledDevices = getDisabledDevicesForProductStrategy(availableOutputDevices, psOrFallback);
376     deviceTypes = productStrategies.getDeviceTypesForProductStrategy(psOrFallback);
377     // In case a fallback is decided on other strategy, prevent from selecting this device if
378     // disabled for current strategy.
379     availableOutputDevices.remove(disabledDevices);
380 
381     if (deviceTypes.empty() ||
382             Intersection(deviceTypes, availableOutputDevicesTypes).empty()) {
383         auto defaultDevice = getApmObserver()->getDefaultOutputDevice();
384         ALOG_ASSERT(defaultDevice != nullptr, "no valid default device defined");
385         selectedDevices = DeviceVector(defaultDevice);
386     } else if (/*device_distinguishes_on_address(*deviceTypes.begin())*/ isSingleDeviceType(
387             deviceTypes, AUDIO_DEVICE_OUT_BUS)) {
388         // We do expect only one device for these types of devices
389         // Criterion device address garantee this one is available
390         // If this criterion is not wished, need to ensure this device is available
391         const String8 address(productStrategies.getDeviceAddressForProductStrategy(ps).c_str());
392         ALOGV("%s:device %s %s %d",
393                 __FUNCTION__, dumpDeviceTypes(deviceTypes).c_str(), address.c_str(), ps);
394         auto busDevice = availableOutputDevices.getDevice(
395                 *deviceTypes.begin(), address, AUDIO_FORMAT_DEFAULT);
396         if (busDevice == nullptr) {
397             ALOGE("%s:unavailable device %s %s, fallback on default", __func__,
398                   dumpDeviceTypes(deviceTypes).c_str(), address.c_str());
399             auto defaultDevice = getApmObserver()->getDefaultOutputDevice();
400             ALOG_ASSERT(defaultDevice != nullptr, "Default Output Device NOT available");
401             selectedDevices = DeviceVector(defaultDevice);
402         } else {
403             selectedDevices = DeviceVector(busDevice);
404         }
405     } else {
406         ALOGV("%s:device %s %d", __FUNCTION__, dumpDeviceTypes(deviceTypes).c_str(), ps);
407         selectedDevices = availableOutputDevices.getDevicesFromTypes(deviceTypes);
408     }
409     return selectedDevices;
410 }
411 
getOutputDevicesForAttributes(const audio_attributes_t & attributes,const sp<DeviceDescriptor> & preferredDevice,bool fromCache) const412 DeviceVector Engine::getOutputDevicesForAttributes(const audio_attributes_t &attributes,
413                                                    const sp<DeviceDescriptor> &preferredDevice,
414                                                    bool fromCache) const
415 {
416     // First check for explict routing device
417     if (preferredDevice != nullptr) {
418         ALOGV("%s explicit Routing on device %s", __func__, preferredDevice->toString().c_str());
419         return DeviceVector(preferredDevice);
420     }
421     product_strategy_t strategy = getProductStrategyForAttributes(attributes);
422     const DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
423     const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs();
424     //
425     // @TODO: what is the priority of explicit routing? Shall it be considered first as it used to
426     // be by APM?
427     //
428     // Honor explicit routing requests only if all active clients have a preferred route in which
429     // case the last active client route is used
430     sp<DeviceDescriptor> device = findPreferredDevice(outputs, strategy, availableOutputDevices);
431     if (device != nullptr) {
432         return DeviceVector(device);
433     }
434     return fromCache? getCachedDevices(strategy) : getDevicesForProductStrategy(strategy);
435 }
436 
getCachedDevices(product_strategy_t ps) const437 DeviceVector Engine::getCachedDevices(product_strategy_t ps) const
438 {
439     return mDevicesForStrategies.find(ps) != mDevicesForStrategies.end() ?
440                 mDevicesForStrategies.at(ps) : DeviceVector{};
441 }
442 
getOutputDevicesForStream(audio_stream_type_t stream,bool fromCache) const443 DeviceVector Engine::getOutputDevicesForStream(audio_stream_type_t stream, bool fromCache) const
444 {
445     auto attributes = EngineBase::getAttributesForStreamType(stream);
446     return getOutputDevicesForAttributes(attributes, nullptr, fromCache);
447 }
448 
getInputDeviceForAttributes(const audio_attributes_t & attr,uid_t uid,audio_session_t session,sp<AudioPolicyMix> * mix) const449 sp<DeviceDescriptor> Engine::getInputDeviceForAttributes(const audio_attributes_t &attr,
450                                                          uid_t uid,
451                                                          audio_session_t session,
452                                                          sp<AudioPolicyMix> *mix) const
453 {
454     const auto &policyMixes = getApmObserver()->getAudioPolicyMixCollection();
455     const auto availableInputDevices = getApmObserver()->getAvailableInputDevices();
456     const auto &inputs = getApmObserver()->getInputs();
457     std::string address;
458     //
459     // Explicit Routing ??? what is the priority of explicit routing? Shall it be considered
460     // first as it used to be by APM?
461     //
462     // Honor explicit routing requests only if all active clients have a preferred route in which
463     // case the last active client route is used
464     sp<DeviceDescriptor> device =
465             findPreferredDevice(inputs, attr.source, availableInputDevices);
466     if (device != nullptr) {
467         return device;
468     }
469 
470     device = policyMixes.getDeviceAndMixForInputSource(attr,
471                                                        availableInputDevices,
472                                                        uid,
473                                                        session,
474                                                        mix);
475     if (device != nullptr) {
476         return device;
477     }
478 
479     audio_devices_t deviceType = getPropertyForKey<audio_devices_t, audio_source_t>(attr.source);
480 
481     if (audio_is_remote_submix_device(deviceType)) {
482         address = "0";
483         std::size_t pos;
484         std::string tags { attr.tags };
485         if ((pos = tags.find("addr=")) != std::string::npos) {
486             address = tags.substr(pos + std::strlen("addr="));
487         }
488     }
489     return availableInputDevices.getDevice(deviceType, String8(address.c_str()), AUDIO_FORMAT_DEFAULT);
490 }
491 
setDeviceAddressForProductStrategy(product_strategy_t strategy,const std::string & address)492 void Engine::setDeviceAddressForProductStrategy(product_strategy_t strategy,
493                                                 const std::string &address)
494 {
495     if (getProductStrategies().find(strategy) == getProductStrategies().end()) {
496         ALOGE("%s: Trying to set address %s on invalid strategy %d", __FUNCTION__, address.c_str(),
497               strategy);
498         return;
499     }
500     getProductStrategies().at(strategy)->setDeviceAddress(address);
501 }
502 
setDeviceTypesForProductStrategy(product_strategy_t strategy,uint64_t devices)503 bool Engine::setDeviceTypesForProductStrategy(product_strategy_t strategy, uint64_t devices)
504 {
505     if (getProductStrategies().find(strategy) == getProductStrategies().end()) {
506         ALOGE("%s: set device %" PRId64 " on invalid strategy %d", __FUNCTION__, devices, strategy);
507         return false;
508     }
509     // Here device matches the criterion value, need to rebuitd android device types;
510     DeviceTypeSet types =
511             mPolicyParameterMgr->convertDeviceCriterionValueToDeviceTypes(devices, true /*isOut*/);
512     getProductStrategies().at(strategy)->setDeviceTypes(types);
513     return true;
514 }
515 
setDeviceForInputSource(const audio_source_t & inputSource,uint64_t device)516 bool Engine::setDeviceForInputSource(const audio_source_t &inputSource, uint64_t device)
517 {
518     DeviceTypeSet types = mPolicyParameterMgr->convertDeviceCriterionValueToDeviceTypes(
519                 device, false /*isOut*/);
520     ALOG_ASSERT(types.size() <= 1, "one input device expected at most");
521     audio_devices_t deviceType = types.empty() ? AUDIO_DEVICE_IN_DEFAULT : *types.begin();
522     return setPropertyForKey<audio_devices_t, audio_source_t>(deviceType, inputSource);
523 }
524 
525 template <>
queryInterface()526 EngineInterface *Engine::queryInterface()
527 {
528     return this;
529 }
530 
531 template <>
queryInterface()532 AudioPolicyPluginInterface *Engine::queryInterface()
533 {
534     return this;
535 }
536 
537 } // namespace audio_policy
538 } // namespace android
539