Native-side proxy

 Remove RemoteGLRenderer
 Remove reflection-based control

Change-Id: If17c2bbb61c7141986d88c4763def77ed1074985
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index bccd6e6..e4ec164 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -18,6 +18,8 @@
 
 #include "RenderThread.h"
 
+#include "CanvasContext.h"
+#include "RenderProxy.h"
 #include <utils/Log.h>
 
 namespace android {
@@ -27,8 +29,82 @@
 namespace uirenderer {
 namespace renderthread {
 
+TaskQueue::TaskQueue() : mHead(0), mTail(0) {}
+
+RenderTask* TaskQueue::next() {
+    RenderTask* ret = mHead;
+    if (ret) {
+        mHead = ret->mNext;
+        if (!mHead) {
+            mTail = 0;
+        }
+        ret->mNext = 0;
+    }
+    return ret;
+}
+
+RenderTask* TaskQueue::peek() {
+    return mHead;
+}
+
+void TaskQueue::queue(RenderTask* task) {
+    // Since the RenderTask itself forms the linked list it is not allowed
+    // to have the same task queued twice
+    LOG_ALWAYS_FATAL_IF(task->mNext || mTail == task, "Task is already in the queue!");
+    if (mTail) {
+        // Fast path if we can just append
+        if (mTail->mRunAt <= task->mRunAt) {
+            mTail->mNext = task;
+            mTail = task;
+        } else {
+            // Need to find the proper insertion point
+            RenderTask* previous = 0;
+            RenderTask* next = mHead;
+            while (next && next->mRunAt <= task->mRunAt) {
+                previous = next;
+                next = next->mNext;
+            }
+            if (!previous) {
+                task->mNext = mHead;
+                mHead = task;
+            } else {
+                previous->mNext = task;
+                if (next) {
+                    task->mNext = next;
+                } else {
+                    mTail = task;
+                }
+            }
+        }
+    } else {
+        mTail = mHead = task;
+    }
+}
+
+void TaskQueue::remove(RenderTask* task) {
+    // TaskQueue is strict here to enforce that users are keeping track of
+    // their RenderTasks due to how their memory is managed
+    LOG_ALWAYS_FATAL_IF(!task->mNext && mTail != task,
+            "Cannot remove a task that isn't in the queue!");
+
+    // If task is the head we can just call next() to pop it off
+    // Otherwise we need to scan through to find the task before it
+    if (peek() == task) {
+        next();
+    } else {
+        RenderTask* previous = mHead;
+        while (previous->mNext != task) {
+            previous = previous->mNext;
+        }
+        previous->mNext = task->mNext;
+        if (mTail == task) {
+            mTail = previous;
+        }
+    }
+}
+
 RenderThread::RenderThread() : Thread(true), Singleton<RenderThread>()
-        , mQueueHead(0), mQueueTail(0) {
+        , mNextWakeup(LLONG_MAX) {
     mLooper = new Looper(false);
     run("RenderThread");
 }
@@ -37,16 +113,25 @@
 }
 
 bool RenderThread::threadLoop() {
+    int timeoutMillis = -1;
     for (;;) {
-        int result = mLooper->pollAll(-1);
-        if (result == Looper::POLL_ERROR) {
-            // TODO Something?
-            break;
-        }
+        int result = mLooper->pollAll(timeoutMillis);
+        LOG_ALWAYS_FATAL_IF(result == Looper::POLL_ERROR,
+                "RenderThread Looper POLL_ERROR!");
+
+        nsecs_t nextWakeup;
         // Process our queue, if we have anything
-        while (RenderTask* task = nextTask()) {
+        while (RenderTask* task = nextTask(&nextWakeup)) {
             task->run();
-            delete task;
+            // task may have deleted itself, do not reference it again
+        }
+        if (nextWakeup == LLONG_MAX) {
+            timeoutMillis = -1;
+        } else {
+            timeoutMillis = nextWakeup - systemTime(SYSTEM_TIME_MONOTONIC);
+            if (timeoutMillis < 0) {
+                timeoutMillis = 0;
+            }
         }
     }
 
@@ -55,30 +140,40 @@
 
 void RenderThread::queue(RenderTask* task) {
     AutoMutex _lock(mLock);
-    if (mQueueTail) {
-        mQueueTail->mNext = task;
-    } else {
-        mQueueHead = task;
-    }
-    mQueueTail = task;
-    if (mQueueHead == task) {
-        // Only wake if this is the first task
+    mQueue.queue(task);
+    if (mNextWakeup && task->mRunAt < mNextWakeup) {
+        mNextWakeup = 0;
         mLooper->wake();
     }
 }
 
-RenderTask* RenderThread::nextTask() {
+void RenderThread::queueDelayed(RenderTask* task, int delayMs) {
+    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+    task->mRunAt = now + delayMs;
+    queue(task);
+}
+
+void RenderThread::remove(RenderTask* task) {
     AutoMutex _lock(mLock);
-    RenderTask* ret = mQueueHead;
-    if (ret) {
-        if (mQueueTail == mQueueHead) {
-            mQueueTail = mQueueHead = 0;
-        } else {
-            mQueueHead = ret->mNext;
+    mQueue.remove(task);
+}
+
+RenderTask* RenderThread::nextTask(nsecs_t* nextWakeup) {
+    AutoMutex _lock(mLock);
+    RenderTask* next = mQueue.peek();
+    if (!next) {
+        mNextWakeup = LLONG_MAX;
+    } else {
+        // Most tasks won't be delayed, so avoid unnecessary systemTime() calls
+        if (next->mRunAt <= 0 || next->mRunAt <= systemTime(SYSTEM_TIME_MONOTONIC)) {
+            next = mQueue.next();
         }
-        ret->mNext = 0;
+        mNextWakeup = next->mRunAt;
     }
-    return ret;
+    if (nextWakeup) {
+        *nextWakeup = mNextWakeup;
+    }
+    return next;
 }
 
 } /* namespace renderthread */