Fix the RS frame timeout.
Previous a slow app would block from receiving new
commands until the timer expired.  This change will
expire the timer immediatly.

Change-Id: I42b949d21f98ee0f1d3156763cd723c3e9cabb67
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 6a30b17..bffe3c0 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -245,20 +245,32 @@
 
     rsc->mRunning = true;
     bool mDraw = true;
+    bool doWait = true;
+
+    uint64_t targetTime = rsc->getTime();
     while (!rsc->mExit) {
-        mDraw |= rsc->mIO.playCoreCommands(rsc, !mDraw);
+        uint64_t waitTime = 0;
+        uint64_t now = rsc->getTime();
+        if (now < targetTime) {
+            waitTime = targetTime - now;
+        } else {
+            doWait = false;
+        }
+
+        mDraw |= rsc->mIO.playCoreCommands(rsc, doWait, waitTime);
         mDraw &= (rsc->mRootScript.get() != NULL);
         mDraw &= rsc->mHasSurface;
 
-        uint32_t targetTime = 0;
         if (mDraw && rsc->mIsGraphicsContext) {
-            targetTime = rsc->runRootScript();
+            uint64_t delay = rsc->runRootScript() * 1000000;
+            targetTime = rsc->getTime() + delay;
+            doWait = delay != 0;
 
             if (rsc->props.mLogVisual) {
                 rsc->displayDebugStats();
             }
 
-            mDraw = targetTime && !rsc->mPaused;
+            mDraw = !rsc->mPaused;
             rsc->timerSet(RS_TIMER_CLEAR_SWAP);
             rsc->mHal.funcs.swap(rsc);
             rsc->timerFrame();
@@ -266,12 +278,6 @@
             rsc->timerPrint();
             rsc->timerReset();
         }
-        if (targetTime > 1) {
-            int32_t t = (targetTime - (int32_t)(rsc->mTimeMSLastScript + rsc->mTimeMSLastSwap)) * 1000;
-            if (t > 0) {
-                usleep(t);
-            }
-        }
     }
 
     LOGV("%p, RS Thread exiting", rsc);
diff --git a/libs/rs/rsLocklessFifo.cpp b/libs/rs/rsLocklessFifo.cpp
index 7023a1f..02a76ab 100644
--- a/libs/rs/rsLocklessFifo.cpp
+++ b/libs/rs/rsLocklessFifo.cpp
@@ -129,21 +129,23 @@
     //dumpState("flush 2");
 }
 
