Engine.cpp revision 28d09f06422841b4274d7fed6ad3441dc97382b2
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 35using std::string; 36using std::map; 37 38namespace android 39{ 40namespace audio_policy 41{ 42template <> 43StrategyCollection &Engine::getCollection<routing_strategy>() 44{ 45 return mStrategyCollection; 46} 47template <> 48StreamCollection &Engine::getCollection<audio_stream_type_t>() 49{ 50 return mStreamCollection; 51} 52template <> 53UsageCollection &Engine::getCollection<audio_usage_t>() 54{ 55 return mUsageCollection; 56} 57template <> 58InputSourceCollection &Engine::getCollection<audio_source_t>() 59{ 60 return mInputSourceCollection; 61} 62 63template <> 64const StrategyCollection &Engine::getCollection<routing_strategy>() const 65{ 66 return mStrategyCollection; 67} 68template <> 69const StreamCollection &Engine::getCollection<audio_stream_type_t>() const 70{ 71 return mStreamCollection; 72} 73template <> 74const UsageCollection &Engine::getCollection<audio_usage_t>() const 75{ 76 return mUsageCollection; 77} 78template <> 79const InputSourceCollection &Engine::getCollection<audio_source_t>() const 80{ 81 return mInputSourceCollection; 82} 83 84Engine::Engine() 85 : mManagerInterface(this), 86 mPluginInterface(this), 87 mPolicyParameterMgr(new ParameterManagerWrapper()), 88 mApmObserver(NULL) 89{ 90} 91 92Engine::~Engine() 93{ 94 mStrategyCollection.clear(); 95 mStreamCollection.clear(); 96 mInputSourceCollection.clear(); 97 mUsageCollection.clear(); 98} 99 100 101void Engine::setObserver(AudioPolicyManagerObserver *observer) 102{ 103 ALOG_ASSERT(observer != NULL, "Invalid Audio Policy Manager observer"); 104 mApmObserver = observer; 105} 106 107status_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 116template <typename Key> 117Element<Key> *Engine::getFromCollection(const Key &key) const 118{ 119 const Collection<Key> collection = getCollection<Key>(); 120 return collection.get(key); 121} 122 123template <typename Key> 124status_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 130template <typename Property, typename Key> 131Property 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 141routing_strategy Engine::ManagerInterfaceImpl::getStrategyForUsage(audio_usage_t usage) 142{ 143 const SwAudioOutputCollection &outputs = mPolicyEngine->mApmObserver->getOutputs(); 144 145 //FIXME: getStrategyForUsage() should return STRATEGY_ACCESSIBILITY and getDeviceForStrategy() 146 // should be implemented accordingly for STRATEGY_ACCESSIBILITY 147 if (usage == AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY && 148 (outputs.isStreamActive(AUDIO_STREAM_RING) || 149 outputs.isStreamActive(AUDIO_STREAM_ALARM))) { 150 return STRATEGY_SONIFICATION; 151 } 152 return mPolicyEngine->getPropertyForKey<routing_strategy, audio_usage_t>(usage); 153} 154 155audio_devices_t Engine::ManagerInterfaceImpl::getDeviceForStrategy(routing_strategy strategy) const 156{ 157 const SwAudioOutputCollection &outputs = mPolicyEngine->mApmObserver->getOutputs(); 158 159 /** This is the only case handled programmatically because the PFW is unable to know the 160 * activity of streams. 161 * 162 * -While media is playing on a remote device, use the the sonification behavior. 163 * Note that we test this usecase before testing if media is playing because 164 * the isStreamActive() method only informs about the activity of a stream, not 165 * if it's for local playback. Note also that we use the same delay between both tests 166 * 167 * -When media is not playing anymore, fall back on the sonification behavior 168 */ 169 if (strategy == STRATEGY_SONIFICATION_RESPECTFUL && 170 !is_state_in_call(getPhoneState()) && 171 !outputs.isStreamActiveRemotely(AUDIO_STREAM_MUSIC, 172 SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY) && 173 outputs.isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) { 174 return mPolicyEngine->getPropertyForKey<audio_devices_t, routing_strategy>(STRATEGY_MEDIA); 175 } 176 return mPolicyEngine->getPropertyForKey<audio_devices_t, routing_strategy>(strategy); 177} 178 179bool Engine::PluginInterfaceImpl::setVolumeProfileForStream(const audio_stream_type_t &stream, 180 const audio_stream_type_t &profile) 181{ 182 if (mPolicyEngine->setPropertyForKey<audio_stream_type_t, audio_stream_type_t>(stream, 183 profile)) { 184 mPolicyEngine->mApmObserver->getVolumeCurves().switchVolumeCurve(profile, stream); 185 return true; 186 } 187 return false; 188} 189 190 191template <typename Property, typename Key> 192bool 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 202status_t Engine::setPhoneState(audio_mode_t mode) 203{ 204 return mPolicyParameterMgr->setPhoneState(mode); 205} 206 207audio_mode_t Engine::getPhoneState() const 208{ 209 return mPolicyParameterMgr->getPhoneState(); 210} 211 212status_t Engine::setForceUse(audio_policy_force_use_t usage, 213 audio_policy_forced_cfg_t config) 214{ 215 return mPolicyParameterMgr->setForceUse(usage, config); 216} 217 218audio_policy_forced_cfg_t Engine::getForceUse(audio_policy_force_use_t usage) const 219{ 220 return mPolicyParameterMgr->getForceUse(usage); 221} 222 223status_t Engine::setDeviceConnectionState(const sp<DeviceDescriptor> devDesc, 224 audio_policy_dev_state_t /*state*/) 225{ 226 if (audio_is_output_device(devDesc->type())) { 227 return mPolicyParameterMgr->setAvailableOutputDevices( 228 mApmObserver->getAvailableOutputDevices().types()); 229 } else if (audio_is_input_device(devDesc->type())) { 230 return mPolicyParameterMgr->setAvailableInputDevices( 231 mApmObserver->getAvailableInputDevices().types()); 232 } 233 return BAD_TYPE; 234} 235 236template <> 237AudioPolicyManagerInterface *Engine::queryInterface() 238{ 239 return &mManagerInterface; 240} 241 242template <> 243AudioPolicyPluginInterface *Engine::queryInterface() 244{ 245 return &mPluginInterface; 246} 247 248} // namespace audio_policy 249} // namespace android 250 251 252