| François Gaffie | 20f06f9 | 2015-03-24 09:01:14 +0100 | [diff] [blame] | 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 | { | 
| François Gaffie | 20f06f9 | 2015-03-24 09:01:14 +0100 | [diff] [blame] | 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 | { | 
| François Gaffie | 814ce80 | 2016-01-18 11:23:47 +0100 | [diff] [blame] | 109 |     if (mPolicyParameterMgr == NULL || mPolicyParameterMgr->start() != NO_ERROR) { | 
| François Gaffie | 0f17ab7 | 2015-05-13 18:13:00 +0200 | [diff] [blame] | 110 |         ALOGE("%s: could not start Policy PFW", __FUNCTION__); | 
| François Gaffie | 0f17ab7 | 2015-05-13 18:13:00 +0200 | [diff] [blame] | 111 |         return NO_INIT; | 
 | 112 |     } | 
 | 113 |     return (mApmObserver != NULL)? NO_ERROR : NO_INIT; | 
| François Gaffie | 20f06f9 | 2015-03-24 09:01:14 +0100 | [diff] [blame] | 114 | } | 
 | 115 |  | 
| François Gaffie | 20f06f9 | 2015-03-24 09:01:14 +0100 | [diff] [blame] | 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 |  | 
| François Gaffie | 20f06f9 | 2015-03-24 09:01:14 +0100 | [diff] [blame] | 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 |  | 
| François Gaffie | 0f17ab7 | 2015-05-13 18:13:00 +0200 | [diff] [blame] | 141 | routing_strategy Engine::ManagerInterfaceImpl::getStrategyForUsage(audio_usage_t usage) | 
| François Gaffie | 20f06f9 | 2015-03-24 09:01:14 +0100 | [diff] [blame] | 142 | { | 
| François Gaffie | 0f17ab7 | 2015-05-13 18:13:00 +0200 | [diff] [blame] | 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 |  | 
 | 153 | audio_devices_t Engine::ManagerInterfaceImpl::getDeviceForStrategy(routing_strategy strategy) const | 
 | 154 | { | 
 | 155 |     const SwAudioOutputCollection &outputs = mPolicyEngine->mApmObserver->getOutputs(); | 
| François Gaffie | 20f06f9 | 2015-03-24 09:01:14 +0100 | [diff] [blame] | 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)) { | 
| François Gaffie | 0f17ab7 | 2015-05-13 18:13:00 +0200 | [diff] [blame] | 172 |         return mPolicyEngine->getPropertyForKey<audio_devices_t, routing_strategy>(STRATEGY_MEDIA); | 
| François Gaffie | 20f06f9 | 2015-03-24 09:01:14 +0100 | [diff] [blame] | 173 |     } | 
| François Gaffie | 0f17ab7 | 2015-05-13 18:13:00 +0200 | [diff] [blame] | 174 |     return mPolicyEngine->getPropertyForKey<audio_devices_t, routing_strategy>(strategy); | 
| François Gaffie | 20f06f9 | 2015-03-24 09:01:14 +0100 | [diff] [blame] | 175 | } | 
 | 176 |  | 
| François Gaffie | d1ab2bd | 2015-12-02 18:20:06 +0100 | [diff] [blame] | 177 | bool 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 |  | 
| François Gaffie | 20f06f9 | 2015-03-24 09:01:14 +0100 | [diff] [blame] | 189 | template <typename Property, typename Key> | 
 | 190 | bool 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 |  | 
| François Gaffie | 20f06f9 | 2015-03-24 09:01:14 +0100 | [diff] [blame] | 200 | status_t Engine::setPhoneState(audio_mode_t mode) | 
 | 201 | { | 
 | 202 |     return mPolicyParameterMgr->setPhoneState(mode); | 
 | 203 | } | 
 | 204 |  | 
 | 205 | audio_mode_t Engine::getPhoneState() const | 
 | 206 | { | 
 | 207 |     return mPolicyParameterMgr->getPhoneState(); | 
 | 208 | } | 
 | 209 |  | 
 | 210 | status_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 |  | 
 | 216 | audio_policy_forced_cfg_t Engine::getForceUse(audio_policy_force_use_t usage) const | 
 | 217 | { | 
 | 218 |     return mPolicyParameterMgr->getForceUse(usage); | 
 | 219 | } | 
 | 220 |  | 
| François Gaffie | a3e696d | 2015-12-18 09:38:43 +0100 | [diff] [blame] | 221 | status_t Engine::setDeviceConnectionState(const sp<DeviceDescriptor> devDesc, | 
 | 222 |                                           audio_policy_dev_state_t /*state*/) | 
| François Gaffie | 20f06f9 | 2015-03-24 09:01:14 +0100 | [diff] [blame] | 223 | { | 
| François Gaffie | a3e696d | 2015-12-18 09:38:43 +0100 | [diff] [blame] | 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; | 
| François Gaffie | 20f06f9 | 2015-03-24 09:01:14 +0100 | [diff] [blame] | 232 | } | 
 | 233 |  | 
 | 234 | template <> | 
 | 235 | AudioPolicyManagerInterface *Engine::queryInterface() | 
 | 236 | { | 
 | 237 |     return &mManagerInterface; | 
 | 238 | } | 
 | 239 |  | 
 | 240 | template <> | 
 | 241 | AudioPolicyPluginInterface *Engine::queryInterface() | 
 | 242 | { | 
 | 243 |     return &mPluginInterface; | 
 | 244 | } | 
 | 245 |  | 
 | 246 | } // namespace audio_policy | 
 | 247 | } // namespace android | 
 | 248 |  | 
 | 249 |  |