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