blob: 7d585c00e070a989f4a55cbb05602a766db9becb [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{
François Gaffie20f06f92015-03-24 09:01:14 +010090}
91
92Engine::~Engine()
93{
94 mStrategyCollection.clear();
95 mStreamCollection.clear();
96 mInputSourceCollection.clear();
97 mUsageCollection.clear();
98}
99
100
101void Engine::setObserver(AudioPolicyManagerObserver *observer)
102{
103 ALOG_ASSERT(observer != NULL, "Invalid Audio Policy Manager observer");
104 mApmObserver = observer;
105}
106
107status_t Engine::initCheck()
108{
François Gaffie0f17ab72015-05-13 18:13:00 +0200109 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;
François Gaffie20f06f92015-03-24 09:01:14 +0100116}
117
François Gaffie20f06f92015-03-24 09:01:14 +0100118template <typename Key>
119Element<Key> *Engine::getFromCollection(const Key &key) const
120{
121 const Collection<Key> collection = getCollection<Key>();
122 return collection.get(key);
123}
124
125template <typename Key>
126status_t Engine::add(const std::string &name, const Key &key)
127{
128 Collection<Key> &collection = getCollection<Key>();
129 return collection.add(name, key);
130}
131
François Gaffie20f06f92015-03-24 09:01:14 +0100132template <typename Property, typename Key>
133Property Engine::getPropertyForKey(Key key) const
134{
135 Element<Key> *element = getFromCollection<Key>(key);
136 if (element == NULL) {
137 ALOGE("%s: Element not found within collection", __FUNCTION__);
138 return static_cast<Property>(0);
139 }
140 return element->template get<Property>();
141}
142
François Gaffie0f17ab72015-05-13 18:13:00 +0200143routing_strategy Engine::ManagerInterfaceImpl::getStrategyForUsage(audio_usage_t usage)
François Gaffie20f06f92015-03-24 09:01:14 +0100144{
François Gaffie0f17ab72015-05-13 18:13:00 +0200145 const SwAudioOutputCollection &outputs = mPolicyEngine->mApmObserver->getOutputs();
146
147 if (usage == AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY &&
148 (outputs.isStreamActive(AUDIO_STREAM_RING) ||
149 outputs.isStreamActive(AUDIO_STREAM_ALARM))) {
150 return STRATEGY_SONIFICATION;
151 }
152 return mPolicyEngine->getPropertyForKey<routing_strategy, audio_usage_t>(usage);
153}
154
155audio_devices_t Engine::ManagerInterfaceImpl::getDeviceForStrategy(routing_strategy strategy) const
156{
157 const SwAudioOutputCollection &outputs = mPolicyEngine->mApmObserver->getOutputs();
François Gaffie20f06f92015-03-24 09:01:14 +0100158
159 /** This is the only case handled programmatically because the PFW is unable to know the
160 * activity of streams.
161 *
162 * -While media is playing on a remote device, use the the sonification behavior.
163 * Note that we test this usecase before testing if media is playing because
164 * the isStreamActive() method only informs about the activity of a stream, not
165 * if it's for local playback. Note also that we use the same delay between both tests
166 *
167 * -When media is not playing anymore, fall back on the sonification behavior
168 */
169 if (strategy == STRATEGY_SONIFICATION_RESPECTFUL &&
170 !is_state_in_call(getPhoneState()) &&
171 !outputs.isStreamActiveRemotely(AUDIO_STREAM_MUSIC,
172 SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY) &&
173 outputs.isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
François Gaffie0f17ab72015-05-13 18:13:00 +0200174 return mPolicyEngine->getPropertyForKey<audio_devices_t, routing_strategy>(STRATEGY_MEDIA);
François Gaffie20f06f92015-03-24 09:01:14 +0100175 }
François Gaffie0f17ab72015-05-13 18:13:00 +0200176 return mPolicyEngine->getPropertyForKey<audio_devices_t, routing_strategy>(strategy);
François Gaffie20f06f92015-03-24 09:01:14 +0100177}
178
François Gaffied1ab2bd2015-12-02 18:20:06 +0100179bool Engine::PluginInterfaceImpl::setVolumeProfileForStream(const audio_stream_type_t &stream,
180 const audio_stream_type_t &profile)
181{
182 if (mPolicyEngine->setPropertyForKey<audio_stream_type_t, audio_stream_type_t>(stream,
183 profile)) {
184 mPolicyEngine->mApmObserver->getVolumeCurves().switchVolumeCurve(profile, stream);
185 return true;
186 }
187 return false;
188}
189
190
François Gaffie20f06f92015-03-24 09:01:14 +0100191template <typename Property, typename Key>
192bool 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
François Gaffie20f06f92015-03-24 09:01:14 +0100202status_t Engine::setPhoneState(audio_mode_t mode)
203{
204 return mPolicyParameterMgr->setPhoneState(mode);
205}
206
207audio_mode_t Engine::getPhoneState() const
208{
209 return mPolicyParameterMgr->getPhoneState();
210}
211
212status_t Engine::setForceUse(audio_policy_force_use_t usage,
213 audio_policy_forced_cfg_t config)
214{
215 return mPolicyParameterMgr->setForceUse(usage, config);
216}
217
218audio_policy_forced_cfg_t Engine::getForceUse(audio_policy_force_use_t usage) const
219{
220 return mPolicyParameterMgr->getForceUse(usage);
221}
222
François Gaffiea3e696d2015-12-18 09:38:43 +0100223status_t Engine::setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
224 audio_policy_dev_state_t /*state*/)
François Gaffie20f06f92015-03-24 09:01:14 +0100225{
François Gaffiea3e696d2015-12-18 09:38:43 +0100226 if (audio_is_output_device(devDesc->type())) {
227 return mPolicyParameterMgr->setAvailableOutputDevices(
228 mApmObserver->getAvailableOutputDevices().types());
229 } else if (audio_is_input_device(devDesc->type())) {
230 return mPolicyParameterMgr->setAvailableInputDevices(
231 mApmObserver->getAvailableInputDevices().types());
232 }
233 return BAD_TYPE;
François Gaffie20f06f92015-03-24 09:01:14 +0100234}
235
236template <>
237AudioPolicyManagerInterface *Engine::queryInterface()
238{
239 return &mManagerInterface;
240}
241
242template <>
243AudioPolicyPluginInterface *Engine::queryInterface()
244{
245 return &mPluginInterface;
246}
247
248} // namespace audio_policy
249} // namespace android
250
251