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 return mPolicyEngine->getPropertyForKey<routing_strategy, audio_usage_t>(usage); 144} 145 146audio_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 178bool 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 190template <typename Property, typename Key> 191bool 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 201status_t Engine::setPhoneState(audio_mode_t mode) 202{ 203 return mPolicyParameterMgr->setPhoneState(mode); 204} 205 206audio_mode_t Engine::getPhoneState() const 207{ 208 return mPolicyParameterMgr->getPhoneState(); 209} 210 211status_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 217audio_policy_forced_cfg_t Engine::getForceUse(audio_policy_force_use_t usage) const 218{ 219 return mPolicyParameterMgr->getForceUse(usage); 220} 221 222status_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 235template <> 236AudioPolicyManagerInterface *Engine::queryInterface() 237{ 238 return &mManagerInterface; 239} 240 241template <> 242AudioPolicyPluginInterface *Engine::queryInterface() 243{ 244 return &mPluginInterface; 245} 246 247} // namespace audio_policy 248} // namespace android 249 250 251