Log audio information to ensure complete delivery

Test: Audio playback
Bug: 30572472
Change-Id: Ibad6fc202692cd3480ae726627252afdead083f3
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 7663fef..d322f05 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -653,6 +653,8 @@
         mState = STATE_STOPPING;
     } else {
         mState = STATE_STOPPED;
+        ALOGD_IF(mSharedBuffer == nullptr,
+                "stop() called with %u frames delivered", mReleased.value());
         mReleased = 0;
     }
 
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index c56dcc1..d791e13 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -19,6 +19,7 @@
 #define ANDROID_AUDIO_FLINGER_H
 
 #include "Configuration.h"
+#include <deque>
 #include <stdint.h>
 #include <sys/types.h>
 #include <limits.h>
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 0f403ae..14a7b8b 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1737,6 +1737,7 @@
     dumpInternals(fd, args);
     dumpTracks(fd, args);
     dumpEffectChains(fd, args);
+    mLocalLog.dump(fd, args, "  " /* prefix */);
 }
 
 void AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args __unused)
@@ -2201,6 +2202,10 @@
             chain->incActiveTrackCnt();
         }
 
+        char buffer[256];
+        track->dump(buffer, ARRAY_SIZE(buffer), false /* active */);
+        mLocalLog.log("addTrack_l    (%p) %s", track.get(), buffer + 4); // log for analysis
+
         status = NO_ERROR;
     }
 
@@ -2226,6 +2231,11 @@
 void AudioFlinger::PlaybackThread::removeTrack_l(const sp<Track>& track)
 {
     track->triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
+
+    char buffer[256];
+    track->dump(buffer, ARRAY_SIZE(buffer), false /* active */);
+    mLocalLog.log("removeTrack_l (%p) %s", track.get(), buffer + 4); // log for analysis
+
     mTracks.remove(track);
     deleteTrackName_l(track->name());
     // redundant as track is about to be destroyed, for dumpsys only
@@ -3421,6 +3431,10 @@
             }
             if (track->isTerminated()) {
                 removeTrack_l(track);
+            } else { // inactive but not terminated
+                char buffer[256];
+                track->dump(buffer, ARRAY_SIZE(buffer), false /* active */);
+                mLocalLog.log("removeTracks_l(%p) %s", track.get(), buffer + 4);
             }
         }
     }
