Home | History | Annotate | Download | only in src
      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 "Strategy.h"
     29 #include "Stream.h"
     30 #include "InputSource.h"
     31 #include "Usage.h"
     32 #include <policy.h>
     33 #include <ParameterManagerWrapper.h>
     34 
     35 using std::string;
     36 using std::map;
     37 
     38 namespace android
     39 {
     40 namespace audio_policy
     41 {
     42 template <>
     43 StrategyCollection &Engine::getCollection<routing_strategy>()
     44 {
     45     return mStrategyCollection;
     46 }
     47 template <>
     48 StreamCollection &Engine::getCollection<audio_stream_type_t>()
     49 {
     50     return mStreamCollection;
     51 }
     52 template <>
     53 UsageCollection &Engine::getCollection<audio_usage_t>()
     54 {
     55     return mUsageCollection;
     56 }
     57 template <>
     58 InputSourceCollection &Engine::getCollection<audio_source_t>()
     59 {
     60     return mInputSourceCollection;
     61 }
     62 
     63 template <>
     64 const StrategyCollection &Engine::getCollection<routing_strategy>() const
     65 {
     66     return mStrategyCollection;
     67 }
     68 template <>
     69 const StreamCollection &Engine::getCollection<audio_stream_type_t>() const
     70 {
     71     return mStreamCollection;
     72 }
     73 template <>
     74 const UsageCollection &Engine::getCollection<audio_usage_t>() const
     75 {
     76     return mUsageCollection;
     77 }
     78 template <>
     79 const InputSourceCollection &Engine::getCollection<audio_source_t>() const
     80 {
     81     return mInputSourceCollection;
     82 }
     83 
     84 Engine::Engine()
     85     : mManagerInterface(this),
     86       mPluginInterface(this),
     87       mPolicyParameterMgr(new ParameterManagerWrapper()),
     88       mApmObserver(NULL)
     89 {
     90 }
     91 
     92 Engine::~Engine()
     93 {
     94     mStrategyCollection.clear();
     95     mStreamCollection.clear();
     96     mInputSourceCollection.clear();
     97     mUsageCollection.clear();
     98 }
     99 
    100 
    101 void Engine::setObserver(AudioPolicyManagerObserver *observer)
    102 {
    103     ALOG_ASSERT(observer != NULL, "Invalid Audio Policy Manager observer");
    104     mApmObserver = observer;
    105 }
    106 
    107 status_t Engine::initCheck()
    108 {
    109     if (mPolicyParameterMgr != NULL && mPolicyParameterMgr->start() != NO_ERROR) {
    110         ALOGE("%s: could not start Policy PFW", __FUNCTION__);
    111         delete mPolicyParameterMgr;
    112         mPolicyParameterMgr = NULL;
    113         return NO_INIT;
    114     }
    115     return (mApmObserver != NULL)? NO_ERROR : NO_INIT;
    116 }
    117 
    118 bool Engine::setVolumeProfileForStream(const audio_stream_type_t &streamType,
    119                                        Volume::device_category deviceCategory,
    120                                        const VolumeCurvePoints &points)
    121 {
    122     Stream *stream = getFromCollection<audio_stream_type_t>(streamType);
    123     if (stream == NULL) {
    124         ALOGE("%s: stream %d not found", __FUNCTION__, streamType);
    125         return false;
    126     }
    127     return stream->setVolumeProfile(deviceCategory, points) == NO_ERROR;
    128 }
    129 
    130 template <typename Key>
    131 Element<Key> *Engine::getFromCollection(const Key &key) const
    132 {
    133     const Collection<Key> collection = getCollection<Key>();
    134     return collection.get(key);
    135 }
    136 
    137 template <typename Key>
    138 status_t Engine::add(const std::string &name, const Key &key)
    139 {
    140     Collection<Key> &collection = getCollection<Key>();
    141     return collection.add(name, key);
    142 }
    143 
    144 template <typename Property, typename Key>
    145 Property Engine::getPropertyForKey(Key key) const
    146 {
    147     Element<Key> *element = getFromCollection<Key>(key);
    148     if (element == NULL) {
    149         ALOGE("%s: Element not found within collection", __FUNCTION__);
    150         return static_cast<Property>(0);
    151     }
    152     return element->template get<Property>();
    153 }
    154 
    155 routing_strategy Engine::ManagerInterfaceImpl::getStrategyForUsage(audio_usage_t usage)
    156 {
    157     const SwAudioOutputCollection &outputs = mPolicyEngine->mApmObserver->getOutputs();
    158 
    159     if (usage == AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY &&
    160             (outputs.isStreamActive(AUDIO_STREAM_RING) ||
    161              outputs.isStreamActive(AUDIO_STREAM_ALARM))) {
    162         return STRATEGY_SONIFICATION;
    163     }
    164     return mPolicyEngine->getPropertyForKey<routing_strategy, audio_usage_t>(usage);
    165 }
    166 
    167 audio_devices_t Engine::ManagerInterfaceImpl::getDeviceForStrategy(routing_strategy strategy) const
    168 {
    169     const SwAudioOutputCollection &outputs = mPolicyEngine->mApmObserver->getOutputs();
    170 
    171     /** This is the only case handled programmatically because the PFW is unable to know the
    172      * activity of streams.
    173      *
    174      * -While media is playing on a remote device, use the the sonification behavior.
    175      * Note that we test this usecase before testing if media is playing because
    176      * the isStreamActive() method only informs about the activity of a stream, not
    177      * if it's for local playback. Note also that we use the same delay between both tests
    178      *
    179      * -When media is not playing anymore, fall back on the sonification behavior
    180      */
    181     if (strategy == STRATEGY_SONIFICATION_RESPECTFUL &&
    182             !is_state_in_call(getPhoneState()) &&
    183             !outputs.isStreamActiveRemotely(AUDIO_STREAM_MUSIC,
    184                                     SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY) &&
    185             outputs.isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
    186         return mPolicyEngine->getPropertyForKey<audio_devices_t, routing_strategy>(STRATEGY_MEDIA);
    187     }
    188     return mPolicyEngine->getPropertyForKey<audio_devices_t, routing_strategy>(strategy);
    189 }
    190 
    191 template <typename Property, typename Key>
    192 bool Engine::setPropertyForKey(const Property &property, const Key &key)
    193 {
    194     Element<Key> *element = getFromCollection<Key>(key);
    195     if (element == NULL) {
    196         ALOGE("%s: Element not found within collection", __FUNCTION__);
    197         return BAD_VALUE;
    198     }
    199     return element->template set<Property>(property) == NO_ERROR;
    200 }
    201 
    202 float Engine::volIndexToDb(Volume::device_category category,
    203                              audio_stream_type_t streamType,
    204                              int indexInUi)
    205 {
    206     Stream *stream = getFromCollection<audio_stream_type_t>(streamType);
    207     if (stream == NULL) {
    208         ALOGE("%s: Element indexed by key=%d not found", __FUNCTION__, streamType);
    209         return 1.0f;
    210     }
    211     return stream->volIndexToDb(category, indexInUi);
    212 }
    213 
    214 status_t Engine::initStreamVolume(audio_stream_type_t streamType,
    215                                            int indexMin, int indexMax)
    216 {
    217     Stream *stream = getFromCollection<audio_stream_type_t>(streamType);
    218     if (stream == NULL) {
    219         ALOGE("%s: Stream Type %d not found", __FUNCTION__, streamType);
    220         return BAD_TYPE;
    221     }
    222     mApmObserver->getStreamDescriptors().setVolumeIndexMin(streamType, indexMin);
    223     mApmObserver->getStreamDescriptors().setVolumeIndexMax(streamType, indexMax);
    224 
    225     return stream->initVolume(indexMin, indexMax);
    226 }
    227 
    228 status_t Engine::setPhoneState(audio_mode_t mode)
    229 {
    230     return mPolicyParameterMgr->setPhoneState(mode);
    231 }
    232 
    233 audio_mode_t Engine::getPhoneState() const
    234 {
    235     return mPolicyParameterMgr->getPhoneState();
    236 }
    237 
    238 status_t Engine::setForceUse(audio_policy_force_use_t usage,
    239                                       audio_policy_forced_cfg_t config)
    240 {
    241     return mPolicyParameterMgr->setForceUse(usage, config);
    242 }
    243 
    244 audio_policy_forced_cfg_t Engine::getForceUse(audio_policy_force_use_t usage) const
    245 {
    246     return mPolicyParameterMgr->getForceUse(usage);
    247 }
    248 
    249 status_t Engine::setDeviceConnectionState(audio_devices_t devices, audio_policy_dev_state_t state,
    250                                           const char *deviceAddress)
    251 {
    252     return mPolicyParameterMgr->setDeviceConnectionState(devices, state, deviceAddress);
    253 }
    254 
    255 template <>
    256 AudioPolicyManagerInterface *Engine::queryInterface()
    257 {
    258     return &mManagerInterface;
    259 }
    260 
    261 template <>
    262 AudioPolicyPluginInterface *Engine::queryInterface()
    263 {
    264     return &mPluginInterface;
    265 }
    266 
    267 } // namespace audio_policy
    268 } // namespace android
    269 
    270 
    271