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