audioflinger: various offload playback fixes

Revert underrun sleep time optimization added for
offload by commit 51716185 which can cause music to pause for a few
seconds in some corner cases.

Allow underruns in STOPPING_1 state to avoid dropping last buffer
received by the AudioTrack callback after stop() is called by the
client.

Allow interruption of thread loop sleep if a command is pending to
speed up track start sequence.

Do not wait for a full AudioTrack buffer before writing to audio HAL
when resuming playback or transitioning to next track.

Also moved log level for underruns in AudioSink from I to D to reduce
spam on user builds.

Bug: 28545177
Bug: 27682362
Bug: 28347796

Change-Id: I05b651b7878a2d2eedcac43cd669e32add171d40
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 35f439b..cd91e72 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -2150,7 +2150,7 @@
         //
         // The underrun event is sent once per track underrun; the condition is reset
         // when more data is sent to the AudioTrack.
-        ALOGI("callbackwrapper: EVENT_UNDERRUN (discarded)");
+        ALOGD("callbackwrapper: EVENT_UNDERRUN (discarded)");
         break;
 
     default:
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 1d575b3..2b0d4c8 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1843,8 +1843,7 @@
 
         PlaybackThread *thread;
         if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
-            thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady,
-                                       config->offload_info.bit_rate);
+            thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady);
             ALOGV("openOutput_l() created offload output: ID %d thread %p", *output, thread);
         } else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT)
                 || !isValidPcmSinkFormat(config->format)
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index bee0447..d296ee3 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -110,12 +110,7 @@
 // direct outputs can be a scarce resource in audio hardware and should
 // be released as quickly as possible.
 static const int8_t kMaxTrackRetriesDirect = 2;
-// retry count before removing active track in case of underrun on offloaded thread:
-// we need to make sure that AudioTrack client has enough time to send large buffers
-//FIXME may be more appropriate if expressed in time units. Need to revise how underrun is handled
-// for offloaded tracks
-static const int8_t kMaxTrackRetriesOffload = 10;
-static const int8_t kMaxTrackStartupRetriesOffload = 100;
+
 
 
 // don't warn about blocked writes or record buffer overflows more often than this
@@ -148,10 +143,6 @@
 // Direct output thread minimum sleep time in idle or active(underrun) state
 static const nsecs_t kDirectMinSleepTimeUs = 10000;
 
-// Offloaded output bit rate in bits per second when unknown.
-// Used for sleep time calculation, so use a high default bitrate to be conservative on sleep time.
-static const uint32_t kOffloadDefaultBitRateBps = 1500000;
-
 
 // Whether to use fast mixer
 static const enum {
@@ -1567,8 +1558,7 @@
                                              audio_io_handle_t id,
                                              audio_devices_t device,
                                              type_t type,
-                                             bool systemReady,
-                                             uint32_t bitRate)
+                                             bool systemReady)
     :   ThreadBase(audioFlinger, id, device, AUDIO_DEVICE_NONE, type, systemReady),
         mNormalFrameCount(0), mSinkBuffer(NULL),
         mMixerBufferEnabled(AudioFlinger::kEnableExtendedPrecision),
@@ -1631,13 +1621,6 @@
         mStreamTypes[stream].volume = mAudioFlinger->streamVolume_l(stream);
         mStreamTypes[stream].mute = mAudioFlinger->streamMute_l(stream);
     }
-
-    if (audio_has_proportional_frames(mFormat)) {
-        mBufferDurationUs = (uint32_t)((mNormalFrameCount * 1000000LL) / mSampleRate);
-    } else {
-        bitRate = bitRate != 0 ? bitRate : kOffloadDefaultBitRateBps;
-        mBufferDurationUs = (uint32_t)((mBufferSize * 8 * 1000000LL) / bitRate);
-    }
 }
 
 AudioFlinger::PlaybackThread::~PlaybackThread()
@@ -2049,12 +2032,18 @@
 
         // set retry count for buffer fill
         if (track->isOffloaded()) {
-            track->mRetryCount = kMaxTrackStartupRetriesOffload;
+            if (track->isStopping_1()) {
+                track->mRetryCount = kMaxTrackStopRetriesOffload;
+            } else {
+                track->mRetryCount = kMaxTrackStartupRetriesOffload;
+            }
+            track->mFillingUpStatus = mStandby ? Track::FS_FILLING : Track::FS_FILLED;
         } else {
             track->mRetryCount = kMaxTrackStartupRetries;
+            track->mFillingUpStatus =
+                    track->sharedBuffer() != 0 ? Track::FS_FILLED : Track::FS_FILLING;
         }
 
