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.
170 lines
6.4 KiB
170 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
|