blob: 61fae717231addb4525e6ce5e24cd69b47ac0719 [file] [log] [blame]
François Gaffie20f06f92015-03-24 09:01:14 +01001/*
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 if (mPolicyParameterMgr->start() != NO_ERROR) {
91 ALOGE("%s: could not start Policy PFW", __FUNCTION__);
92 delete mPolicyParameterMgr;
93 mPolicyParameterMgr = NULL;
94 }
95}
96
97Engine::~Engine()
98{
99 mStrategyCollection.clear();
100 mStreamCollection.clear();
101 mInputSourceCollection.clear();
102 mUsageCollection.clear();
103}
104
105
106void Engine::setObserver(AudioPolicyManagerObserver *observer)
107{
108 ALOG_ASSERT(observer != NULL, "Invalid Audio Policy Manager observer");
109 mApmObserver = observer;
110}
111
112status_t Engine::initCheck()
113{
114 return (mPolicyParameterMgr != NULL) &&
115 mPolicyParameterMgr->isStarted() &&
116 (mApmObserver != NULL)?
117 NO_ERROR : NO_INIT;
118}
119
120bool Engine::setVolumeProfileForStream(const audio_stream_type_t &streamType,
121 Volume::device_category deviceCategory,
122 const VolumeCurvePoints &points)
123{
124 Stream *stream = getFromCollection<audio_stream_type_t>(streamType);
125 if (stream == NULL) {
126 ALOGE("%s: stream %d not found", __FUNCTION__, streamType);
127 return false;
128 }
129 return stream->setVolumeProfile(deviceCategory, points) == NO_ERROR;
130}
131
132template <typename Key>
133Element<Key> *Engine::getFromCollection(const Key &key) const
134{
135 const Collection<Key> collection = getCollection<Key>();
136 return collection.get(key);
137}
138
139template <typename Key>
140status_t Engine::add(const std::string &name, const Key &key)
141{
142 Collection<Key> &collection = getCollection<Key>();
143 return collection.add(name, key);
144}
145
146template <>
147routing_strategy Engine::getPropertyForKey<routing_strategy, audio_usage_t>(audio_usage_t usage) const
148{
149 const SwAudioOutputCollection &outputs = mApmObserver->getOutputs();
150
151 if (usage == AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY &&
152 (outputs.isStreamActive(AUDIO_STREAM_RING) ||
153 outputs.isStreamActive(AUDIO_STREAM_ALARM))) {
154 return STRATEGY_SONIFICATION;
155 }
156 return getPropertyForKey<routing_strategy, audio_usage_t>(usage);
157}
158
159template <typename Property, typename Key>
160Property Engine::getPropertyForKey(Key key) const
161{
162 Element<Key> *element = getFromCollection<Key>(key);
163 if (element == NULL) {
164 ALOGE("%s: Element not found within collection", __FUNCTION__);
165 return static_cast<Property>(0);
166 }
167 return element->template get<Property>();
168}
169
170template <>
171audio_devices_t Engine::getPropertyForKey<audio_devices_t, routing_strategy>(routing_strategy strategy) const
172{
173 const SwAudioOutputCollection &outputs = mApmObserver->getOutputs();
174
175 /** This is the only case handled programmatically because the PFW is unable to know the
176 * activity of streams.
177 *
178 * -While media is playing on a remote device, use the the sonification behavior.
179 * Note that we test this usecase before testing if media is playing because
180 * the isStreamActive() method only informs about the activity of a stream, not
181 * if it's for local playback. Note also that we use the same delay between both tests
182 *
183 * -When media is not playing anymore, fall back on the sonification behavior
184 */
185 if (strategy == STRATEGY_SONIFICATION_RESPECTFUL &&
186 !is_state_in_call(getPhoneState()) &&
187 !outputs.isStreamActiveRemotely(AUDIO_STREAM_MUSIC,
188 SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY) &&
189 outputs.isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
190 return getPropertyForKey<audio_devices_t, routing_strategy>(STRATEGY_MEDIA);
191 }
192 return getPropertyForKey<audio_devices_t, routing_strategy>(strategy);
193}
194
195routing_strategy Engine::ManagerInterfaceImpl::getStrategyForUsage(audio_usage_t usage)
196{
197 return mPolicyEngine->getPropertyForKey<routing_strategy, audio_usage_t>(usage);
198}
199
200audio_devices_t Engine::ManagerInterfaceImpl::getDeviceForStrategy(routing_strategy stategy) const
201{
202 return mPolicyEngine->getPropertyForKey<audio_devices_t, routing_strategy>(stategy);
203}
204
205template <typename Property, typename Key>
206bool Engine::setPropertyForKey(const Property &property, const Key &key)
207{
208 Element<Key> *element = getFromCollection<Key>(key);
209 if (element == NULL) {
210 ALOGE("%s: Element not found within collection", __FUNCTION__);
211 return BAD_VALUE;
212 }
213 return element->template set<Property>(property) == NO_ERROR;
214}
215
216float Engine::volIndexToDb(Volume::device_category category,
217 audio_stream_type_t streamType,
218 int indexInUi)
219{
220 Stream *stream = getFromCollection<audio_stream_type_t>(streamType);
221 if (stream == NULL) {
222 ALOGE("%s: Element indexed by key=%d not found", __FUNCTION__, streamType);
223 return 1.0f;
224 }
225 return stream->volIndexToDb(category, indexInUi);
226}
227
228status_t Engine::initStreamVolume(audio_stream_type_t streamType,
229 int indexMin, int indexMax)
230{
231 Stream *stream = getFromCollection<audio_stream_type_t>(streamType);
232 if (stream == NULL) {
233 ALOGE("%s: Stream Type %d not found", __FUNCTION__, streamType);
234 return BAD_TYPE;
235 }
236 return stream->initVolume(indexMin, indexMax);
237}
238
239status_t Engine::setPhoneState(audio_mode_t mode)
240{
241 return mPolicyParameterMgr->setPhoneState(mode);
242}
243
244audio_mode_t Engine::getPhoneState() const
245{
246 return mPolicyParameterMgr->getPhoneState();
247}
248
249status_t Engine::setForceUse(audio_policy_force_use_t usage,
250 audio_policy_forced_cfg_t config)
251{
252 return mPolicyParameterMgr->setForceUse(usage, config);
253}
254
255audio_policy_forced_cfg_t Engine::getForceUse(audio_policy_force_use_t usage) const
256{
257 return mPolicyParameterMgr->getForceUse(usage);
258}
259
260status_t Engine::setDeviceConnectionState(audio_devices_t devices, audio_policy_dev_state_t state,
261 const char *deviceAddress)
262{
263 return mPolicyParameterMgr->setDeviceConnectionState(devices, state, deviceAddress);
264}
265
266template <>
267AudioPolicyManagerInterface *Engine::queryInterface()
268{
269 return &mManagerInterface;
270}
271
272template <>
273AudioPolicyPluginInterface *Engine::queryInterface()
274{
275 return &mPluginInterface;
276}
277
278} // namespace audio_policy
279} // namespace android
280
281