-        track->mFillingUpStatus = track->sharedBuffer() != 0 ? Track::FS_FILLED : Track::FS_FILLING;
         track->mResetDone = false;
         track->mPresentationCompleteFrames = 0;
         mActiveTracks.add(track);
@@ -3181,32 +3170,9 @@
 
             } else {
                 ATRACE_BEGIN("sleep");
-                if ((mType == OFFLOAD) && !audio_has_proportional_frames(mFormat)) {
-                    Mutex::Autolock _l(mLock);
-                    if (!mSignalPending && !exitPending()) {
-                        // If more than one buffer has been written to the audio HAL since exiting
-                        // standby or last flush, do not sleep more than one buffer duration
-                        // since last write and not less than kDirectMinSleepTimeUs.
-                        // Wake up if a command is received
-                        uint32_t timeoutUs = mSleepTimeUs;
-                        if (mBytesWritten >= (int64_t) mBufferSize) {
-                            nsecs_t now = systemTime();
-                            uint32_t deltaUs = (uint32_t)((now - mLastWriteTime) / 1000);
-                            if (timeoutUs + deltaUs > mBufferDurationUs) {
-                                if (mBufferDurationUs > deltaUs) {
-                                    timeoutUs = mBufferDurationUs - deltaUs;
-                                    if (timeoutUs < kDirectMinSleepTimeUs) {
-                                        timeoutUs = kDirectMinSleepTimeUs;
-                                    }
-                                } else {
-                                    timeoutUs = kDirectMinSleepTimeUs;
-                                }
-                            }
-                        }
-                        mWaitWorkCV.waitRelative(mLock, microseconds((nsecs_t)timeoutUs));
-                    }
-                } else {
-                    usleep(mSleepTimeUs);
+                Mutex::Autolock _l(mLock);
+                if (!mSignalPending && mConfigEvents.isEmpty() && !exitPending()) {
+                    mWaitWorkCV.waitRelative(mLock, microseconds((nsecs_t)mSleepTimeUs));
                 }
                 ATRACE_END();
             }
@@ -4592,17 +4558,16 @@
 // ----------------------------------------------------------------------------
 
 AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
-        AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, bool systemReady,
-        uint32_t bitRate)
-    :   PlaybackThread(audioFlinger, output, id, device, DIRECT, systemReady, bitRate)
+        AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, bool systemReady)
+    :   PlaybackThread(audioFlinger, output, id, device, DIRECT, systemReady)
         // mLeftVolFloat, mRightVolFloat
 {
 }
 
 AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
         AudioStreamOut* output, audio_io_handle_t id, uint32_t device,
-        ThreadBase::type_t type, bool systemReady, uint32_t bitRate)
-    :   PlaybackThread(audioFlinger, output, id, device, type, systemReady, bitRate)
+        ThreadBase::type_t type, bool systemReady)
+    :   PlaybackThread(audioFlinger, output, id, device, type, systemReady)
         // mLeftVolFloat, mRightVolFloat
 {
 }