-void LocklessCommandFifo::wait() {
+bool LocklessCommandFifo::wait(uint64_t timeout) {
     while (isEmpty() && !mInShutdown) {
         mSignalToControl.set();
-        mSignalToWorker.wait();
+        return mSignalToWorker.wait(timeout);
     }
+    return true;
 }
 
-const void * LocklessCommandFifo::get(uint32_t *command, uint32_t *bytesData) {
+const void * LocklessCommandFifo::get(uint32_t *command, uint32_t *bytesData, uint64_t timeout) {
     while (1) {
         //dumpState("get");
-        wait();
-        if (mInShutdown) {
+        wait(timeout);
+
+        if (isEmpty() || mInShutdown) {
             *command = 0;
             *bytesData = 0;
-            return 0;
+            return NULL;
         }
 
         *command = reinterpret_cast<const uint16_t *>(mGet)[0];
diff --git a/libs/rs/rsLocklessFifo.h b/libs/rs/rsLocklessFifo.h
index eabdc3e..4962ef6 100644
--- a/libs/rs/rsLocklessFifo.h
+++ b/libs/rs/rsLocklessFifo.h
@@ -57,9 +57,9 @@
     void commitSync(uint32_t command, uint32_t bytes);
 
     void flush();
-    void wait();
+    bool wait(uint64_t timeout = 0);
 
-    const void * get(uint32_t *command, uint32_t *bytesData);
+    const void * get(uint32_t *command, uint32_t *bytesData, uint64_t timeout = 0);
     void next();
 
     void makeSpace(uint32_t bytes);
diff --git a/libs/rs/rsSignal.cpp b/libs/rs/rsSignal.cpp
index ccd20b9..413ac2b 100644
--- a/libs/rs/rsSignal.cpp
+++ b/libs/rs/rsSignal.cpp
@@ -68,26 +68,43 @@
     }
 }
 
-void Signal::wait() {
+bool Signal::wait(uint64_t timeout) {
     int status;
+    bool ret = false;
 
     status = pthread_mutex_lock(&mMutex);
     if (status) {
         LOGE("LocklessCommandFifo: error %i locking for condition.", status);
-        return;
+        return false;
     }
 
     if (!mSet) {
-        status = pthread_cond_wait(&mCondition, &mMutex);
-        if (status) {
-            LOGE("LocklessCommandFifo: error %i waiting on condition.", status);
+        if (!timeout) {
+            status = pthread_cond_wait(&mCondition, &mMutex);
+        } else {
+#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
+            status = pthread_cond_timeout_np(&mCondition, &mMutex, timeout / 1000000);
+#else
+            // This is safe it will just make things less reponsive
+            status = pthread_cond_wait(&mCondition, &mMutex);
+#endif
         }
     }
-    mSet = false;
+
+    if (!status) {
+        mSet = false;
+        ret = true;
+    } else {
+        if (status != ETIMEDOUT) {
+            LOGE("LocklessCommandFifo: error %i waiting for condition.", status);
+        }
+    }
 
     status = pthread_mutex_unlock(&mMutex);
     if (status) {
         LOGE("LocklessCommandFifo: error %i unlocking for condition.", status);
     }
+
+    return ret;
 }
 
diff --git a/libs/rs/rsSignal.h b/libs/rs/rsSignal.h
index 2e760f1..fc31883 100644
--- a/libs/rs/rsSignal.h
+++ b/libs/rs/rsSignal.h
@@ -31,7 +31,10 @@
     bool init();
 
     void set();
-    void wait();
+
+    // returns true if the signal occured
+    // false for timeout
+    bool wait(uint64_t timeout = 0);
 
 protected:
     bool mSet;
diff --git a/libs/rs/rsThreadIO.cpp b/libs/rs/rsThreadIO.cpp
index 1c8b89c..fe2c52e 100644
--- a/libs/rs/rsThreadIO.cpp
+++ b/libs/rs/rsThreadIO.cpp
@@ -113,8 +113,10 @@
 }
 
 
-bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand) {
+bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand, uint64_t timeToWait) {
     bool ret = false;
+    uint64_t startTime = con->getTime();
+
     while (!mToCore.isEmpty() || waitForCommand) {
         uint32_t cmdID = 0;
         uint32_t cmdSize = 0;
@@ -122,9 +124,17 @@
         if (con->props.mLogTimes) {
             con->timerSet(Context::RS_TIMER_IDLE);
         }
-        const void * data = mToCore.get(&cmdID, &cmdSize);
+
+        uint64_t delay = 0;
+        if (waitForCommand) {
+            delay = timeToWait - (con->getTime() - startTime);
+            if (delay > timeToWait) {
+                delay = 0;
+            }
+        }
+        const void * data = mToCore.get(&cmdID, &cmdSize, delay);
         if (!cmdSize) {
-            // exception occured, probably shutdown.
+            // exception or timeout occurred.
             return false;
         }
         if (con->props.mLogTimes) {
diff --git a/libs/rs/rsThreadIO.h b/libs/rs/rsThreadIO.h
index cad7318..9036118 100644
--- a/libs/rs/rsThreadIO.h
+++ b/libs/rs/rsThreadIO.h
@@ -37,7 +37,7 @@
 
     // Plays back commands from the client.
     // Returns true if any commands were processed.
-    bool playCoreCommands(Context *con, bool waitForCommand);
+    bool playCoreCommands(Context *con, bool waitForCommand, uint64_t timeToWait);
 
     //LocklessCommandFifo mToCore;