Add audio watchdog thread

Change-Id: I4ed62087bd6554179abb8258d2da606050e762c0
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index be59ca0..586a916 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2300,6 +2300,19 @@
         }
 #endif
 
+#ifdef AUDIO_WATCHDOG
+        // create and start the watchdog
+        mAudioWatchdog = new AudioWatchdog();
+        mAudioWatchdog->setDump(&mAudioWatchdogDump);
+        mAudioWatchdog->run("AudioWatchdog", PRIORITY_URGENT_AUDIO);
+        tid = mAudioWatchdog->getTid();
+        err = requestPriority(getpid_cached, tid, 1);
+        if (err != 0) {
+            ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; error %d",
+                    1, getpid_cached, tid, err);
+        }
+#endif
+
     } else {
         mFastMixer = NULL;
     }
@@ -2349,6 +2362,11 @@
         }
         delete mSoaker;
 #endif
+        if (mAudioWatchdog != 0) {
+            mAudioWatchdog->requestExit();
+            mAudioWatchdog->requestExitAndWait();
+            mAudioWatchdog.clear();
+        }
     }
     delete mAudioMixer;
 }
@@ -2670,6 +2688,9 @@
                 if (old == -1) {
                     __futex_syscall3(&mFastMixerFutex, FUTEX_WAKE_PRIVATE, 1);
                 }
+                if (mAudioWatchdog != 0) {
+                    mAudioWatchdog->resume();
+                }
             }
             state->mCommand = FastMixerState::MIX_WRITE;
             sq->end();
@@ -2746,6 +2767,9 @@
             if (kUseFastMixer == FastMixer_Dynamic) {
                 mNormalSink = mOutputSink;
             }
+            if (mAudioWatchdog != 0) {
+                mAudioWatchdog->pause();
+            }
         } else {
             sq->end(false /*didModify*/);
         }
@@ -3234,6 +3258,7 @@
     }
 
     // Push the new FastMixer state if necessary
+    bool pauseAudioWatchdog = false;
     if (didModify) {
         state->mFastTracksGen++;
         // if the fast mixer was active, but now there are no fast tracks, then put it in cold idle
@@ -3249,6 +3274,7 @@
             // If we go into cold idle, need to wait for acknowledgement
             // so that fast mixer stops doing I/O.
             block = FastMixerStateQueue::BLOCK_UNTIL_ACKED;
+            pauseAudioWatchdog = true;
         }
         sq->end();
     }
@@ -3256,6 +3282,9 @@
         sq->end(didModify);
         sq->push(block);
     }
+    if (pauseAudioWatchdog && mAudioWatchdog != 0) {
+        mAudioWatchdog->pause();
+    }
 
     // Now perform the deferred reset on fast tracks that have stopped
     while (resetMask != 0) {
@@ -3576,6 +3605,12 @@
         }
     }
 
+    if (mAudioWatchdog != 0) {
+        // Make a non-atomic copy of audio watchdog dump so it won't change underneath us
+        AudioWatchdogDump wdCopy = mAudioWatchdogDump;
+        wdCopy.dump(fd);
+    }
+
     return NO_ERROR;
 }