Home | History | Annotate | Download | only in libaudio-qdsp5v2
      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         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 
    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             ALOGV("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