• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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/Base"
18 //#define LOG_NDEBUG 0
19 
20 #include <functional>
21 #include <string>
22 #include <sys/stat.h>
23 
24 #include "EngineBase.h"
25 #include "EngineDefaultConfig.h"
26 #include <TypeConverter.h>
27 
28 namespace android {
29 namespace audio_policy {
30 
setObserver(AudioPolicyManagerObserver * observer)31 void EngineBase::setObserver(AudioPolicyManagerObserver *observer)
32 {
33     ALOG_ASSERT(observer != NULL, "Invalid Audio Policy Manager observer");
34     mApmObserver = observer;
35 }
36 
initCheck()37 status_t EngineBase::initCheck()
38 {
39     return (mApmObserver != nullptr)? NO_ERROR : NO_INIT;
40 }
41 
setPhoneState(audio_mode_t state)42 status_t EngineBase::setPhoneState(audio_mode_t state)
43 {
44     ALOGV("setPhoneState() state %d", state);
45 
46     if (state < 0 || uint32_t(state) >= AUDIO_MODE_CNT) {
47         ALOGW("setPhoneState() invalid state %d", state);
48         return BAD_VALUE;
49     }
50 
51     if (state == mPhoneState ) {
52         ALOGW("setPhoneState() setting same state %d", state);
53         return BAD_VALUE;
54     }
55 
56     // store previous phone state for management of sonification strategy below
57     int oldState = mPhoneState;
58     mPhoneState = state;
59 
60     if (!is_state_in_call(oldState) && is_state_in_call(state)) {
61         ALOGV("  Entering call in setPhoneState()");
62         switchVolumeCurve(AUDIO_STREAM_VOICE_CALL, AUDIO_STREAM_DTMF);
63     } else if (is_state_in_call(oldState) && !is_state_in_call(state)) {
64         ALOGV("  Exiting call in setPhoneState()");
65         restoreOriginVolumeCurve(AUDIO_STREAM_DTMF);
66     }
67     return NO_ERROR;
68 }
69 
setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,audio_policy_dev_state_t state)70 status_t EngineBase::setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
71                                               audio_policy_dev_state_t state)
72 {
73     audio_devices_t deviceType = devDesc->type();
74     if ((deviceType != AUDIO_DEVICE_NONE) && audio_is_output_device(deviceType)) {
75         mLastRemovableMediaDevices.setRemovableMediaDevices(devDesc, state);
76     }
77 
78     return NO_ERROR;
79 }
80 
getProductStrategyForAttributes(const audio_attributes_t & attr,bool fallbackOnDefault) const81 product_strategy_t EngineBase::getProductStrategyForAttributes(
82         const audio_attributes_t &attr, bool fallbackOnDefault) const
83 {
84     return mProductStrategies.getProductStrategyForAttributes(attr, fallbackOnDefault);
85 }
86 
getStreamTypeForAttributes(const audio_attributes_t & attr) const87 audio_stream_type_t EngineBase::getStreamTypeForAttributes(const audio_attributes_t &attr) const
88 {
89     return mProductStrategies.getStreamTypeForAttributes(attr);
90 }
91 
getAttributesForStreamType(audio_stream_type_t stream) const92 audio_attributes_t EngineBase::getAttributesForStreamType(audio_stream_type_t stream) const
93 {
94     return mProductStrategies.getAttributesForStreamType(stream);
95 }
96 
getProductStrategyForStream(audio_stream_type_t stream) const97 product_strategy_t EngineBase::getProductStrategyForStream(audio_stream_type_t stream) const
98 {
99     return mProductStrategies.getProductStrategyForStream(stream);
100 }
101 
getProductStrategyByName(const std::string & name) const102 product_strategy_t EngineBase::getProductStrategyByName(const std::string &name) const
103 {
104     for (const auto &iter : mProductStrategies) {
105         if (iter.second->getName() == name) {
106             return iter.second->getId();
107         }
108     }
109     return PRODUCT_STRATEGY_NONE;
110 }
111 
loadAudioPolicyEngineConfig()112 engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig()
113 {
114     auto loadVolumeConfig = [](auto &volumeGroups, auto &volumeConfig) {
115         // Ensure name unicity to prevent duplicate
116         LOG_ALWAYS_FATAL_IF(std::any_of(std::begin(volumeGroups), std::end(volumeGroups),
117                                      [&volumeConfig](const auto &volumeGroup) {
118                 return volumeConfig.name == volumeGroup.second->getName(); }),
119                             "group name %s defined twice, review the configuration",
120                             volumeConfig.name.c_str());
121 
122         sp<VolumeGroup> volumeGroup = new VolumeGroup(volumeConfig.name, volumeConfig.indexMin,
123                                                       volumeConfig.indexMax);
124         volumeGroups[volumeGroup->getId()] = volumeGroup;
125 
126         for (auto &configCurve : volumeConfig.volumeCurves) {
127             device_category deviceCat = DEVICE_CATEGORY_SPEAKER;
128             if (!DeviceCategoryConverter::fromString(configCurve.deviceCategory, deviceCat)) {
129                 ALOGE("%s: Invalid %s", __FUNCTION__, configCurve.deviceCategory.c_str());
130                 continue;
131             }
132             sp<VolumeCurve> curve = new VolumeCurve(deviceCat);
133             for (auto &point : configCurve.curvePoints) {
134                 curve->add({point.index, point.attenuationInMb});
135             }
136             volumeGroup->add(curve);
137         }
138         return volumeGroup;
139     };
140     auto addSupportedAttributesToGroup = [](auto &group, auto &volumeGroup, auto &strategy) {
141         for (const auto &attr : group.attributesVect) {
142             strategy->addAttributes({group.stream, volumeGroup->getId(), attr});
143             volumeGroup->addSupportedAttributes(attr);
144         }
145     };
146     auto checkStreamForGroups = [](auto streamType, const auto &volumeGroups) {
147         const auto &iter = std::find_if(std::begin(volumeGroups), std::end(volumeGroups),
148                                      [&streamType](const auto &volumeGroup) {
149             const auto& streams = volumeGroup.second->getStreamTypes();
150             return std::find(std::begin(streams), std::end(streams), streamType) !=
151                     std::end(streams);
152         });
153         return iter != end(volumeGroups);
154     };
155     auto fileExists = [](const char* path) {
156         struct stat fileStat;
157         return stat(path, &fileStat) == 0 && S_ISREG(fileStat.st_mode);
158     };
159 
160     auto result = fileExists(engineConfig::DEFAULT_PATH) ?
161             engineConfig::parse(engineConfig::DEFAULT_PATH) : engineConfig::ParsingResult{};
162     if (result.parsedConfig == nullptr) {
163         ALOGD("%s: No configuration found, using default matching phone experience.", __FUNCTION__);
164         engineConfig::Config config = gDefaultEngineConfig;
165         android::status_t ret = engineConfig::parseLegacyVolumes(config.volumeGroups);
166         result = {std::make_unique<engineConfig::Config>(config),
167                   static_cast<size_t>(ret == NO_ERROR ? 0 : 1)};
168     } else {
169         // Append for internal use only volume groups (e.g. rerouting/patch)
170         result.parsedConfig->volumeGroups.insert(
171                     std::end(result.parsedConfig->volumeGroups),
172                     std::begin(gSystemVolumeGroups), std::end(gSystemVolumeGroups));
173     }
174     // Append for internal use only strategies (e.g. rerouting/patch)
175     result.parsedConfig->productStrategies.insert(
176                 std::end(result.parsedConfig->productStrategies),
177                 std::begin(gOrderedSystemStrategies), std::end(gOrderedSystemStrategies));
178 
179 
180     ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement);
181 
182     engineConfig::VolumeGroup defaultVolumeConfig;
183     engineConfig::VolumeGroup defaultSystemVolumeConfig;
184     for (auto &volumeConfig : result.parsedConfig->volumeGroups) {
185         // save default volume config for streams not defined in configuration
186         if (volumeConfig.name.compare("AUDIO_STREAM_MUSIC") == 0) {
187             defaultVolumeConfig = volumeConfig;
188         }
189         if (volumeConfig.name.compare("AUDIO_STREAM_PATCH") == 0) {
190             defaultSystemVolumeConfig = volumeConfig;
191         }
192         loadVolumeConfig(mVolumeGroups, volumeConfig);
193     }
194     for (auto& strategyConfig : result.parsedConfig->productStrategies) {
195         sp<ProductStrategy> strategy = new ProductStrategy(strategyConfig.name);
196         for (const auto &group : strategyConfig.attributesGroups) {
197             const auto &iter = std::find_if(begin(mVolumeGroups), end(mVolumeGroups),
198                                          [&group](const auto &volumeGroup) {
199                     return group.volumeGroup == volumeGroup.second->getName(); });
200             sp<VolumeGroup> volumeGroup = nullptr;
201             // If no volume group provided for this strategy, creates a new one using
202             // Music Volume Group configuration (considered as the default)
203             if (iter == end(mVolumeGroups)) {
204                 engineConfig::VolumeGroup volumeConfig;
205                 if (group.stream >= AUDIO_STREAM_PUBLIC_CNT) {
206                     volumeConfig = defaultSystemVolumeConfig;
207                 } else {
208                     volumeConfig = defaultVolumeConfig;
209                 }
210                 ALOGW("%s: No configuration of %s found, using default volume configuration"
211                         , __FUNCTION__, group.volumeGroup.c_str());
212                 volumeConfig.name = group.volumeGroup;
213                 volumeGroup = loadVolumeConfig(mVolumeGroups, volumeConfig);
214             } else {
215                 volumeGroup = iter->second;
216             }
217             if (group.stream != AUDIO_STREAM_DEFAULT) {
218                 // A legacy stream can be assigned once to a volume group
219                 LOG_ALWAYS_FATAL_IF(checkStreamForGroups(group.stream, mVolumeGroups),
220                                     "stream %s already assigned to a volume group, "
221                                     "review the configuration", toString(group.stream).c_str());
222                 volumeGroup->addSupportedStream(group.stream);
223             }
224             addSupportedAttributesToGroup(group, volumeGroup, strategy);
225         }
226         product_strategy_t strategyId = strategy->getId();
227         mProductStrategies[strategyId] = strategy;
228     }
229     mProductStrategies.initialize();
230     return result;
231 }
232 
getOrderedProductStrategies() const233 StrategyVector EngineBase::getOrderedProductStrategies() const
234 {
235     auto findByFlag = [](const auto &productStrategies, auto flag) {
236         return std::find_if(begin(productStrategies), end(productStrategies),
237                             [&](const auto &strategy) {
238             for (const auto &attributes : strategy.second->getAudioAttributes()) {
239                 if ((attributes.flags & flag) == flag) {
240                     return true;
241                 }
242             }
243             return false;
244         });
245     };
246     auto strategies = mProductStrategies;
247     auto enforcedAudibleStrategyIter = findByFlag(strategies, AUDIO_FLAG_AUDIBILITY_ENFORCED);
248 
249     if (getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED &&
250             enforcedAudibleStrategyIter != strategies.end()) {
251         auto enforcedAudibleStrategy = *enforcedAudibleStrategyIter;
252         strategies.erase(enforcedAudibleStrategyIter);
253         strategies.insert(begin(strategies), enforcedAudibleStrategy);
254     }
255     StrategyVector orderedStrategies;
256     for (const auto &iter : strategies) {
257         orderedStrategies.push_back(iter.second->getId());
258     }
259     return orderedStrategies;
260 }
261 
getStreamTypesForProductStrategy(product_strategy_t ps) const262 StreamTypeVector EngineBase::getStreamTypesForProductStrategy(product_strategy_t ps) const
263 {
264     // @TODO default music stream to control volume if no group?
265     return (mProductStrategies.find(ps) != end(mProductStrategies)) ?
266                 mProductStrategies.at(ps)->getSupportedStreams() :
267                 StreamTypeVector(AUDIO_STREAM_MUSIC);
268 }
269 
getAllAttributesForProductStrategy(product_strategy_t ps) const270 AttributesVector EngineBase::getAllAttributesForProductStrategy(product_strategy_t ps) const
271 {
272     return (mProductStrategies.find(ps) != end(mProductStrategies)) ?
273                 mProductStrategies.at(ps)->getAudioAttributes() : AttributesVector();
274 }
275 
listAudioProductStrategies(AudioProductStrategyVector & strategies) const276 status_t EngineBase::listAudioProductStrategies(AudioProductStrategyVector &strategies) const
277 {
278     for (const auto &iter : mProductStrategies) {
279         const auto &productStrategy = iter.second;
280         strategies.push_back(
281         {productStrategy->getName(), productStrategy->listAudioAttributes(),
282          productStrategy->getId()});
283     }
284     return NO_ERROR;
285 }
286 
getVolumeCurvesForAttributes(const audio_attributes_t & attr) const287 VolumeCurves *EngineBase::getVolumeCurvesForAttributes(const audio_attributes_t &attr) const
288 {
289     volume_group_t volGr = mProductStrategies.getVolumeGroupForAttributes(attr);
290     const auto &iter = mVolumeGroups.find(volGr);
291     LOG_ALWAYS_FATAL_IF(iter == std::end(mVolumeGroups), "No volume groups for %s", toString(attr).c_str());
292     return mVolumeGroups.at(volGr)->getVolumeCurves();
293 }
294 
getVolumeCurvesForStreamType(audio_stream_type_t stream) const295 VolumeCurves *EngineBase::getVolumeCurvesForStreamType(audio_stream_type_t stream) const
296 {
297     volume_group_t volGr = mProductStrategies.getVolumeGroupForStreamType(stream);
298     if (volGr == VOLUME_GROUP_NONE) {
299         volGr = mProductStrategies.getDefaultVolumeGroup();
300     }
301     const auto &iter = mVolumeGroups.find(volGr);
302     LOG_ALWAYS_FATAL_IF(iter == std::end(mVolumeGroups), "No volume groups for %s",
303                 toString(stream).c_str());
304     return mVolumeGroups.at(volGr)->getVolumeCurves();
305 }
306 
switchVolumeCurve(audio_stream_type_t streamSrc,audio_stream_type_t streamDst)307 status_t EngineBase::switchVolumeCurve(audio_stream_type_t streamSrc, audio_stream_type_t streamDst)
308 {
309     auto srcCurves = getVolumeCurvesForStreamType(streamSrc);
310     auto dstCurves = getVolumeCurvesForStreamType(streamDst);
311 
312     if (srcCurves == nullptr || dstCurves == nullptr) {
313         return BAD_VALUE;
314     }
315     return dstCurves->switchCurvesFrom(*srcCurves);
316 }
317 
restoreOriginVolumeCurve(audio_stream_type_t stream)318 status_t EngineBase::restoreOriginVolumeCurve(audio_stream_type_t stream)
319 {
320     VolumeCurves *curves = getVolumeCurvesForStreamType(stream);
321     return curves != nullptr ? curves->switchCurvesFrom(*curves) : BAD_VALUE;
322 }
323 
getVolumeGroups() const324 VolumeGroupVector EngineBase::getVolumeGroups() const
325 {
326     VolumeGroupVector group;
327     for (const auto &iter : mVolumeGroups) {
328         group.push_back(iter.first);
329     }
330     return group;
331 }
332 
getVolumeGroupForAttributes(const audio_attributes_t & attr,bool fallbackOnDefault) const333 volume_group_t EngineBase::getVolumeGroupForAttributes(
334         const audio_attributes_t &attr, bool fallbackOnDefault) const
335 {
336     return mProductStrategies.getVolumeGroupForAttributes(attr, fallbackOnDefault);
337 }
338 
getVolumeGroupForStreamType(audio_stream_type_t stream,bool fallbackOnDefault) const339 volume_group_t EngineBase::getVolumeGroupForStreamType(
340         audio_stream_type_t stream, bool fallbackOnDefault) const
341 {
342     return mProductStrategies.getVolumeGroupForStreamType(stream, fallbackOnDefault);
343 }
344 
listAudioVolumeGroups(AudioVolumeGroupVector & groups) const345 status_t EngineBase::listAudioVolumeGroups(AudioVolumeGroupVector &groups) const
346 {
347     for (const auto &iter : mVolumeGroups) {
348         groups.push_back({iter.second->getName(), iter.second->getId(),
349                           iter.second->getSupportedAttributes(), iter.second->getStreamTypes()});
350     }
351     return NO_ERROR;
352 }
353 
354 namespace {
355 template <typename T>
setDevicesRoleForT(std::map<std::pair<T,device_role_t>,AudioDeviceTypeAddrVector> & tDevicesRoleMap,T t,device_role_t role,const AudioDeviceTypeAddrVector & devices,const std::string & logStr,std::function<bool (T)> p)356 status_t setDevicesRoleForT(
357         std::map<std::pair<T, device_role_t>, AudioDeviceTypeAddrVector>& tDevicesRoleMap,
358         T t, device_role_t role, const AudioDeviceTypeAddrVector &devices,
359         const std::string& logStr, std::function<bool(T)> p) {
360     if (!p(t)) {
361         ALOGE("%s invalid %s %u", __func__, logStr.c_str(), t);
362         return BAD_VALUE;
363     }
364 
365     switch (role) {
366     case DEVICE_ROLE_PREFERRED:
367     case DEVICE_ROLE_DISABLED: {
368         tDevicesRoleMap[std::make_pair(t, role)] = devices;
369         // The preferred devices and disabled devices are mutually exclusive. Once a device is added
370         // the a list, it must be removed from the other one.
371         const device_role_t roleToRemove = role == DEVICE_ROLE_PREFERRED ? DEVICE_ROLE_DISABLED
372                                                                          : DEVICE_ROLE_PREFERRED;
373         auto it = tDevicesRoleMap.find(std::make_pair(t, roleToRemove));
374         if (it != tDevicesRoleMap.end()) {
375             it->second = excludeDeviceTypeAddrsFrom(it->second, devices);
376             if (it->second.empty()) {
377                 tDevicesRoleMap.erase(it);
378             }
379         }
380     } break;
381     case DEVICE_ROLE_NONE:
382         // Intentionally fall-through as it is no need to set device role as none for a strategy.
383     default:
384         ALOGE("%s invalid role %d", __func__, role);
385         return BAD_VALUE;
386     }
387     return NO_ERROR;
388 }
389 
390 template <typename T>
removeAllDevicesRoleForT(std::map<std::pair<T,device_role_t>,AudioDeviceTypeAddrVector> & tDevicesRoleMap,T t,device_role_t role,const std::string & logStr,std::function<bool (T)> p)391 status_t removeAllDevicesRoleForT(
392         std::map<std::pair<T, device_role_t>, AudioDeviceTypeAddrVector>& tDevicesRoleMap,
393         T t, device_role_t role, const std::string& logStr, std::function<bool(T)> p) {
394     if (!p(t)) {
395         ALOGE("%s invalid %s %u", __func__, logStr.c_str(), t);
396         return BAD_VALUE;
397     }
398 
399     switch (role) {
400     case DEVICE_ROLE_PREFERRED:
401     case DEVICE_ROLE_DISABLED:
402         if (tDevicesRoleMap.erase(std::make_pair(t, role)) == 0) {
403             // no preferred/disabled device was set
404             return NAME_NOT_FOUND;
405         }
406         break;
407     case DEVICE_ROLE_NONE:
408         // Intentionally fall-through as it makes no sense to remove devices with
409         // role as DEVICE_ROLE_NONE
410     default:
411         ALOGE("%s invalid role %d", __func__, role);
412         return BAD_VALUE;
413     }
414     return NO_ERROR;
415 }
416 
417 template <typename T>
getDevicesRoleForT(const std::map<std::pair<T,device_role_t>,AudioDeviceTypeAddrVector> & tDevicesRoleMap,T t,device_role_t role,AudioDeviceTypeAddrVector & devices,const std::string & logStr,std::function<bool (T)> p)418 status_t getDevicesRoleForT(
419         const std::map<std::pair<T, device_role_t>, AudioDeviceTypeAddrVector>& tDevicesRoleMap,
420         T t, device_role_t role, AudioDeviceTypeAddrVector &devices, const std::string& logStr,
421         std::function<bool(T)> p) {
422     if (!p(t)) {
423         ALOGE("%s invalid %s %u", __func__, logStr.c_str(), t);
424         return BAD_VALUE;
425     }
426 
427     switch (role) {
428     case DEVICE_ROLE_PREFERRED:
429     case DEVICE_ROLE_DISABLED: {
430         auto it = tDevicesRoleMap.find(std::make_pair(t, role));
431         if (it == tDevicesRoleMap.end()) {
432             ALOGV("%s no device as role %u for %s %u", __func__, role, logStr.c_str(), t);
433             return NAME_NOT_FOUND;
434         }
435 
436         devices = it->second;
437     } break;
438     case DEVICE_ROLE_NONE:
439         // Intentionally fall-through as the DEVICE_ROLE_NONE is never set
440     default:
441         ALOGE("%s invalid role %d", __func__, role);
442         return BAD_VALUE;
443     }
444     return NO_ERROR;
445 }
446 
447 } // namespace
448 
setDevicesRoleForStrategy(product_strategy_t strategy,device_role_t role,const AudioDeviceTypeAddrVector & devices)449 status_t EngineBase::setDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role,
450             const AudioDeviceTypeAddrVector &devices)
451 {
452     std::function<bool(product_strategy_t)> p = [this](product_strategy_t strategy) {
453         return mProductStrategies.find(strategy) != mProductStrategies.end();
454     };
455     return setDevicesRoleForT(
456             mProductStrategyDeviceRoleMap, strategy, role, devices, "strategy" /*logStr*/, p);
457 }
458 
removeDevicesRoleForStrategy(product_strategy_t strategy,device_role_t role)459 status_t EngineBase::removeDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role)
460 {
461     std::function<bool(product_strategy_t)> p = [this](product_strategy_t strategy) {
462         return mProductStrategies.find(strategy) != mProductStrategies.end();
463     };
464     return removeAllDevicesRoleForT(
465             mProductStrategyDeviceRoleMap, strategy, role, "strategy" /*logStr*/, p);
466 }
467 
getDevicesForRoleAndStrategy(product_strategy_t strategy,device_role_t role,AudioDeviceTypeAddrVector & devices) const468 status_t EngineBase::getDevicesForRoleAndStrategy(product_strategy_t strategy, device_role_t role,
469             AudioDeviceTypeAddrVector &devices) const
470 {
471     std::function<bool(product_strategy_t)> p = [this](product_strategy_t strategy) {
472         return mProductStrategies.find(strategy) != mProductStrategies.end();
473     };
474     return getDevicesRoleForT(
475             mProductStrategyDeviceRoleMap, strategy, role, devices, "strategy" /*logStr*/, p);
476 }
477 
setDevicesRoleForCapturePreset(audio_source_t audioSource,device_role_t role,const AudioDeviceTypeAddrVector & devices)478 status_t EngineBase::setDevicesRoleForCapturePreset(audio_source_t audioSource, device_role_t role,
479         const AudioDeviceTypeAddrVector &devices)
480 {
481     std::function<bool(audio_source_t)> p = [](audio_source_t audioSource) {
482         return audio_is_valid_audio_source(audioSource);
483     };
484     return setDevicesRoleForT(
485             mCapturePresetDevicesRoleMap, audioSource, role, devices, "audio source" /*logStr*/, p);
486 }
487 
addDevicesRoleForCapturePreset(audio_source_t audioSource,device_role_t role,const AudioDeviceTypeAddrVector & devices)488 status_t EngineBase::addDevicesRoleForCapturePreset(audio_source_t audioSource, device_role_t role,
489         const AudioDeviceTypeAddrVector &devices)
490 {
491     // verify if the audio source is valid
492     if (!audio_is_valid_audio_source(audioSource)) {
493         ALOGE("%s unknown audio source %u", __func__, audioSource);
494     }
495 
496     switch (role) {
497     case DEVICE_ROLE_PREFERRED:
498     case DEVICE_ROLE_DISABLED: {
499         const auto audioSourceRole = std::make_pair(audioSource, role);
500         mCapturePresetDevicesRoleMap[audioSourceRole] = excludeDeviceTypeAddrsFrom(
501                 mCapturePresetDevicesRoleMap[audioSourceRole], devices);
502         for (const auto &device : devices) {
503             mCapturePresetDevicesRoleMap[audioSourceRole].push_back(device);
504         }
505         // When the devices are set as preferred devices, remove them from the disabled devices.
506         doRemoveDevicesRoleForCapturePreset(
507                 audioSource,
508                 role == DEVICE_ROLE_PREFERRED ? DEVICE_ROLE_DISABLED : DEVICE_ROLE_PREFERRED,
509                 devices,
510                 false /*forceMatched*/);
511     } break;
512     case DEVICE_ROLE_NONE:
513         // Intentionally fall-through as it is no need to set device role as none
514     default:
515         ALOGE("%s invalid role %d", __func__, role);
516         return BAD_VALUE;
517     }
518     return NO_ERROR;
519 }
520 
removeDevicesRoleForCapturePreset(audio_source_t audioSource,device_role_t role,const AudioDeviceTypeAddrVector & devices)521 status_t EngineBase::removeDevicesRoleForCapturePreset(
522         audio_source_t audioSource, device_role_t role, const AudioDeviceTypeAddrVector& devices) {
523     return doRemoveDevicesRoleForCapturePreset(audioSource, role, devices);
524 }
525 
doRemoveDevicesRoleForCapturePreset(audio_source_t audioSource,device_role_t role,const AudioDeviceTypeAddrVector & devices,bool forceMatched)526 status_t EngineBase::doRemoveDevicesRoleForCapturePreset(audio_source_t audioSource,
527         device_role_t role, const AudioDeviceTypeAddrVector& devices, bool forceMatched)
528 {
529     // verify if the audio source is valid
530     if (!audio_is_valid_audio_source(audioSource)) {
531         ALOGE("%s unknown audio source %u", __func__, audioSource);
532     }
533 
534     switch (role) {
535     case DEVICE_ROLE_PREFERRED:
536     case DEVICE_ROLE_DISABLED: {
537         const auto audioSourceRole = std::make_pair(audioSource, role);
538         if (mCapturePresetDevicesRoleMap.find(audioSourceRole) ==
539                 mCapturePresetDevicesRoleMap.end()) {
540             return NAME_NOT_FOUND;
541         }
542         AudioDeviceTypeAddrVector remainingDevices = excludeDeviceTypeAddrsFrom(
543                 mCapturePresetDevicesRoleMap[audioSourceRole], devices);
544         if (forceMatched && remainingDevices.size() !=
545                 mCapturePresetDevicesRoleMap[audioSourceRole].size() - devices.size()) {
546             // There are some devices from `devicesToRemove` that are not shown in the cached record
547             return BAD_VALUE;
548         }
549         mCapturePresetDevicesRoleMap[audioSourceRole] = remainingDevices;
550         if (mCapturePresetDevicesRoleMap[audioSourceRole].empty()) {
551             // Remove the role when device list is empty
552             mCapturePresetDevicesRoleMap.erase(audioSourceRole);
553         }
554     } break;
555     case DEVICE_ROLE_NONE:
556         // Intentionally fall-through as it makes no sense to remove devices with
557         // role as DEVICE_ROLE_NONE
558     default:
559         ALOGE("%s invalid role %d", __func__, role);
560         return BAD_VALUE;
561     }
562     return NO_ERROR;
563 }
564 
clearDevicesRoleForCapturePreset(audio_source_t audioSource,device_role_t role)565 status_t EngineBase::clearDevicesRoleForCapturePreset(audio_source_t audioSource,
566                                                       device_role_t role)
567 {
568     std::function<bool(audio_source_t)> p = [](audio_source_t audioSource) {
569         return audio_is_valid_audio_source(audioSource);
570     };
571     return removeAllDevicesRoleForT(
572             mCapturePresetDevicesRoleMap, audioSource, role, "audio source" /*logStr*/, p);
573 }
574 
getDevicesForRoleAndCapturePreset(audio_source_t audioSource,device_role_t role,AudioDeviceTypeAddrVector & devices) const575 status_t EngineBase::getDevicesForRoleAndCapturePreset(audio_source_t audioSource,
576         device_role_t role, AudioDeviceTypeAddrVector &devices) const
577 {
578     std::function<bool(audio_source_t)> p = [](audio_source_t audioSource) {
579         return audio_is_valid_audio_source(audioSource);
580     };
581     return getDevicesRoleForT(
582             mCapturePresetDevicesRoleMap, audioSource, role, devices, "audio source" /*logStr*/, p);
583 }
584 
getMediaDevicesForRole(device_role_t role,const DeviceVector & availableDevices,DeviceVector & devices) const585 status_t EngineBase::getMediaDevicesForRole(device_role_t role,
586         const DeviceVector& availableDevices, DeviceVector& devices) const
587 {
588     product_strategy_t strategy = getProductStrategyByName("STRATEGY_MEDIA" /*name*/);
589     if (strategy == PRODUCT_STRATEGY_NONE) {
590         strategy = getProductStrategyForStream(AUDIO_STREAM_MUSIC);
591     }
592     if (strategy == PRODUCT_STRATEGY_NONE) {
593         return NAME_NOT_FOUND;
594     }
595     AudioDeviceTypeAddrVector deviceAddrVec;
596     status_t status = getDevicesForRoleAndStrategy(strategy, role, deviceAddrVec);
597     if (status != NO_ERROR) {
598         return status;
599     }
600     devices = availableDevices.getDevicesFromDeviceTypeAddrVec(deviceAddrVec);
601     return deviceAddrVec.size() == devices.size() ? NO_ERROR : NOT_ENOUGH_DATA;
602 }
603 
getActiveMediaDevices(const DeviceVector & availableDevices) const604 DeviceVector EngineBase::getActiveMediaDevices(const DeviceVector& availableDevices) const
605 {
606     // The priority of active devices as follows:
607     // 1: the available preferred devices for media
608     // 2: the latest connected removable media device that is enabled
609     DeviceVector activeDevices;
610     if (getMediaDevicesForRole(
611             DEVICE_ROLE_PREFERRED, availableDevices, activeDevices) != NO_ERROR) {
612         activeDevices.clear();
613         DeviceVector disabledDevices;
614         getMediaDevicesForRole(DEVICE_ROLE_DISABLED, availableDevices, disabledDevices);
615         sp<DeviceDescriptor> device =
616                 mLastRemovableMediaDevices.getLastRemovableMediaDevice(disabledDevices);
617         if (device != nullptr) {
618             activeDevices.add(device);
619         }
620     }
621     return activeDevices;
622 }
623 
dumpCapturePresetDevicesRoleMap(String8 * dst,int spaces) const624 void EngineBase::dumpCapturePresetDevicesRoleMap(String8 *dst, int spaces) const
625 {
626     dst->appendFormat("\n%*sDevice role per capture preset dump:", spaces, "");
627     for (const auto& [capturePresetRolePair, devices] : mCapturePresetDevicesRoleMap) {
628         dst->appendFormat("\n%*sCapture preset(%u) Device Role(%u) Devices(%s)", spaces + 2, "",
629                 capturePresetRolePair.first, capturePresetRolePair.second,
630                 dumpAudioDeviceTypeAddrVector(devices, true /*includeSensitiveInfo*/).c_str());
631     }
632     dst->appendFormat("\n");
633 }
634 
dump(String8 * dst) const635 void EngineBase::dump(String8 *dst) const
636 {
637     mProductStrategies.dump(dst, 2);
638     dumpProductStrategyDevicesRoleMap(mProductStrategyDeviceRoleMap, dst, 2);
639     dumpCapturePresetDevicesRoleMap(dst, 2);
640     mVolumeGroups.dump(dst, 2);
641 }
642 
643 } // namespace audio_policy
644 } // namespace android
645