Throttle low priority RS threads by sleeping once per frame to avoid starving other apps.
diff --git a/rsContext.cpp b/rsContext.cpp
index 52074ca..3652f0a 100644
--- a/rsContext.cpp
+++ b/rsContext.cpp
@@ -113,14 +113,14 @@
 }
 
 
-bool Context::runScript(Script *s, uint32_t launchID)
+uint32_t Context::runScript(Script *s, uint32_t launchID)
 {
     ObjectBaseRef<ProgramFragment> frag(mFragment);
     ObjectBaseRef<ProgramVertex> vtx(mVertex);
     ObjectBaseRef<ProgramFragmentStore> store(mFragmentStore);
     ObjectBaseRef<ProgramRaster> raster(mRaster);
 
-    bool ret = s->run(this, launchID);
+    uint32_t ret = s->run(this, launchID);
 
     mFragment.set(frag);
     mVertex.set(vtx);
@@ -130,11 +130,9 @@
 }
 
 
-bool Context::runRootScript()
+uint32_t Context::runRootScript()
 {
-    if (props.mLogTimes) {
-        timerSet(RS_TIMER_CLEAR_SWAP);
-    }
+    timerSet(RS_TIMER_CLEAR_SWAP);
     rsAssert(mRootScript->mEnviroment.mIsRoot);
 
     eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_WIDTH, &mEGL.mWidth);
@@ -154,11 +152,9 @@
         glClear(GL_COLOR_BUFFER_BIT);
     }
 
-    if (this->props.mLogTimes) {
-        timerSet(RS_TIMER_SCRIPT);
-    }
+    timerSet(RS_TIMER_SCRIPT);
     mStateFragmentStore.mLast.clear();
-    bool ret = runScript(mRootScript.get(), 0);
+    uint32_t ret = runScript(mRootScript.get(), 0);
 
     GLenum err = glGetError();
     if (err != GL_NO_ERROR) {
@@ -212,13 +208,19 @@
         total += mTimers[ct];
     }
     uint64_t frame = mTimeFrame - mTimeLastFrame;
+    mTimeMSLastFrame = frame / 1000000;
+    mTimeMSLastScript = mTimers[RS_TIMER_SCRIPT] / 1000000;
+    mTimeMSLastSwap = mTimers[RS_TIMER_CLEAR_SWAP] / 1000000;
 
-    LOGV("RS: Frame (%lli),   Script %2.1f (%lli),  Clear & Swap %2.1f (%lli),  Idle %2.1f (%lli),  Internal %2.1f (%lli)",
-         frame / 1000000,
-         100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimers[RS_TIMER_SCRIPT] / 1000000,
-         100.0 * mTimers[RS_TIMER_CLEAR_SWAP] / total, mTimers[RS_TIMER_CLEAR_SWAP] / 1000000,
-         100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000,
-         100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000);
+
+    if (props.mLogTimes) {
+        LOGV("RS: Frame (%i),   Script %2.1f (%i),  Clear & Swap %2.1f (%i),  Idle %2.1f (%lli),  Internal %2.1f (%lli)",
+             mTimeMSLastFrame,
+             100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimeMSLastScript,
+             100.0 * mTimers[RS_TIMER_CLEAR_SWAP] / total, mTimeMSLastSwap,
+             100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000,
+             100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000);
+    }
 }
 
 void Context::setupCheck()
@@ -242,6 +244,7 @@
      rsc->mNativeThreadId = gettid();
 
      setpriority(PRIO_PROCESS, rsc->mNativeThreadId, ANDROID_PRIORITY_DISPLAY);
+     rsc->mThreadPriority = ANDROID_PRIORITY_DISPLAY;
 
      rsc->props.mLogTimes = getProp("debug.rs.profile");
      rsc->props.mLogScripts = getProp("debug.rs.script");
@@ -279,22 +282,26 @@
          mDraw &= (rsc->mRootScript.get() != NULL);
          mDraw &= (rsc->mWndSurface != NULL);
 
+         uint32_t targetTime = 0;
          if (mDraw) {
-             mDraw = rsc->runRootScript() && !rsc->mPaused;
-             if (rsc->props.mLogTimes) {
-                 rsc->timerSet(RS_TIMER_CLEAR_SWAP);
-             }
+             targetTime = rsc->runRootScript();
+             mDraw = targetTime && !rsc->mPaused;
+             rsc->timerSet(RS_TIMER_CLEAR_SWAP);
              eglSwapBuffers(rsc->mEGL.mDisplay, rsc->mEGL.mSurface);
-             if (rsc->props.mLogTimes) {
-                 rsc->timerFrame();
-                 rsc->timerSet(RS_TIMER_INTERNAL);
-                 rsc->timerPrint();
-                 rsc->timerReset();
-             }
+             rsc->timerFrame();
+             rsc->timerSet(RS_TIMER_INTERNAL);
+             rsc->timerPrint();
+             rsc->timerReset();
          }
          if (rsc->mObjDestroy.mNeedToEmpty) {
              rsc->objDestroyOOBRun();
          }
+         if (rsc->mThreadPriority > 0 && targetTime) {
+             int32_t t = (targetTime - (int32_t)(rsc->mTimeMSLastScript + rsc->mTimeMSLastSwap)) * 1000;
+             if (t > 0) {
+                 usleep(t);
+             }
+         }
      }
 
      LOGV("RS Thread exiting");
@@ -330,6 +337,7 @@
     // the wallpapers can become completly unresponsive at times.
     // This is probably not what we want for something the user is actively
     // looking at.
+    mThreadPriority = p;
 #if 0
     SchedPolicy pol = SP_FOREGROUND;
     if (p > 0) {