Fix issue 2416481: Support Voice Dialer over BT SCO.
- AudioPolicyManager: allow platform specific choice for opening a direct output. Also fixed problems in direct output management. - AudioFliinger: use shorter standby delay and track inactivity grace period for direct output thread to free hardware resources as soon as possible. - AudioSystem: do not use cached output selection in getOutput() when a direct output can be selected. Change-Id: If44b50d29237b8402ffd7a5ba1dc43c56f903e9b
This commit is contained in:
@@ -72,6 +72,10 @@ static const float MAX_GAIN = 4096.0f;
|
||||
// 50 * ~20msecs = 1 second
|
||||
static const int8_t kMaxTrackRetries = 50;
|
||||
static const int8_t kMaxTrackStartupRetries = 50;
|
||||
// allow less retry attempts on direct output thread.
|
||||
// direct outputs can be a scarce resource in audio hardware and should
|
||||
// be released as quickly as possible.
|
||||
static const int8_t kMaxTrackRetriesDirect = 2;
|
||||
|
||||
static const int kDumpLockRetries = 50;
|
||||
static const int kDumpLockSleep = 20000;
|
||||
@@ -1794,6 +1798,9 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
|
||||
uint32_t activeSleepTime = activeSleepTimeUs();
|
||||
uint32_t idleSleepTime = idleSleepTimeUs();
|
||||
uint32_t sleepTime = idleSleepTime;
|
||||
// use shorter standby delay as on normal output to release
|
||||
// hardware resources as soon as possible
|
||||
nsecs_t standbyDelay = microseconds(activeSleepTime*2);
|
||||
|
||||
|
||||
while (!exitPending())
|
||||
@@ -1810,6 +1817,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
|
||||
mixBufferSize = mFrameCount*mFrameSize;
|
||||
activeSleepTime = activeSleepTimeUs();
|
||||
idleSleepTime = idleSleepTimeUs();
|
||||
standbyDelay = microseconds(activeSleepTime*2);
|
||||
}
|
||||
|
||||
// put audio hardware into standby after short delay
|
||||
@@ -1842,7 +1850,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
|
||||
}
|
||||
}
|
||||
|
||||
standbyTime = systemTime() + kStandbyTimeInNsecs;
|
||||
standbyTime = systemTime() + standbyDelay;
|
||||
sleepTime = idleSleepTime;
|
||||
continue;
|
||||
}
|
||||
@@ -1896,7 +1904,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
|
||||
}
|
||||
|
||||
// reset retry count
|
||||
track->mRetryCount = kMaxTrackRetries;
|
||||
track->mRetryCount = kMaxTrackRetriesDirect;
|
||||
activeTrack = t;
|
||||
mixerStatus = MIXER_TRACKS_READY;
|
||||
} else {
|
||||
@@ -1949,7 +1957,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
|
||||
activeTrack->releaseBuffer(&buffer);
|
||||
}
|
||||
sleepTime = 0;
|
||||
standbyTime = systemTime() + kStandbyTimeInNsecs;
|
||||
standbyTime = systemTime() + standbyDelay;
|
||||
} else {
|
||||
if (sleepTime == 0) {
|
||||
if (mixerStatus == MIXER_TRACKS_ENABLED) {
|
||||
|
||||
@@ -458,11 +458,8 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str
|
||||
}
|
||||
#endif //AUDIO_POLICY_TEST
|
||||
|
||||
// open a direct output if:
|
||||
// 1 a direct output is explicitely requested
|
||||
// 2 the audio format is compressed
|
||||
if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
|
||||
(format !=0 && !AudioSystem::isLinearPCM(format))) {
|
||||
// open a direct output if required by specified parameters
|
||||
if (needsDirectOuput(stream, samplingRate, format, channels, flags, device)) {
|
||||
|
||||
LOGV("getOutput() opening direct output device %x", device);
|
||||
AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
|
||||
@@ -472,7 +469,7 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str
|
||||
outputDesc->mChannels = channels;
|
||||
outputDesc->mLatency = 0;
|
||||
outputDesc->mFlags = (AudioSystem::output_flags)(flags | AudioSystem::OUTPUT_FLAG_DIRECT);
|
||||
outputDesc->mRefCount[stream] = 1;
|
||||
outputDesc->mRefCount[stream] = 0;
|
||||
output = mpClientInterface->openOutput(&outputDesc->mDevice,
|
||||
&outputDesc->mSamplingRate,
|
||||
&outputDesc->mFormat,
|
||||
@@ -609,6 +606,9 @@ status_t AudioPolicyManagerBase::stopOutput(audio_io_handle_t output, AudioSyste
|
||||
setStrategyMute(STRATEGY_MEDIA, false, mA2dpOutput, mOutputs.valueFor(mHardwareOutput)->mLatency*2);
|
||||
}
|
||||
#endif
|
||||
if (output != mHardwareOutput) {
|
||||
setOutputDevice(mHardwareOutput, getNewDevice(mHardwareOutput), true);
|
||||
}
|
||||
return NO_ERROR;
|
||||
} else {
|
||||
LOGW("stopOutput() refcount is already 0 for output %d", output);
|
||||
@@ -1550,10 +1550,10 @@ void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, uint32_t
|
||||
}
|
||||
#ifdef WITH_A2DP
|
||||
// filter devices according to output selected
|
||||
if (output == mHardwareOutput) {
|
||||
device &= ~AudioSystem::DEVICE_OUT_ALL_A2DP;
|
||||
} else {
|
||||
if (output == mA2dpOutput) {
|
||||
device &= AudioSystem::DEVICE_OUT_ALL_A2DP;
|
||||
} else {
|
||||
device &= ~AudioSystem::DEVICE_OUT_ALL_A2DP;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1562,8 +1562,7 @@ void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, uint32_t
|
||||
// - the requestede device is 0
|
||||
// - the requested device is the same as current device and force is not specified.
|
||||
// Doing this check here allows the caller to call setOutputDevice() without conditions
|
||||
if (device == 0 ||
|
||||
(device == prevDevice && !force)) {
|
||||
if ((device == 0 || device == prevDevice) && !force) {
|
||||
LOGV("setOutputDevice() setting same device %x or null device for output %d", device, output);
|
||||
return;
|
||||
}
|
||||
@@ -1666,7 +1665,7 @@ float AudioPolicyManagerBase::computeVolume(int stream, int index, audio_io_hand
|
||||
int volInt = (100 * (index - streamDesc.mIndexMin)) / (streamDesc.mIndexMax - streamDesc.mIndexMin);
|
||||
volume = AudioSystem::linearToLog(volInt);
|
||||
|
||||
// if a heaset is connected, apply the following rules to ring tones and notifications
|
||||
// if a headset is connected, apply the following rules to ring tones and notifications
|
||||
// to avoid sound level bursts in user's ears:
|
||||
// - always attenuate ring tones and notifications volume by 6dB
|
||||
// - if music is playing, always limit the volume to current music volume,
|
||||
@@ -1825,6 +1824,17 @@ void AudioPolicyManagerBase::handleIncallSonification(int stream, bool starting,
|
||||
}
|
||||
}
|
||||
|
||||
bool AudioPolicyManagerBase::needsDirectOuput(AudioSystem::stream_type stream,
|
||||
uint32_t samplingRate,
|
||||
uint32_t format,
|
||||
uint32_t channels,
|
||||
AudioSystem::output_flags flags,
|
||||
uint32_t device)
|
||||
{
|
||||
return ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
|
||||
(format !=0 && !AudioSystem::isLinearPCM(format)));
|
||||
}
|
||||
|
||||
// --- AudioOutputDescriptor class implementation
|
||||
|
||||
AudioPolicyManagerBase::AudioOutputDescriptor::AudioOutputDescriptor()
|
||||
|
||||
@@ -358,7 +358,7 @@ unsigned int AudioSystem::getInputFramesLost(audio_io_handle_t ioHandle) {
|
||||
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
|
||||
unsigned int result = 0;
|
||||
if (af == 0) return result;
|
||||
if (ioHandle == NULL) return result;
|
||||
if (ioHandle == 0) return result;
|
||||
|
||||
result = af->getInputFramesLost(ioHandle);
|
||||
return result;
|
||||
@@ -556,7 +556,18 @@ audio_io_handle_t AudioSystem::getOutput(stream_type stream,
|
||||
output_flags flags)
|
||||
{
|
||||
audio_io_handle_t output = 0;
|
||||
if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) == 0) {
|
||||
// Do not use stream to output map cache if the direct output
|
||||
// flag is set or if we are likely to use a direct output
|
||||
// (e.g voice call stream @ 8kHz could use BT SCO device and be routed to
|
||||
// a direct output on some platforms).
|
||||
// TODO: the output cache and stream to output mapping implementation needs to
|
||||
// be reworked for proper operation with direct outputs. This code is too specific
|
||||
// to the first use case we want to cover (Voice Recognition and Voice Dialer over
|
||||
// Bluetooth SCO
|
||||
if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) == 0 &&
|
||||
((stream != AudioSystem::VOICE_CALL && stream != AudioSystem::BLUETOOTH_SCO) ||
|
||||
channels != AudioSystem::CHANNEL_OUT_MONO ||
|
||||
(samplingRate != 8000 && samplingRate != 16000))) {
|
||||
Mutex::Autolock _l(gLock);
|
||||
output = AudioSystem::gStreamOutputMap.valueFor(stream);
|
||||
LOGV_IF((output != 0), "getOutput() read %d from cache for stream %d", output, stream);
|
||||
|
||||
Reference in New Issue
Block a user