audioflinger: fix track terminated before playing

When a track is terminated before any audio was written,
we should not send a drain request to the HAL. The drain
will be ignored and we will wait the async callback for ever.

Also fix a potential deadlock by not deleting a track with the
thread mutex held: mPreviousTrack changed from a sp to a raw pointer.

Bug: 11247103.
Change-Id: I0a4b47b099204c7c326d45d700234ab8f72d8eae
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 47dcca6..9c8fd1f 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -3884,15 +3884,11 @@
     :   DirectOutputThread(audioFlinger, output, id, device, OFFLOAD),
         mHwPaused(false),
         mFlushPending(false),
-        mPausedBytesRemaining(0)
+        mPausedBytesRemaining(0),
+        mPreviousTrack(NULL)
 {
 }
 
-AudioFlinger::OffloadThread::~OffloadThread()
-{
-    mPreviousTrack.clear();
-}
-
 void AudioFlinger::OffloadThread::threadLoop_exit()
 {
     if (mFlushPending || mHwPaused) {
@@ -3928,7 +3924,7 @@
         Track* const track = t.get();
         audio_track_cblk_t* cblk = track->cblk();
         if (mPreviousTrack != NULL) {
-            if (t != mPreviousTrack) {
+            if (t.get() != mPreviousTrack) {
                 // Flush any data still being written from last track
                 mBytesRemaining = 0;
                 if (mPausedBytesRemaining) {
@@ -3943,7 +3939,7 @@
                 }
             }
         }
-        mPreviousTrack = t;
+        mPreviousTrack = t.get();
         bool last = (i == (count - 1));
         if (track->isPausing()) {
             track->setPaused();
@@ -4008,7 +4004,8 @@
                     // has been written
                     ALOGV("OffloadThread: underrun and STOPPING_1 -> draining, STOPPING_2");
                     track->mState = TrackBase::STOPPING_2; // so presentation completes after drain
-                    if (last) {
+                    // do not drain if no data was ever sent to HAL (mStandby == true)
+                    if (last && !mStandby) {
                         sleepTime = 0;
                         standbyTime = systemTime() + standbyDelay;
                         mixerStatus = MIXER_DRAIN_TRACK;
@@ -4022,8 +4019,8 @@
                     }
                 }
             } else if (track->isStopping_2()) {
-                // Drain has completed, signal presentation complete
-                if (!(mDrainSequence & 1) || !last) {
+                // Drain has completed or we are in standby, signal presentation complete
+                if (!(mDrainSequence & 1) || !last || mStandby) {
                     track->mState = TrackBase::STOPPED;
                     size_t audioHALFrames =
                             (mOutput->stream->get_latency(mOutput->stream)*mSampleRate) / 1000;
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 802b784..a5d2169 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -735,7 +735,7 @@
 
     OffloadThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
                         audio_io_handle_t id, uint32_t device);
-    virtual                 ~OffloadThread();
+    virtual                 ~OffloadThread() {};
 
 protected:
     // threadLoop snippets
@@ -755,7 +755,7 @@
     bool        mFlushPending;
     size_t      mPausedWriteLength;     // length in bytes of write interrupted by pause
     size_t      mPausedBytesRemaining;  // bytes still waiting in mixbuffer after resume
-    sp<Track>   mPreviousTrack;         // used to detect track switch
+    Track       *mPreviousTrack;         // used to detect track switch
 };
 
 class AsyncCallbackThread : public Thread {