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 39 extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface) 40 { 41 return new AudioPolicyManager(clientInterface); 42 } 43 44 extern "C" void destroyAudioPolicyManager(AudioPolicyInterface *interface) 45 { 46 delete interface; 47 } 48 49 // --- 50 51 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 LOGV("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 LOGE("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 LOGE("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 LOGE("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 LOGE("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 LOGV("getDeviceForStrategy() incompatible media and phone devices"); 224 } 225 } break; 226 227 default: 228 LOGW("getDeviceForStrategy() unknown strategy: %d", strategy); 229 break; 230 } 231 232 LOGV("getDeviceForStrategy() strategy %d, device %x", strategy, device); 233 return device; 234 } 235 236 float AudioPolicyManager::computeVolume(int stream, int index, audio_io_handle_t output, uint32_t device) 237 { 238 // force volume on A2DP output to maximum if playing through car dock speakers 239 // as volume is applied on the car dock and controlled via car dock keys. 240 #ifdef WITH_A2DP 241 if (output == mA2dpOutput && 242 mForceUse[AudioSystem::FOR_DOCK] == AudioSystem::FORCE_BT_CAR_DOCK) { 243 return 1.0; 244 } 245 #endif 246 247 float volume = AudioPolicyManagerBase::computeVolume(stream, index, output, device); 248 249 // limit stream volume when in call and playing over bluetooth SCO device to 250 // avoid saturation 251 if (mPhoneState == AudioSystem::MODE_IN_CALL && AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)device)) { 252 if (volume > IN_CALL_SCO_VOLUME_MAX) { 253 LOGV("computeVolume limiting SYSTEM volume %f to %f",volume, IN_CALL_SCO_VOLUME_MAX); 254 volume = IN_CALL_SCO_VOLUME_MAX; 255 } 256 } 257 258 // in car dock: when using the 3.5mm jack to play media, set a fixed volume as access to the 259 // physical volume keys is blocked by the car dock frame. 260 if ((mForceUse[AudioSystem::FOR_DOCK] == AudioSystem::FORCE_BT_CAR_DOCK) && 261 (stream == AudioSystem::MUSIC) && 262 (device & (AudioSystem::DEVICE_OUT_WIRED_HEADPHONE | 263 AudioSystem::DEVICE_OUT_WIRED_HEADSET))) { 264 volume = CAR_DOCK_MUSIC_MINI_JACK_VOLUME_MIN; 265 } 266 267 return volume; 268 } 269 270 271 272 273 }; // namespace android 274