blob: bcd7b2236b6842da4da2ef726505bd5918f3de24 [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
François Gaffief19cf792018-05-30 17:22:17 +020038namespace android {
39namespace audio_policy {
40
François Gaffie20f06f92015-03-24 09:01:14 +010041template <>
42StrategyCollection &Engine::getCollection<routing_strategy>()
43{
44 return mStrategyCollection;
45}
46template <>
47StreamCollection &Engine::getCollection<audio_stream_type_t>()
48{
49 return mStreamCollection;
50}
51template <>
52UsageCollection &Engine::getCollection<audio_usage_t>()
53{
54 return mUsageCollection;
55}
56template <>
57InputSourceCollection &Engine::getCollection<audio_source_t>()
58{
59 return mInputSourceCollection;
60}
61
62template <>
63const StrategyCollection &Engine::getCollection<routing_strategy>() const
64{
65 return mStrategyCollection;
66}
67template <>
68const StreamCollection &Engine::getCollection<audio_stream_type_t>() const
69{
70 return mStreamCollection;
71}
72template <>
73const UsageCollection &Engine::getCollection<audio_usage_t>() const
74{
75 return mUsageCollection;
76}
77template <>
78const InputSourceCollection &Engine::getCollection<audio_source_t>() const
79{
80 return mInputSourceCollection;
81}
82
83Engine::Engine()
84 : mManagerInterface(this),
85 mPluginInterface(this),
86 mPolicyParameterMgr(new ParameterManagerWrapper()),
87 mApmObserver(NULL)
88{
François Gaffie20f06f92015-03-24 09:01:14 +010089}
90
91Engine::~Engine()
92{
93 mStrategyCollection.clear();
94 mStreamCollection.clear();
95 mInputSourceCollection.clear();
96 mUsageCollection.clear();
97}
98
99
100void Engine::setObserver(AudioPolicyManagerObserver *observer)
101{
102 ALOG_ASSERT(observer != NULL, "Invalid Audio Policy Manager observer");
103 mApmObserver = observer;
104}
105
106status_t Engine::initCheck()
107{
François Gaffie814ce802016-01-18 11:23:47 +0100108 if (mPolicyParameterMgr == NULL || mPolicyParameterMgr->start() != NO_ERROR) {
François Gaffie0f17ab72015-05-13 18:13:00 +0200109 ALOGE("%s: could not start Policy PFW", __FUNCTION__);
François Gaffie0f17ab72015-05-13 18:13:00 +0200110 return NO_INIT;
111 }
112 return (mApmObserver != NULL)? NO_ERROR : NO_INIT;
François Gaffie20f06f92015-03-24 09:01:14 +0100113}
114
François Gaffie20f06f92015-03-24 09:01:14 +0100115template <typename Key>
116Element<Key> *Engine::getFromCollection(const Key &key) const
117{
118 const Collection<Key> collection = getCollection<Key>();
119 return collection.get(key);
120}
121
122template <typename Key>
123status_t Engine::add(const std::string &name, const Key &key)
124{
125 Collection<Key> &collection = getCollection<Key>();
126 return collection.add(name, key);
127}
128
François Gaffie20f06f92015-03-24 09:01:14 +0100129template <typename Property, typename Key>
130Property Engine::getPropertyForKey(Key key) const
131{
132 Element<Key> *element = getFromCollection<Key>(key);
133 if (element == NULL) {
134 ALOGE("%s: Element not found within collection", __FUNCTION__);
135 return static_cast<Property>(0);
136 }
137 return element->template get<Property>();
138}
139
François Gaffie0f17ab72015-05-13 18:13:00 +0200140routing_strategy Engine::ManagerInterfaceImpl::getStrategyForUsage(audio_usage_t usage)
François Gaffie20f06f92015-03-24 09:01:14 +0100141{
François Gaffie0f17ab72015-05-13 18:13:00 +0200142 return mPolicyEngine->getPropertyForKey<routing_strategy, audio_usage_t>(usage);
143}
144
145audio_devices_t Engine::ManagerInterfaceImpl::getDeviceForStrategy(routing_strategy strategy) const
146{
147 const SwAudioOutputCollection &outputs = mPolicyEngine->mApmObserver->getOutputs();
François Gaffie20f06f92015-03-24 09:01:14 +0100148
149 /** This is the only case handled programmatically because the PFW is unable to know the
150 * activity of streams.
151 *
152 * -While media is playing on a remote device, use the the sonification behavior.
153 * Note that we test this usecase before testing if media is playing because
154 * the isStreamActive() method only informs about the activity of a stream, not
155 * if it's for local playback. Note also that we use the same delay between both tests
156 *
157 * -When media is not playing anymore, fall back on the sonification behavior
158 */
159 if (strategy == STRATEGY_SONIFICATION_RESPECTFUL &&
160 !is_state_in_call(getPhoneState()) &&
161 !outputs.isStreamActiveRemotely(AUDIO_STREAM_MUSIC,
162 SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY) &&
163 outputs.isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
François Gaffie0f17ab72015-05-13 18:13:00 +0200164 return mPolicyEngine->getPropertyForKey<audio_devices_t, routing_strategy>(STRATEGY_MEDIA);
François Gaffie20f06f92015-03-24 09:01:14 +0100165 }
François Gaffie4ac9d842016-04-12 16:56:35 +0200166 if (strategy == STRATEGY_ACCESSIBILITY &&
167 (outputs.isStreamActive(AUDIO_STREAM_RING) || outputs.isStreamActive(AUDIO_STREAM_ALARM))) {
168 // do not route accessibility prompts to a digital output currently configured with a
169 // compressed format as they would likely not be mixed and dropped.
170 // Device For Sonification conf file has HDMI, SPDIF and HDMI ARC unreacheable.
171 return mPolicyEngine->getPropertyForKey<audio_devices_t, routing_strategy>(
172 STRATEGY_SONIFICATION);
173 }
François Gaffie0f17ab72015-05-13 18:13:00 +0200174 return mPolicyEngine->getPropertyForKey<audio_devices_t, routing_strategy>(strategy);
François Gaffie20f06f92015-03-24 09:01:14 +0100175}
176
François Gaffied1ab2bd2015-12-02 18:20:06 +0100177bool 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 Gaffie20f06f92015-03-24 09:01:14 +0100189template <typename Property, typename Key>
190bool 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 Gaffie20f06f92015-03-24 09:01:14 +0100200status_t Engine::setPhoneState(audio_mode_t mode)
201{
202 return mPolicyParameterMgr->setPhoneState(mode);
203}
204
205audio_mode_t Engine::getPhoneState() const
206{
207 return mPolicyParameterMgr->getPhoneState();
208}
209
210status_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
216audio_policy_forced_cfg_t Engine::getForceUse(audio_policy_force_use_t usage) const
217{
218 return mPolicyParameterMgr->getForceUse(usage);
219}
220
François Gaffiea3e696d2015-12-18 09:38:43 +0100221status_t Engine::setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
222 audio_policy_dev_state_t /*state*/)
François Gaffie20f06f92015-03-24 09:01:14 +0100223{
François Gaffiea3e696d2015-12-18 09:38:43 +0100224 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 Gaffie20f06f92015-03-24 09:01:14 +0100232}
233
234template <>
235AudioPolicyManagerInterface *Engine::queryInterface()
236{
237 return &mManagerInterface;
238}
239
240template <>
241AudioPolicyPluginInterface *Engine::queryInterface()
242{
243 return &mPluginInterface;
244}
245
246} // namespace audio_policy
247} // namespace android
248
249