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