OSDN Git Service

Fix issue 2416481: Support Voice Dialer over BT SCO.
authorEric Laurent <elaurent@google.com>
Thu, 11 Mar 2010 22:47:00 +0000 (14:47 -0800)
committerEric Laurent <elaurent@google.com>
Wed, 17 Mar 2010 00:32:18 +0000 (17:32 -0700)
- 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

libs/audioflinger/AudioFlinger.cpp
libs/audioflinger/AudioPolicyManagerBase.cpp

index 7902212..815a367 100644 (file)
@@ -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) {
index a61221a..c8b3f48 100644 (file)
@@ -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()