You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
6.4 KiB
169 lines
6.4 KiB
/* |
|
* Copyright (C) 2009 The Android Open Source Project |
|
* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
|
|
#define LOG_TAG "AudioPolicyManagerALSA" |
|
//#define LOG_NDEBUG 0 |
|
#define LOG_NDDEBUG 0 |
|
#include <utils/Log.h> |
|
|
|
#include "AudioPolicyManagerALSA.h" |
|
#include <media/mediarecorder.h> |
|
|
|
namespace android_audio_legacy { |
|
|
|
// ---------------------------------------------------------------------------- |
|
// AudioPolicyManagerALSA |
|
// ---------------------------------------------------------------------------- |
|
|
|
//Compiling error seen if AudioParamer doesn't exist in this file |
|
|
|
AudioParameter param; |
|
|
|
// --- class factory |
|
|
|
|
|
extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface) |
|
{ |
|
return new AudioPolicyManager(clientInterface); |
|
} |
|
|
|
extern "C" void destroyAudioPolicyManager(AudioPolicyInterface *interface) |
|
{ |
|
delete interface; |
|
} |
|
|
|
void AudioPolicyManager::setPhoneState(int state) { |
|
ALOGV("setPhoneState() state %d", state); |
|
audio_devices_t newDevice = AUDIO_DEVICE_NONE; |
|
if (state < 0 || state >= AudioSystem::NUM_MODES) { |
|
ALOGW("setPhoneState() invalid state %d", state); |
|
return; |
|
} |
|
|
|
if (state == mPhoneState) { |
|
ALOGW("setPhoneState() setting same state %d", state); |
|
return; |
|
} |
|
|
|
// if leaving call state, handle special case of active streams |
|
// pertaining to sonification strategy see handleIncallSonification() |
|
if (isInCall()) { |
|
ALOGV("setPhoneState() in call state management: new state is %d", state); |
|
for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { |
|
handleIncallSonification(stream, false, true); |
|
} |
|
} |
|
|
|
// store previous phone state for management of sonification strategy below |
|
int oldState = mPhoneState; |
|
mPhoneState = state; |
|
bool force = false; |
|
|
|
// are we entering or starting a call |
|
if (!isStateInCall(oldState) && isStateInCall(state)) { |
|
ALOGV(" Entering call in setPhoneState()"); |
|
// force routing command to audio hardware when starting a call |
|
// even if no device change is needed |
|
force = true; |
|
} else if (isStateInCall(oldState) && !isStateInCall(state)) { |
|
ALOGV(" Exiting call in setPhoneState()"); |
|
// force routing command to audio hardware when exiting a call |
|
// even if no device change is needed |
|
force = true; |
|
} else if (isStateInCall(state) && (state != oldState)) { |
|
ALOGV(" Switching between telephony and VoIP in setPhoneState()"); |
|
// force routing command to audio hardware when switching between telephony and VoIP |
|
// even if no device change is needed |
|
force = true; |
|
} |
|
|
|
// check for device and output changes triggered by new phone state |
|
newDevice = getNewDevice(mPrimaryOutput, false /*fromCache*/); |
|
checkA2dpSuspend(); |
|
checkOutputForAllStrategies(); |
|
updateDevicesAndOutputs(); |
|
|
|
AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mPrimaryOutput); |
|
|
|
// force routing command to audio hardware when ending call |
|
// even if no device change is needed |
|
if (isStateInCall(oldState) && newDevice == AUDIO_DEVICE_NONE) { |
|
newDevice = hwOutputDesc->device(); |
|
} |
|
|
|
// when changing from ring tone to in call mode, mute the ringing tone |
|
// immediately and delay the route change to avoid sending the ring tone |
|
// tail into the earpiece or headset. |
|
int delayMs = 0; |
|
if (isStateInCall(state) && oldState == AudioSystem::MODE_RINGTONE) { |
|
// delay the device change command by twice the output latency to have some margin |
|
// and be sure that audio buffers not yet affected by the mute are out when |
|
// we actually apply the route change |
|
delayMs = hwOutputDesc->mLatency*2; |
|
setStreamMute(AudioSystem::RING, true, mPrimaryOutput); |
|
} |
|
|
|
if (isStateInCall(state)) { |
|
for (size_t i = 0; i < mOutputs.size(); i++) { |
|
AudioOutputDescriptor *desc = mOutputs.valueAt(i); |
|
//take the biggest latency for all outputs |
|
if (delayMs < desc->mLatency*2) { |
|
delayMs = desc->mLatency*2; |
|
} |
|
//mute STRATEGY_MEDIA on all outputs |
|
if (desc->strategyRefCount(STRATEGY_MEDIA) != 0) { |
|
setStrategyMute(STRATEGY_MEDIA, true, mOutputs.keyAt(i)); |
|
setStrategyMute(STRATEGY_MEDIA, false, mOutputs.keyAt(i), MUTE_TIME_MS, |
|
getDeviceForStrategy(STRATEGY_MEDIA, true /*fromCache*/)); |
|
} |
|
} |
|
} |
|
|
|
// Ignore the delay to enable voice call on this target as the enabling the |
|
// voice call has enough delay to make sure the ringtone audio completely |
|
// played out |
|
if (state == AudioSystem::MODE_IN_CALL && oldState == AudioSystem::MODE_RINGTONE) { |
|
delayMs = 40; |
|
} |
|
|
|
// change routing is necessary |
|
setOutputDevice(mPrimaryOutput, newDevice, force, delayMs); |
|
|
|
// if entering in call state, handle special case of active streams |
|
// pertaining to sonification strategy see handleIncallSonification() |
|
if (isStateInCall(state)) { |
|
ALOGV("setPhoneState() in call state management: new state is %d", state); |
|
// unmute the ringing tone after a sufficient delay if it was muted before |
|
// setting output device above |
|
if (oldState == AudioSystem::MODE_RINGTONE) { |
|
setStreamMute(AudioSystem::RING, false, mPrimaryOutput, MUTE_TIME_MS); |
|
} |
|
for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { |
|
handleIncallSonification(stream, true, true); |
|
} |
|
} |
|
|
|
// Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE |
|
if (state == AudioSystem::MODE_RINGTONE && |
|
isStreamActive(AudioSystem::MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)) { |
|
mLimitRingtoneVolume = true; |
|
} else { |
|
mLimitRingtoneVolume = false; |
|
} |
|
} |
|
|
|
}; // namespace androidi_audio_legacy
|
|
|