diff options
-rw-r--r-- | libs/audioflinger/AudioFlinger.cpp | 14 | ||||
-rw-r--r-- | libs/audioflinger/AudioPolicyManagerBase.cpp | 34 | ||||
-rw-r--r-- | media/libmedia/AudioSystem.cpp | 15 |
3 files changed, 46 insertions, 17 deletions
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp index 790221285517..815a36737ef9 100644 --- a/libs/audioflinger/AudioFlinger.cpp +++ b/libs/audioflinger/AudioFlinger.cpp @@ -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) { diff --git a/libs/audioflinger/AudioPolicyManagerBase.cpp b/libs/audioflinger/AudioPolicyManagerBase.cpp index a61221a1a353..c8b3f487a02c 100644 --- a/libs/audioflinger/AudioPolicyManagerBase.cpp +++ b/libs/audioflinger/AudioPolicyManagerBase.cpp @@ -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() diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 4b364f2da0a6..5e6ce425c763 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -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); |