• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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