@@ -4908,14 +4873,7 @@
     }
     if (mSleepTimeUs == 0) {
         if (mMixerStatus == MIXER_TRACKS_ENABLED) {
-            // For compressed offload, use faster sleep time when underruning until more than an
-            // entire buffer was written to the audio HAL
-            if (!audio_has_proportional_frames(mFormat) &&
-                    (mType == OFFLOAD) && (mBytesWritten < (int64_t) mBufferSize)) {
-                mSleepTimeUs = kDirectMinSleepTimeUs;
-            } else {
-                mSleepTimeUs = mActiveSleepTimeUs;
-            }
+            mSleepTimeUs = mActiveSleepTimeUs;
         } else {
             mSleepTimeUs = mIdleSleepTimeUs;
         }
@@ -5187,9 +5145,8 @@
 
 // ----------------------------------------------------------------------------
 AudioFlinger::OffloadThread::OffloadThread(const sp<AudioFlinger>& audioFlinger,
-        AudioStreamOut* output, audio_io_handle_t id, uint32_t device, bool systemReady,
-        uint32_t bitRate)
-    :   DirectOutputThread(audioFlinger, output, id, device, OFFLOAD, systemReady, bitRate),
+        AudioStreamOut* output, audio_io_handle_t id, uint32_t device, bool systemReady)
+    :   DirectOutputThread(audioFlinger, output, id, device, OFFLOAD, systemReady),
         mPausedWriteLength(0), mPausedBytesRemaining(0), mKeepWakeLock(true)
 {
     //FIXME: mStandby should be set to true by ThreadBase constructor
@@ -5273,7 +5230,11 @@
             }
             tracksToRemove->add(track);
         } else if (track->isFlushPending()) {
-            track->mRetryCount = kMaxTrackRetriesOffload;
+            if (track->isStopping_1()) {
+                track->mRetryCount = kMaxTrackStopRetriesOffload;
+            } else {
+                track->mRetryCount = kMaxTrackRetriesOffload;
+            }
             track->flushAck();
             if (last) {
                 mFlushPending = true;
@@ -5334,38 +5295,47 @@
                 }
                 mPreviousTrack = track;
                 // reset retry count
-                track->mRetryCount = kMaxTrackRetriesOffload;
+                if (track->isStopping_1()) {
+                    track->mRetryCount = kMaxTrackStopRetriesOffload;
+                } else {
+                    track->mRetryCount = kMaxTrackRetriesOffload;
+                }
                 mActiveTrack = t;
                 mixerStatus = MIXER_TRACKS_READY;
             }
         } else {
             ALOGVV("OffloadThread: track %d s=%08x [NOT READY]", track->name(), cblk->mServer);
             if (track->isStopping_1()) {
-                // Hardware buffer can hold a large amount of audio so we must
-                // wait for all current track's data to drain before we say
-                // that the track is stopped.
-                if (mBytesRemaining == 0) {
-                    // Only start draining when all data in mixbuffer
-                    // has been written
-                    ALOGV("OffloadThread: underrun and STOPPING_1 -> draining, STOPPING_2");
-                    track->mState = TrackBase::STOPPING_2; // so presentation completes after drain
-                    // do not drain if no data was ever sent to HAL (mStandby == true)
-                    if (last && !mStandby) {
-                        // do not modify drain sequence if we are already draining. This happens
-                        // when resuming from pause after drain.
-                        if ((mDrainSequence & 1) == 0) {
-                            mSleepTimeUs = 0;
-                            mStandbyTimeNs = systemTime() + mStandbyDelayNs;
-                            mixerStatus = MIXER_DRAIN_TRACK;
-                            mDrainSequence += 2;
-                        }
-                        if (mHwPaused) {
-                            // It is possible to move from PAUSED to STOPPING_1 without
-                            // a resume so we must ensure hardware is running
-                            doHwResume = true;
-                            mHwPaused = false;
+                if (--(track->mRetryCount) <= 0) {
+                    // Hardware buffer can hold a large amount of audio so we must
+                    // wait for all current track's data to drain before we say
+                    // that the track is stopped.
+                    if (mBytesRemaining == 0) {
+                        // Only start draining when all data in mixbuffer
+                        // has been written
+                        ALOGV("OffloadThread: underrun and STOPPING_1 -> draining, STOPPING_2");
+                        track->mState = TrackBase::STOPPING_2; // so presentation completes after
+                        // drain do not drain if no data was ever sent to HAL (mStandby == true)
+                        if (last && !mStandby) {
+                            // do not modify drain sequence if we are already draining. This happens
+                            // when resuming from pause after drain.
+                            if ((mDrainSequence & 1) == 0) {
+                                mSleepTimeUs = 0;
+                                mStandbyTimeNs = systemTime() + mStandbyDelayNs;
+                                mixerStatus = MIXER_DRAIN_TRACK;
+                                mDrainSequence += 2;
+                            }
+                            if (mHwPaused) {
+                                // It is possible to move from PAUSED to STOPPING_1 without
+                                // a resume so we must ensure hardware is running
+                                doHwResume = true;
+                                mHwPaused = false;
+                            }
                         }
                     }
+                } else if (last) {
+                    ALOGV("stopping1 underrun retries left %d", track->mRetryCount);
+                    mixerStatus = MIXER_TRACKS_ENABLED;
                 }
             } else if (track->isStopping_2()) {
                 // Drain has completed or we are in standby, signal presentation complete
@@ -5456,20 +5426,6 @@
     }
 }
 
-uint32_t AudioFlinger::OffloadThread::activeSleepTimeUs() const
-{
-    uint32_t time;
-    if (audio_has_proportional_frames(mFormat)) {
-        time = PlaybackThread::activeSleepTimeUs();
-    } else {
-        // sleep time is half the duration of an audio HAL buffer.
-        // Note: This can be problematic in case of underrun with variable bit rate and
-        // current rate is much less than initial rate.
-        time = (uint32_t)max(kDirectMinSleepTimeUs, mBufferDurationUs / 2);
-    }
-    return time;
-}
-
 void AudioFlinger::OffloadThread::invalidateTracks(audio_stream_type_t streamType)
 {
     Mutex::Autolock _l(mLock);
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 0ddd279..1cceb6d 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -486,9 +486,16 @@
         // suspend by audio policy manager is orthogonal to mixer state
     };
 
+    // retry count before removing active track in case of underrun on offloaded thread:
+    // we need to make sure that AudioTrack client has enough time to send large buffers
+    //FIXME may be more appropriate if expressed in time units. Need to revise how underrun is
+    // handled for offloaded tracks
+    static const int8_t kMaxTrackRetriesOffload = 20;
+    static const int8_t kMaxTrackStartupRetriesOffload = 100;
+    static const int8_t kMaxTrackStopRetriesOffload = 2;
+
     PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
-                   audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady,
-                   uint32_t bitRate = 0);
+                   audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady);
     virtual             ~PlaybackThread();
 
                 void        dump(int fd, const Vector<String16>& args);
@@ -843,8 +850,6 @@
                 bool        mHwSupportsPause;
                 bool        mHwPaused;
                 bool        mFlushPending;
-                uint32_t    mBufferDurationUs;      // estimated duration of an audio HAL buffer
-                                                    // based on initial bit rate (offload only)
 };
 
 class MixerThread : public PlaybackThread {
@@ -935,8 +940,7 @@
 public:
 
     DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
-                       audio_io_handle_t id, audio_devices_t device, bool systemReady,
-                       uint32_t bitRate = 0);
+                       audio_io_handle_t id, audio_devices_t device, bool systemReady);
     virtual                 ~DirectOutputThread();
 
     // Thread virtuals
