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         return NO_INIT;
    112     }
    113     return (mApmObserver != NULL)? NO_ERROR : NO_INIT;
    114 }
    115 
    116 template <typename Key>
    117 Element<Key> *Engine::getFromCollection(const Key &key) const
    118 {
    119     const Collection<Key> collection = getCollection<Key>();
    120     return collection.get(key);
    121 }
    122 
    123 template <typename Key>
    124 status_t Engine::add(const std::string &name, const Key &key)
    125 {
    126     Collection<Key> &collection = getCollection<Key>();
    127     return collection.add(name, key);
    128 }
    129 
    130 template <typename Property, typename Key>
    131 Property Engine::getPropertyForKey(Key key) const
    132 {
    133     Element<Key> *element = getFromCollection<Key>(key);
    134     if (element == NULL) {
    135         ALOGE("%s: Element not found within collection", __FUNCTION__);
    136         return static_cast<Property>(0);
    137     }
    138     return element->template get<Property>();
    139 }
    140 
    141 routing_strategy Engine::ManagerInterfaceImpl::getStrategyForUsage(audio_usage_t usage)
    142 {
    143     return mPolicyEngine->getPropertyForKey<routing_strategy, audio_usage_t>(usage);
    144 }
    145 
    146 audio_devices_t Engine::ManagerInterfaceImpl::getDeviceForStrategy(routing_strategy strategy) const
    147 {
    148     const SwAudioOutputCollection &outputs = mPolicyEngine->mApmObserver->getOutputs();
    149 
    150     /** This is the only case handled programmatically because the PFW is unable to know the
    151      * activity of streams.
    152      *
    153      * -While media is playing on a remote device, use the the sonification behavior.
    154      * Note that we test this usecase before testing if media is playing because
    155      * the isStreamActive() method only informs about the activity of a stream, not
    156      * if it's for local playback. Note also that we use the same delay between both tests
    157      *
    158      * -When media is not playing anymore, fall back on the sonification behavior
    159      */
    160     if (strategy == STRATEGY_SONIFICATION_RESPECTFUL &&
    161             !is_state_in_call(getPhoneState()) &&
    162             !outputs.isStreamActiveRemotely(AUDIO_STREAM_MUSIC,
    163                                     SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY) &&
    164             outputs.isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
    165         return mPolicyEngine->getPropertyForKey<audio_devices_t, routing_strategy>(STRATEGY_MEDIA);
    166     }
    167     if (strategy == STRATEGY_ACCESSIBILITY &&
    168         (outputs.isStreamActive(AUDIO_STREAM_RING) || outputs.isStreamActive(AUDIO_STREAM_ALARM))) {
    169             // do not route accessibility prompts to a digital output currently configured with a
    170             // compressed format as they would likely not be mixed and dropped.
    171             // Device For Sonification conf file has HDMI, SPDIF and HDMI ARC unreacheable.
    172         return mPolicyEngine->getPropertyForKey<audio_devices_t, routing_strategy>(
    173                     STRATEGY_SONIFICATION);
    174     }
    175     return mPolicyEngine->getPropertyForKey<audio_devices_t, routing_strategy>(strategy);
    176 }
    177 
    178 bool Engine::PluginInterfaceImpl::setVolumeProfileForStream(const audio_stream_type_t &stream,
    179                                                             const audio_stream_type_t &profile)
    180 {
    181     if (mPolicyEngine->setPropertyForKey<audio_stream_type_t, audio_stream_type_t>(stream,
    182                                                                                    profile)) {
    183         mPolicyEngine->mApmObserver->getVolumeCurves().switchVolumeCurve(profile, stream);
    184         return true;
    185     }
    186     return false;
    187 }
    188 
    189 
    190 template <typename Property, typename Key>
    191 bool Engine::setPropertyForKey(const Property &property, const Key &key)
    192 {
    193     Element<Key> *element = getFromCollection<Key>(key);
    194     if (element == NULL) {
    195         ALOGE("%s: Element not found within collection", __FUNCTION__);
    196         return BAD_VALUE;
    197     }
    198     return element->template set<Property>(property) == NO_ERROR;
    199 }
    200 
    201 status_t Engine::setPhoneState(audio_mode_t mode)
    202 {
    203     return mPolicyParameterMgr->setPhoneState(mode);
    204 }
    205 
    206 audio_mode_t Engine::getPhoneState() const
    207 {
    208     return mPolicyParameterMgr->getPhoneState();
    209 }
    210 
    211 status_t Engine::setForceUse(audio_policy_force_use_t usage,
    212                                       audio_policy_forced_cfg_t config)
    213 {
    214     return mPolicyParameterMgr->setForceUse(usage, config);
    215 }
    216 
    217 audio_policy_forced_cfg_t Engine::getForceUse(audio_policy_force_use_t usage) const
    218 {
    219     return mPolicyParameterMgr->getForceUse(usage);
    220 }
    221 
    222 status_t Engine::setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
    223                                           audio_policy_dev_state_t /*state*/)
    224 {
    225     if (audio_is_output_device(devDesc->type())) {
    226         return mPolicyParameterMgr->setAvailableOutputDevices(
    227                     mApmObserver->getAvailableOutputDevices().types());
    228     } else if (audio_is_input_device(devDesc->type())) {
    229         return mPolicyParameterMgr->setAvailableInputDevices(
    230                     mApmObserver->getAvailableInputDevices().types());
    231     }
    232     return BAD_TYPE;
    233 }
    234 
    235 template <>
    236 AudioPolicyManagerInterface *Engine::queryInterface()
    237 {
    238     return &mManagerInterface;
    239 }
    240 
    241 template <>
    242 AudioPolicyPluginInterface *Engine::queryInterface()
    243 {
    244     return &mPluginInterface;
    245 }
    246 
    247 } // namespace audio_policy
    248 } // namespace android
    249 
    250 
    251