Engine.cpp revision 814ce809867326e6ba46583444476e9f63ad01f7
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 if (usage == AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY && 146 (outputs.isStreamActive(AUDIO_STREAM_RING) || 147 outputs.isStreamActive(AUDIO_STREAM_ALARM))) { 148 return STRATEGY_SONIFICATION; 149 } 150 return mPolicyEngine->getPropertyForKey<routing_strategy, audio_usage_t>(usage); 151} 152 153audio_devices_t Engine::ManagerInterfaceImpl::getDeviceForStrategy(routing_strategy strategy) const 154{ 155 const SwAudioOutputCollection &outputs = mPolicyEngine->mApmObserver->getOutputs(); 156 157 /** This is the only case handled programmatically because the PFW is unable to know the 158 * activity of streams. 159 * 160 * -While media is playing on a remote device, use the the sonification behavior. 161 * Note that we test this usecase before testing if media is playing because 162 * the isStreamActive() method only informs about the activity of a stream, not 163 * if it's for local playback. Note also that we use the same delay between both tests 164 * 165 * -When media is not playing anymore, fall back on the sonification behavior 166 */ 167 if (strategy == STRATEGY_SONIFICATION_RESPECTFUL && 168 !is_state_in_call(getPhoneState()) && 169 !outputs.isStreamActiveRemotely(AUDIO_STREAM_MUSIC, 170 SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY) && 171 outputs.isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) { 172 return mPolicyEngine->getPropertyForKey<audio_devices_t, routing_strategy>(STRATEGY_MEDIA); 173 } 174 return mPolicyEngine->getPropertyForKey<audio_devices_t, routing_strategy>(strategy); 175} 176 177bool Engine::PluginInterfaceImpl::setVolumeProfileForStream(const audio_stream_type_t &stream, 178 const audio_stream_type_t &profile) 179{ 180 if (mPolicyEngine->setPropertyForKey<audio_stream_type_t, audio_stream_type_t>(stream, 181 profile)) { 182 mPolicyEngine->mApmObserver->getVolumeCurves().switchVolumeCurve(profile, stream); 183 return true; 184 } 185 return false; 186} 187 188 189template <typename Property, typename Key> 190bool Engine::setPropertyForKey(const Property &property, const Key &key) 191{ 192 Element<Key> *element = getFromCollection<Key>(key); 193 if (element == NULL) { 194 ALOGE("%s: Element not found within collection", __FUNCTION__); 195 return BAD_VALUE; 196 } 197 return element->template set<Property>(property) == NO_ERROR; 198} 199 200status_t Engine::setPhoneState(audio_mode_t mode) 201{ 202 return mPolicyParameterMgr->setPhoneState(mode); 203} 204 205audio_mode_t Engine::getPhoneState() const 206{ 207 return mPolicyParameterMgr->getPhoneState(); 208} 209 210status_t Engine::setForceUse(audio_policy_force_use_t usage, 211 audio_policy_forced_cfg_t config) 212{ 213 return mPolicyParameterMgr->setForceUse(usage, config); 214} 215 216audio_policy_forced_cfg_t Engine::getForceUse(audio_policy_force_use_t usage) const 217{ 218 return mPolicyParameterMgr->getForceUse(usage); 219} 220 221status_t Engine::setDeviceConnectionState(const sp<DeviceDescriptor> devDesc, 222 audio_policy_dev_state_t /*state*/) 223{ 224 if (audio_is_output_device(devDesc->type())) { 225 return mPolicyParameterMgr->setAvailableOutputDevices( 226 mApmObserver->getAvailableOutputDevices().types()); 227 } else if (audio_is_input_device(devDesc->type())) { 228 return mPolicyParameterMgr->setAvailableInputDevices( 229 mApmObserver->getAvailableInputDevices().types()); 230 } 231 return BAD_TYPE; 232} 233 234template <> 235AudioPolicyManagerInterface *Engine::queryInterface() 236{ 237 return &mManagerInterface; 238} 239 240template <> 241AudioPolicyPluginInterface *Engine::queryInterface() 242{ 243 return &mPluginInterface; 244} 245 246} // namespace audio_policy 247} // namespace android 248 249 250