Merge "audioflinger: add watchdog on main mutex" into nyc-mr1-dev
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 8b831f0..05dacac 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -3,7 +3,8 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
-    ServiceUtilities.cpp
+    ServiceUtilities.cpp \
+    LockWatch.cpp
 
 # FIXME Move this library to frameworks/native
 LOCAL_MODULE := libserviceutility
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 79f4a66..c32eadd 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -246,7 +246,9 @@
     }
 
     mPatchPanel = new PatchPanel(this);
-
+    // FIXME: bug 30737845: trigger audioserver restart if main audioflinger lock
+    // is held continuously for more than 3 seconds
+    mLockWatch = new LockWatch(mLock, String8("AudioFlinger"));
     mMode = AUDIO_MODE_NORMAL;
 }
 
@@ -279,6 +281,7 @@
             }
         }
     }
+    mLockWatch->requestExitAndWait();
 }
 
 static const char * const audio_interfaces[] = {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index c56dcc1..e334d80 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -58,6 +58,7 @@
 #include "SpdifStreamOut.h"
 #include "AudioHwDevice.h"
 #include "LinearMap.h"
+#include "LockWatch.h"
 
 #include <powermanager/IPowerManager.h>
 
@@ -630,6 +631,7 @@
     };
 
     mutable     Mutex                               mLock;
+                sp<LockWatch>                       mLockWatch;
                 // protects mClients and mNotificationClients.
                 // must be locked after mLock and ThreadBase::mLock if both must be locked
                 // avoids acquiring AudioFlinger::mLock from inside thread loop.
diff --git a/services/audioflinger/LockWatch.cpp b/services/audioflinger/LockWatch.cpp
new file mode 100644
index 0000000..21eed6e
--- /dev/null
+++ b/services/audioflinger/LockWatch.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LockWatch"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include "LockWatch.h"
+
+namespace android {
+
+void LockWatch::onFirstRef()
+{
+    run("lock watch", ANDROID_PRIORITY_URGENT_AUDIO);
+}
+
+bool LockWatch::threadLoop()
+{
+    while (!exitPending()) {
+        // we neglect previous lock time effect on period
+        usleep(mPeriodMs * 1000);
+        if (mLock.timedLock(milliseconds(mTimeOutMs)) != NO_ERROR) {
+            LOG_ALWAYS_FATAL("LockWatch timeout for: %s", mTag.string());
+        }
+        mLock.unlock();
+    }
+    return false;
+}
+
+}   // namespace android
+
diff --git a/services/audioflinger/LockWatch.h b/services/audioflinger/LockWatch.h
new file mode 100644
index 0000000..2d30217
--- /dev/null
+++ b/services/audioflinger/LockWatch.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef LOCK_WATCH_H
+#define LOCK_WATCH_H
+
+#include <utils/String8.h>
+#include <utils/Thread.h>
+
+namespace android {
+
+// periodically checks if a mutex can be acquired and kill process otherwise
+class LockWatch : public Thread {
+
+public:
+    static const uint32_t DEFAULT_PERIOD_MS = 10000; // 10 seconds default check period
+    static const uint32_t DEFAULT_TIMEOUT_MS = 3000; // 3 seconds default lock timeout
+
+    LockWatch(Mutex& lock, const String8& tag = String8(""),
+            uint32_t periodMs = DEFAULT_PERIOD_MS, uint32_t timeoutMs = DEFAULT_TIMEOUT_MS)
+        : Thread(false /*canCallJava*/),
+          mLock(lock), mTag(tag), mPeriodMs(periodMs), mTimeOutMs(timeoutMs) {}
+
+    virtual         ~LockWatch() { }
+
+    // RefBase
+    virtual void    onFirstRef();
+
+private:
+    // Thread
+    virtual bool    threadLoop();
+
+    Mutex&          mLock;          // monitored mutex
+    String8         mTag;           // tag
+    uint32_t        mPeriodMs;      // check period in milliseconds
+    uint32_t        mTimeOutMs;     // mutex lock timeout in milliseconds
+};
+
+}   // namespace android
+
+#endif  // LOCK_WATCH_H