@@ -3872,6 +3886,15 @@
         FastMixerStateQueue *sq = mFastMixer->sq();
         FastMixerState *state = sq->begin();
         if (!(state->mCommand & FastMixerState::IDLE)) {
+            // Report any frames trapped in the Monopipe
+            MonoPipe *monoPipe = (MonoPipe *)mPipeSink.get();
+            const long long pipeFrames = monoPipe->maxFrames() - monoPipe->availableToWrite();
+            mLocalLog.log("threadLoop_standby: framesWritten:%lld  suspendedFrames:%lld  "
+                    "monoPipeWritten:%lld  monoPipeLeft:%lld",
+                    (long long)mFramesWritten, (long long)mSuspendedFrames,
+                    (long long)mPipeSink->framesWritten(), pipeFrames);
+            mLocalLog.log("threadLoop_standby: %s", mTimestamp.toString().c_str());
+
             state->mCommand = FastMixerState::COLD_IDLE;
             state->mColdFutexAddr = &mFastMixerFutex;
             state->mColdGen++;
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index f353f3b..854e203 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -862,6 +862,78 @@
     uint32_t                mScreenState;   // cached copy of gScreenState
     static const size_t     kFastMixerLogSize = 4 * 1024;
     sp<NBLog::Writer>       mFastMixerNBLogWriter;
+
+    // Do not call from a sched_fifo thread as it uses a system time call
+    // and obtains a local mutex.
+    class LocalLog {
+    public:
+        void log(const char *fmt, ...) {
+            va_list val;
+            va_start(val, fmt);
+
+            // format to buffer
+            char buffer[512];
+            int length = vsnprintf(buffer, sizeof(buffer), fmt, val);
+            if (length >= (signed)sizeof(buffer)) {
+                length = sizeof(buffer) - 1;
+            }
+
+            // strip out trailing newline
+            while (length > 0 && buffer[length - 1] == '\n') {
+                buffer[--length] = 0;
+            }
+
+            // store in circular array
+            AutoMutex _l(mLock);
+            mLog.emplace_back(
+                    std::make_pair(systemTime(SYSTEM_TIME_REALTIME), std::string(buffer)));
+            if (mLog.size() > kLogSize) {
+                mLog.pop_front();
+            }
+
+            va_end(val);
+        }
+
+        void dump(int fd, const Vector<String16>& args, const char *prefix = "") {
+            if (!AudioFlinger::dumpTryLock(mLock)) return; // a local lock, shouldn't happen
+            if (mLog.size() > 0) {
+                bool dumpAll = false;
+                for (const auto &arg : args) {
+                    if (arg == String16("--locallog")) {
+                        dumpAll = true;
+                    }
+                }
+
+                dprintf(fd, "Local Log:\n");
+                auto it = mLog.begin();
+                if (!dumpAll && mLog.size() > kLogPrint) {
+                    it += (mLog.size() - kLogPrint);
+                }
+                for (; it != mLog.end(); ++it) {
+                    const int64_t ns = it->first;
+                    const int ns_per_sec = 1000000000;
+                    const time_t sec = ns / ns_per_sec;
+                    struct tm tm;
+                    localtime_r(&sec, &tm);
+
+                    dprintf(fd, "%s%02d-%02d %02d:%02d:%02d.%03d %s\n",
+                            prefix,
+                            tm.tm_mon + 1, // localtime_r uses months in 0 - 11 range
+                            tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
+                            (int)(ns % ns_per_sec / 1000000),
+                            it->second.c_str());
+                }
+            }
+            mLock.unlock();
+        }
+
+    private:
+        Mutex mLock;
+        static const size_t kLogSize = 256; // full history
+        static const size_t kLogPrint = 32; // default print history
+        std::deque<std::pair<int64_t, std::string>> mLog;
+    } mLocalLog;
+
 public:
     virtual     bool        hasFastMixer() const = 0;
     virtual     FastTrackUnderruns getFastTrackUnderruns(size_t fastIndex __unused) const
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index ba6e6e5..348cac4 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -461,7 +461,7 @@
 /*static*/ void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result)
 {
     result.append("    Name Active Client Type      Fmt Chn mask Session fCount S F SRate  "
-                  "L dB  R dB    Server Main buf  Aux Buf Flags UndFrmCnt\n");
+                  "L dB  R dB    Server Main buf  Aux buf Flags UndFrmCnt  Flushed\n");
 }
 
 void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size, bool active)
@@ -528,7 +528,7 @@
         break;
     }
     snprintf(&buffer[8], size-8, " %6s %6u %4u %08X %08X %7u %6zu %1c %1d %5u %5.2g %5.2g  "
-                                 "%08X %p %p 0x%03X %9u%c\n",
+                                 "%08X %08zX %08zX 0x%03X %9u%c %7u\n",
             active ? "yes" : "no",
             (mClient == 0) ? getpid_cached : mClient->pid(),
             mStreamType,
@@ -542,11 +542,12 @@
             20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))),
             20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
             mCblk->mServer,
-            mMainBuffer,
-            mAuxBuffer,
+            (size_t)mMainBuffer, // use %zX as %p appends 0x
+            (size_t)mAuxBuffer,  // use %zX as %p appends 0x
             mCblk->mFlags,
             mAudioTrackServerProxy->getUnderrunFrames(),
-            nowInUnderrun);
+            nowInUnderrun,
+            (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000); // 7 digits
 }
 
 uint32_t AudioFlinger::PlaybackThread::Track::sampleRate() const {