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 <>
getCollection()43 StrategyCollection &Engine::getCollection<routing_strategy>()
44 {
45 return mStrategyCollection;
46 }
47 template <>
getCollection()48 StreamCollection &Engine::getCollection<audio_stream_type_t>()
49 {
50 return mStreamCollection;
51 }
52 template <>
getCollection()53 UsageCollection &Engine::getCollection<audio_usage_t>()
54 {
55 return mUsageCollection;
56 }
57 template <>
getCollection()58 InputSourceCollection &Engine::getCollection<audio_source_t>()
59 {
60 return mInputSourceCollection;
61 }
62
63 template <>
getCollection() const64 const StrategyCollection &Engine::getCollection<routing_strategy>() const
65 {
66 return mStrategyCollection;
67 }
68 template <>
getCollection() const69 const StreamCollection &Engine::getCollection<audio_stream_type_t>() const
70 {
71 return mStreamCollection;
72 }
73 template <>
getCollection() const74 const UsageCollection &Engine::getCollection<audio_usage_t>() const
75 {
76 return mUsageCollection;
77 }
78 template <>
getCollection() const79 const InputSourceCollection &Engine::getCollection<audio_source_t>() const
80 {
81 return mInputSourceCollection;
82 }
83
Engine()84 Engine::Engine()
85 : mManagerInterface(this),
86 mPluginInterface(this),
87 mPolicyParameterMgr(new ParameterManagerWrapper()),
88 mApmObserver(NULL)
89 {
90 }
91
~Engine()92 Engine::~Engine()
93 {
94 mStrategyCollection.clear();
95 mStreamCollection.clear();
96 mInputSourceCollection.clear();
97 mUsageCollection.clear();
98 }
99
100
setObserver(AudioPolicyManagerObserver * observer)101 void Engine::setObserver(AudioPolicyManagerObserver *observer)
102 {
103 ALOG_ASSERT(observer != NULL, "Invalid Audio Policy Manager observer");
104 mApmObserver = observer;
105 }
106
initCheck()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
setVolumeProfileForStream(const audio_stream_type_t & streamType,Volume::device_category deviceCategory,const VolumeCurvePoints & points)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>
getFromCollection(const Key & key) const131 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>
add(const std::string & name,const Key & 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>
getPropertyForKey(Key key) const145 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
getStrategyForUsage(audio_usage_t usage)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
getDeviceForStrategy(routing_strategy strategy) const167 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>
setPropertyForKey(const Property & property,const Key & 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
volIndexToDb(Volume::device_category category,audio_stream_type_t streamType,int indexInUi)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
initStreamVolume(audio_stream_type_t streamType,int indexMin,int indexMax)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
setPhoneState(audio_mode_t mode)228 status_t Engine::setPhoneState(audio_mode_t mode)
229 {
230 return mPolicyParameterMgr->setPhoneState(mode);
231 }
232
getPhoneState() const233 audio_mode_t Engine::getPhoneState() const
234 {
235 return mPolicyParameterMgr->getPhoneState();
236 }
237
setForceUse(audio_policy_force_use_t usage,audio_policy_forced_cfg_t config)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
getForceUse(audio_policy_force_use_t usage) const244 audio_policy_forced_cfg_t Engine::getForceUse(audio_policy_force_use_t usage) const
245 {
246 return mPolicyParameterMgr->getForceUse(usage);
247 }
248
setDeviceConnectionState(audio_devices_t devices,audio_policy_dev_state_t state,const char * deviceAddress)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 <>
queryInterface()256 AudioPolicyManagerInterface *Engine::queryInterface()
257 {
258 return &mManagerInterface;
259 }
260
261 template <>
queryInterface()262 AudioPolicyPluginInterface *Engine::queryInterface()
263 {
264 return &mPluginInterface;
265 }
266
267 } // namespace audio_policy
268 } // namespace android
269
270
271