@@ -969,7 +973,7 @@
 
     DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
                         audio_io_handle_t id, uint32_t device, ThreadBase::type_t type,
-                        bool systemReady, uint32_t bitRate = 0);
+                        bool systemReady);
     void processVolume_l(Track *track, bool lastTrack);
 
     // prepareTracks_l() tells threadLoop_mix() the name of the single active track
@@ -985,8 +989,7 @@
 public:
 
     OffloadThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
-                        audio_io_handle_t id, uint32_t device,
-                        bool systemReady, uint32_t bitRate);
+                        audio_io_handle_t id, uint32_t device, bool systemReady);
     virtual                 ~OffloadThread() {};
     virtual     void        flushHw_l();
 
@@ -995,8 +998,6 @@
     virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
     virtual     void        threadLoop_exit();
 
-    virtual     uint32_t    activeSleepTimeUs() const;
-
     virtual     bool        waitingAsyncCallback();
     virtual     bool        waitingAsyncCallback_l();
     virtual     void        invalidateTracks(audio_stream_type_t streamType);
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 41cb030..364e339 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -373,7 +373,7 @@
     // client == 0 implies sharedBuffer == 0
     ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
 
-    ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(),
+    ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %zu", sharedBuffer->pointer(),
             sharedBuffer->size());
 
     if (mCblk == NULL) {
@@ -728,6 +728,9 @@
                 // For an offloaded track this starts a drain and state will
                 // move to STOPPING_2 when drain completes and then STOPPED
                 mState = STOPPING_1;
+                if (isOffloaded()) {
+                    mRetryCount = PlaybackThread::kMaxTrackStopRetriesOffload;
+                }
             }
             playbackThread->broadcast_l();
             ALOGV("not stopping/stopped => stopping/stopped (%d) on thread %p", mName,