14765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev/* 24765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * Copyright (C) 2009 The Android Open Source Project 34765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. 44765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * 54765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * Licensed under the Apache License, Version 2.0 (the "License"); 64765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * you may not use this file except in compliance with the License. 74765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * You may obtain a copy of the License at 84765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * 94765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * http://www.apache.org/licenses/LICENSE-2.0 104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * 114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * Unless required by applicable law or agreed to in writing, software 124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * distributed under the License is distributed on an "AS IS" BASIS, 134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * See the License for the specific language governing permissions and 154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * limitations under the License. 164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev */ 174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 189746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#define LOG_TAG "AudioPolicyManagerALSA" 194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev//#define LOG_NDEBUG 0 209746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#define LOG_NDDEBUG 0 214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <utils/Log.h> 224113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev 234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include "AudioPolicyManagerALSA.h" 244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <media/mediarecorder.h> 254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevnamespace android_audio_legacy { 274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// ---------------------------------------------------------------------------- 294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// AudioPolicyManagerALSA 304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// ---------------------------------------------------------------------------- 314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 326ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani//Compiling error seen if AudioParamer doesn't exist in this file 336ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani 346ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar ManiAudioParameter param; 359746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani 364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// --- class factory 374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 389746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani 394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevextern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface) 404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return new AudioPolicyManager(clientInterface); 424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevextern "C" void destroyAudioPolicyManager(AudioPolicyInterface *interface) 454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev delete interface; 474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 496ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Manivoid AudioPolicyManager::setPhoneState(int state) { 506ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani ALOGV("setPhoneState() state %d", state); 516ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani audio_devices_t newDevice = AUDIO_DEVICE_NONE; 526ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani if (state < 0 || state >= AudioSystem::NUM_MODES) { 536ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani ALOGW("setPhoneState() invalid state %d", state); 546ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani return; 556ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani } 566ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani 576ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani if (state == mPhoneState) { 586ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani ALOGW("setPhoneState() setting same state %d", state); 596ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani return; 606ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani } 616ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani 626ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // if leaving call state, handle special case of active streams 636ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // pertaining to sonification strategy see handleIncallSonification() 646ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani if (isInCall()) { 656ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani ALOGV("setPhoneState() in call state management: new state is %d", state); 666ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { 676ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani handleIncallSonification(stream, false, true); 686ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani } 696ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani } 706ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani 716ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // store previous phone state for management of sonification strategy below 726ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani int oldState = mPhoneState; 736ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani mPhoneState = state; 746ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani bool force = false; 756ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani 766ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // are we entering or starting a call 776ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani if (!isStateInCall(oldState) && isStateInCall(state)) { 786ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani ALOGV(" Entering call in setPhoneState()"); 796ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // force routing command to audio hardware when starting a call 806ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // even if no device change is needed 816ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani force = true; 826ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani } else if (isStateInCall(oldState) && !isStateInCall(state)) { 836ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani ALOGV(" Exiting call in setPhoneState()"); 846ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // force routing command to audio hardware when exiting a call 856ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // even if no device change is needed 866ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani force = true; 876ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani } else if (isStateInCall(state) && (state != oldState)) { 886ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani ALOGV(" Switching between telephony and VoIP in setPhoneState()"); 896ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // force routing command to audio hardware when switching between telephony and VoIP 906ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // even if no device change is needed 916ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani force = true; 926ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani } 936ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani 946ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // check for device and output changes triggered by new phone state 956ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani newDevice = getNewDevice(mPrimaryOutput, false /*fromCache*/); 966ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani checkA2dpSuspend(); 976ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani checkOutputForAllStrategies(); 986ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani updateDevicesAndOutputs(); 996ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani 1006ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mPrimaryOutput); 1016ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani 1026ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // force routing command to audio hardware when ending call 1036ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // even if no device change is needed 1046ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani if (isStateInCall(oldState) && newDevice == AUDIO_DEVICE_NONE) { 1056ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani newDevice = hwOutputDesc->device(); 1066ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani } 1076ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani 1086ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // when changing from ring tone to in call mode, mute the ringing tone 1096ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // immediately and delay the route change to avoid sending the ring tone 1106ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // tail into the earpiece or headset. 1116ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani int delayMs = 0; 1126ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani if (isStateInCall(state) && oldState == AudioSystem::MODE_RINGTONE) { 1136ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // delay the device change command by twice the output latency to have some margin 1146ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // and be sure that audio buffers not yet affected by the mute are out when 1156ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // we actually apply the route change 1166ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani delayMs = hwOutputDesc->mLatency*2; 1176ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani setStreamMute(AudioSystem::RING, true, mPrimaryOutput); 1186ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani } 1196ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani 1206ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani if (isStateInCall(state)) { 1216ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani for (size_t i = 0; i < mOutputs.size(); i++) { 1226ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani AudioOutputDescriptor *desc = mOutputs.valueAt(i); 1236ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani //take the biggest latency for all outputs 1246ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani if (delayMs < desc->mLatency*2) { 1256ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani delayMs = desc->mLatency*2; 1266ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani } 1276ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani //mute STRATEGY_MEDIA on all outputs 1286ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani if (desc->strategyRefCount(STRATEGY_MEDIA) != 0) { 1296ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani setStrategyMute(STRATEGY_MEDIA, true, mOutputs.keyAt(i)); 1306ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani setStrategyMute(STRATEGY_MEDIA, false, mOutputs.keyAt(i), MUTE_TIME_MS, 1316ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani getDeviceForStrategy(STRATEGY_MEDIA, true /*fromCache*/)); 1326ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani } 1336ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani } 1346ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani } 1356ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani 1366ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // Ignore the delay to enable voice call on this target as the enabling the 1376ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // voice call has enough delay to make sure the ringtone audio completely 1386ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // played out 1396ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani if (state == AudioSystem::MODE_IN_CALL && oldState == AudioSystem::MODE_RINGTONE) { 140e365ed0cb095eed5fbc6a86c21642113e2c24f21Devin Kim delayMs = 40; 1416ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani } 1426ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani 1436ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // change routing is necessary 1446ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani setOutputDevice(mPrimaryOutput, newDevice, force, delayMs); 1456ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani 1466ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // if entering in call state, handle special case of active streams 1476ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // pertaining to sonification strategy see handleIncallSonification() 1486ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani if (isStateInCall(state)) { 1496ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani ALOGV("setPhoneState() in call state management: new state is %d", state); 1506ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // unmute the ringing tone after a sufficient delay if it was muted before 1516ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // setting output device above 1526ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani if (oldState == AudioSystem::MODE_RINGTONE) { 1536ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani setStreamMute(AudioSystem::RING, false, mPrimaryOutput, MUTE_TIME_MS); 1546ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani } 1556ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { 1566ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani handleIncallSonification(stream, true, true); 1576ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani } 1586ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani } 1596ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani 1606ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani // Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE 1616ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani if (state == AudioSystem::MODE_RINGTONE && 1626ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani isStreamActive(AudioSystem::MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)) { 1636ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani mLimitRingtoneVolume = true; 1646ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani } else { 1656ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani mLimitRingtoneVolume = false; 1666ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani } 1676ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani} 1686ae807c434c814a2ba6a84198a536d3a4b4153deSathishKumar Mani 1694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}; // namespace androidi_audio_legacy 170