1 /*
2 * Copyright (C) 2009 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 "AudioPolicyManager"
18 //#define LOG_NDEBUG 0
19 #include <utils/Log.h>
20 #include "AudioPolicyManager.h"
21 #include <media/mediarecorder.h>
22
23 namespace android {
24
25
26 // Max volume for streams when playing over bluetooth SCO device while in call: -18dB
27 #define IN_CALL_SCO_VOLUME_MAX 0.126
28 // Min music volume for 3.5mm jack in car dock: -10dB
29 #define CAR_DOCK_MUSIC_MINI_JACK_VOLUME_MIN 0.316
30
31 // ----------------------------------------------------------------------------
32 // AudioPolicyManager implementation for qsd8k platform
33 // Common audio policy manager code is implemented in AudioPolicyManagerBase class
34 // ----------------------------------------------------------------------------
35
36 // --- class factory
37
38
createAudioPolicyManager(AudioPolicyClientInterface * clientInterface)39 extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
40 {
41 return new AudioPolicyManager(clientInterface);
42 }
43
destroyAudioPolicyManager(AudioPolicyInterface * interface)44 extern "C" void destroyAudioPolicyManager(AudioPolicyInterface *interface)
45 {
46 delete interface;
47 }
48
49 // ---
50
51
getDeviceForStrategy(routing_strategy strategy,bool fromCache)52 uint32_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy, bool fromCache)
53 {
54 uint32_t device = 0;
55
56 if (fromCache) {
57 device = mDeviceForStrategy[strategy];
58 ALOGV("getDeviceForStrategy() from cache strategy %d, device %x", strategy, device);
59 return device;
60 }
61
62 switch (strategy) {
63 case STRATEGY_DTMF:
64 if (mPhoneState != AudioSystem::MODE_IN_CALL) {
65 // when off call, DTMF strategy follows the same rules as MEDIA strategy
66 device = getDeviceForStrategy(STRATEGY_MEDIA, false);
67 break;
68 }
69 // when in call, DTMF and PHONE strategies follow the same rules
70 // FALL THROUGH
71
72 case STRATEGY_PHONE:
73 // for phone strategy, we first consider the forced use and then the available devices by order
74 // of priority
75 switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) {
76 case AudioSystem::FORCE_BT_SCO:
77 if (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) {
78 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
79 if (device) break;
80 }
81 // otherwise (not docked) continue with selection
82 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
83 if (device) break;
84 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO;
85 if (device) break;
86 // if SCO device is requested but no SCO device is available, fall back to default case
87 // FALL THROUGH
88
89 default: // FORCE_NONE
90 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
91 if (device) break;
92 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
93 if (device) break;
94 // when not in call:
95 if (mPhoneState != AudioSystem::MODE_IN_CALL) {
96 // - if we are docked to a BT CAR dock, give A2DP preference over earpiece
97 // - if we are docked to a BT DESK dock, give speaker preference over earpiece
98 if (mForceUse[AudioSystem::FOR_DOCK] == AudioSystem::FORCE_BT_CAR_DOCK) {
99 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
100 } else if (mForceUse[AudioSystem::FOR_DOCK] == AudioSystem::FORCE_BT_DESK_DOCK) {
101 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
102 }
103 if (device) break;
104 // - phone strategy should route STREAM_VOICE_CALL to A2DP
105 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
106 if (device) break;
107 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
108 if (device) break;
109 }
110 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_EARPIECE;
111 if (device == 0) {
112 ALOGE("getDeviceForStrategy() earpiece device not found");
113 }
114 break;
115
116 case AudioSystem::FORCE_SPEAKER:
117 if (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) {
118 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
119 if (device) break;
120 }
121 // when not in call:
122 if (mPhoneState != AudioSystem::MODE_IN_CALL) {
123 // - if we are docked to a BT CAR dock, give A2DP preference over phone spkr
124 if (mForceUse[AudioSystem::FOR_DOCK] == AudioSystem::FORCE_BT_CAR_DOCK) {
125 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
126 if (device) break;
127 }
128 // - phone strategy should route STREAM_VOICE_CALL to A2DP speaker
129 // when forcing to speaker output
130 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
131 if (device) break;
132 }
133 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
134 if (device == 0) {
135 ALOGE("getDeviceForStrategy() speaker device not found");
136 }
137 break;
138 }
139 break;
140
141 case STRATEGY_SONIFICATION:
142
143 // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by
144 // handleIncallSonification().
145 if (mPhoneState == AudioSystem::MODE_IN_CALL) {
146 device = getDeviceForStrategy(STRATEGY_PHONE, false);
147 break;
148 }
149 // If not incall:
150 // - if we are docked to a BT CAR dock, don't duplicate for the sonification strategy
151 // - if we are docked to a BT DESK dock, use only speaker for the sonification strategy
152 if (mForceUse[AudioSystem::FOR_DOCK] != AudioSystem::FORCE_BT_CAR_DOCK) {
153 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
154 if (device == 0) {
155 ALOGE("getDeviceForStrategy() speaker device not found");
156 }
157 if (mForceUse[AudioSystem::FOR_DOCK] == AudioSystem::FORCE_BT_DESK_DOCK) {
158 if (mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) {
159 device |= AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
160 } else if (mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) {
161 device |= AudioSystem::DEVICE_OUT_WIRED_HEADSET;
162 }
163 break;
164 }
165 } else {
166 device = 0;
167 }
168 // The second device used for sonification is the same as the device used by media strategy
169 // Note that when docked, we pick the device below (no duplication)
170 // FALL THROUGH
171
172 case STRATEGY_MEDIA: {
173 uint32_t device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
174 #ifdef WITH_A2DP
175 if (mA2dpOutput != 0) {
176 if (device2 == 0) {
177 // play ringtone over speaker (or speaker + headset) if in car dock
178 // because A2DP is suspended in this case
179 if (mForceUse[AudioSystem::FOR_DOCK] == AudioSystem::FORCE_BT_CAR_DOCK &&
180 strategy == STRATEGY_SONIFICATION &&
181 mPhoneState == AudioSystem::MODE_RINGTONE) {
182 device2 = mAvailableOutputDevices &
183 (AudioSystem::DEVICE_OUT_SPEAKER |
184 AudioSystem::DEVICE_OUT_WIRED_HEADPHONE |
185 AudioSystem::DEVICE_OUT_WIRED_HEADSET);
186 }
187 }
188 }
189 #endif
190 if (device2 == 0) {
191 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
192 }
193 if (device2 == 0) {
194 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
195 }
196 #ifdef WITH_A2DP
197 if (mA2dpOutput != 0) {
198 if (device2 == 0) {
199 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
200 }
201 if (device2 == 0) {
202 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
203 }
204 if (device2 == 0) {
205 device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
206 }
207 }
208 #endif
209 if (device2 == 0) {
210 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
211 }
212 // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION, 0 otherwise
213 device |= device2;
214 if (device == 0) {
215 ALOGE("getDeviceForStrategy() speaker device not found");
216 }
217 // Do not play media stream if in call and the requested device would change the hardware
218 // output routing
219 if (mPhoneState == AudioSystem::MODE_IN_CALL &&
220 !AudioSystem::isA2dpDevice((AudioSystem::audio_devices)device) &&
221 device != getDeviceForStrategy(STRATEGY_PHONE, false)) {
222 device = 0;
223 ALOGV("getDeviceForStrategy() incompatible media and phone devices");
224 }
225 } break;
226
227 default:
228 ALOGW("getDeviceForStrategy() unknown strategy: %d", strategy);
229 break;
230 }
231
232 ALOGV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
233 return device;
234 }
235
computeVolume(int stream,int index,audio_io_handle_t output,uint32_t device)236 float AudioPolicyManager::computeVolume(int stream, int index, audio_io_handle_t output, uint32_t device)
237 {
238 // if requested volume index is the minimum possible value, we must honor this value as this
239 // means the stream is muted. This overrides condition-specific modifications to the volume
240 // computed in the generic APM
241 if (index == mStreams[stream].mIndexMin) {
242 return AudioPolicyManagerBase::computeVolume(stream, index, output, device);
243 }
244
245 // force volume on A2DP output to maximum if playing through car dock speakers
246 // as volume is applied on the car dock and controlled via car dock keys.
247 #ifdef WITH_A2DP
248 if (output == mA2dpOutput &&
249 mForceUse[AudioSystem::FOR_DOCK] == AudioSystem::FORCE_BT_CAR_DOCK) {
250 return 1.0;
251 }
252 #endif
253
254 float volume = AudioPolicyManagerBase::computeVolume(stream, index, output, device);
255
256 // limit stream volume when in call and playing over bluetooth SCO device to
257 // avoid saturation
258 if (mPhoneState == AudioSystem::MODE_IN_CALL && AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)device)) {
259 if (volume > IN_CALL_SCO_VOLUME_MAX) {
260 ALOGV("computeVolume limiting SYSTEM volume %f to %f",volume, IN_CALL_SCO_VOLUME_MAX);
261 volume = IN_CALL_SCO_VOLUME_MAX;
262 }
263 }
264
265 // in car dock: when using the 3.5mm jack to play media, set a minimum volume as access to the
266 // physical volume keys is blocked by the car dock frame.
267 if ((mForceUse[AudioSystem::FOR_DOCK] == AudioSystem::FORCE_BT_CAR_DOCK) &&
268 (volume < CAR_DOCK_MUSIC_MINI_JACK_VOLUME_MIN) &&
269 (stream == AudioSystem::MUSIC) &&
270 (device & (AudioSystem::DEVICE_OUT_WIRED_HEADPHONE |
271 AudioSystem::DEVICE_OUT_WIRED_HEADSET))) {
272 volume = CAR_DOCK_MUSIC_MINI_JACK_VOLUME_MIN;
273 }
274
275 return volume;
276 }
277
278
279
280
281 }; // namespace android
282