Make RenderNodeAnimator and WebView play nice

Change-Id: Ifaefcf510b2d377663fc86f60608d6ec9be8329a
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 2c29985..9902ff1 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -160,13 +160,13 @@
     newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
     mAnimators.erase(newEnd, mAnimators.end());
     mProperties.updateMatrix();
-    info.hasAnimations |= mAnimators.size();
+    info.out.hasAnimations |= mAnimators.size();
 }
 
 void RenderNode::prepareSubTree(TreeInfo& info, DisplayListData* subtree) {
     if (subtree) {
         TextureCache& cache = Caches::getInstance().textureCache;
-        info.hasFunctors |= subtree->functorCount;
+        info.out.hasFunctors |= subtree->functorCount;
         // TODO: Fix ownedBitmapResources to not require disabling prepareTextures
         // and thus falling out of async drawing path.
         if (subtree->ownedBitmapResources.size()) {
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index a383fbf..fc5994c 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -34,25 +34,33 @@
 struct TreeInfo {
     // The defaults here should be safe for everyone but DrawFrameTask to use as-is.
     TreeInfo()
-            : hasFunctors(false)
-            , prepareTextures(false)
-            , performStagingPush(true)
-            , frameTimeMs(0)
-            , evaluateAnimations(false)
-            , hasAnimations(false)
-            , animationHook(0)
+        : frameTimeMs(0)
+        , animationHook(NULL)
+        , prepareTextures(false)
+        , performStagingPush(true)
+        , evaluateAnimations(false)
     {}
 
-    bool hasFunctors;
+    nsecs_t frameTimeMs;
+    AnimationHook* animationHook;
     bool prepareTextures;
     bool performStagingPush;
-
-    // Animations
-    nsecs_t frameTimeMs;
     bool evaluateAnimations;
-    // This is only updated if evaluateAnimations is true
-    bool hasAnimations;
-    AnimationHook* animationHook;
+
+    struct Out {
+        Out()
+            : hasFunctors(false)
+            , hasAnimations(false)
+            , requiresUiRedraw(false)
+        {}
+        bool hasFunctors;
+        // This is only updated if evaluateAnimations is true
+        bool hasAnimations;
+        // This is set to true if there is an animation that RenderThread cannot
+        // animate itself, such as if hasFunctors is true
+        // This is only set if hasAnimations is true
+        bool requiresUiRedraw;
+    } out;
 
     // TODO: Damage calculations
 };
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index f199236..fc3548c 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -391,10 +391,20 @@
     mHaveNewSurface |= mGlobalContext->makeCurrent(mEglSurface);
 }
 
+void CanvasContext::prepareDraw(const Vector<DeferredLayerUpdater*>* layerUpdaters,
+        TreeInfo& info) {
+    LOG_ALWAYS_FATAL_IF(!mCanvas, "Cannot prepareDraw without a canvas!");
+    makeCurrent();
+
+    processLayerUpdates(layerUpdaters, info);
+    if (info.out.hasAnimations) {
+        // TODO: Uh... crap?
+    }
+    prepareTree(info);
+}
+
 void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters,
         TreeInfo& info) {
-    LOG_ALWAYS_FATAL_IF(!mCanvas, "Cannot process layer updates without a canvas!");
-    makeCurrent();
     for (size_t i = 0; i < layerUpdaters->size(); i++) {
         DeferredLayerUpdater* update = layerUpdaters->itemAt(i);
         bool success = update->apply(info);
@@ -406,13 +416,19 @@
 }
 
 void CanvasContext::prepareTree(TreeInfo& info) {
-    info.frameTimeMs = mRenderThread.timeLord().frameTimeMs();
+    mRenderThread.removeFrameCallback(this);
 
+    info.frameTimeMs = mRenderThread.timeLord().frameTimeMs();
     mRootRenderNode->prepareTree(info);
 
-    if (info.hasAnimations && !info.hasFunctors) {
-        // TODO: Functors
-        mRenderThread.postFrameCallback(this);
+    if (info.out.hasAnimations) {
+        if (info.out.hasFunctors) {
+            info.out.requiresUiRedraw = true;
+        } else if (!info.out.requiresUiRedraw) {
+            // If animationsNeedsRedraw is set don't bother posting for an RT anim
+            // as we will just end up fighting the UI thread.
+            mRenderThread.postFrameCallback(this);
+        }
     }
 }
 
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 8022c9e..a95e27a 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -53,8 +53,7 @@
     void pauseSurface(EGLNativeWindowType window);
     void setup(int width, int height);
     void makeCurrent();
-    void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, TreeInfo& info);
-    void prepareTree(TreeInfo& info);
+    void prepareDraw(const Vector<DeferredLayerUpdater*>* layerUpdaters, TreeInfo& info);
     void draw(Rect* dirty);
     void destroyCanvasAndSurface();
 
@@ -71,6 +70,9 @@
     Layer* createTextureLayer();
 
 private:
+    void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, TreeInfo& info);
+    void prepareTree(TreeInfo& info);
+
     void setSurface(EGLNativeWindowType window);
     void swapBuffers();
     void requireSurface();
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index a7b781a..3b8786c 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -33,7 +33,8 @@
 DrawFrameTask::DrawFrameTask()
         : mRenderThread(NULL)
         , mContext(NULL)
-        , mFrameTimeNanos(NULL) {
+        , mFrameTimeNanos(0)
+        , mSyncResult(kSync_OK) {
 }
 
 DrawFrameTask::~DrawFrameTask() {
@@ -63,15 +64,18 @@
     mDirty.set(left, top, right, bottom);
 }
 
-void DrawFrameTask::drawFrame(nsecs_t frameTimeNanos) {
+int DrawFrameTask::drawFrame(nsecs_t frameTimeNanos) {
     LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
 
+    mSyncResult = kSync_OK;
     mFrameTimeNanos = frameTimeNanos;
     postAndWait();
 
     // Reset the single-frame data
     mFrameTimeNanos = 0;
     mDirty.setEmpty();
+
+    return mSyncResult;
 }
 
 void DrawFrameTask::postAndWait() {
@@ -114,14 +118,16 @@
     Caches::getInstance().textureCache.resetMarkInUse();
     TreeInfo info;
     initTreeInfo(info);
-    mContext->processLayerUpdates(&mLayers, info);
-    mContext->prepareTree(info);
-    if (info.hasAnimations) {
+    mContext->prepareDraw(&mLayers, info);
+    if (info.out.hasAnimations) {
         // TODO: dirty calculations, for now just do a full-screen inval
         mDirty.setEmpty();
+        if (info.out.requiresUiRedraw) {
+            mSyncResult |= kSync_UIRedrawRequired;
+        }
     }
     // If prepareTextures is false, we ran out of texture cache space
-    return !info.hasFunctors && info.prepareTextures;
+    return !info.out.hasFunctors && info.prepareTextures;
 }
 
 void DrawFrameTask::unblockUiThread() {
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index ea00900..b9307e1 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -37,6 +37,11 @@
 class CanvasContext;
 class RenderThread;
 
+enum SyncResult {
+    kSync_OK = 0,
+    kSync_UIRedrawRequired = 1 << 1,
+};
+
 /*
  * This is a special Super Task. It is re-used multiple times by RenderProxy,
  * and contains state (such as layer updaters & new DisplayListDatas) that is
@@ -54,7 +59,7 @@
     void removeLayer(DeferredLayerUpdater* layer);
 
     void setDirty(int left, int top, int right, int bottom);
-    void drawFrame(nsecs_t frameTimeNanos);
+    int drawFrame(nsecs_t frameTimeNanos);
 
     virtual void run();
 
@@ -75,6 +80,8 @@
     Rect mDirty;
     nsecs_t mFrameTimeNanos;
 
+    int mSyncResult;
+
     /*********************************************
      *  Multi frame data
      *********************************************/
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 7b7c019..31bb61a 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -146,10 +146,10 @@
     post(task);
 }
 
-void RenderProxy::syncAndDrawFrame(nsecs_t frameTimeNanos,
+int RenderProxy::syncAndDrawFrame(nsecs_t frameTimeNanos,
         int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom) {
     mDrawFrameTask.setDirty(dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
-    mDrawFrameTask.drawFrame(frameTimeNanos);
+    return mDrawFrameTask.drawFrame(frameTimeNanos);
 }
 
 CREATE_BRIDGE1(destroyCanvasAndSurface, CanvasContext* context) {
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index bfa2b8d..984cc65 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -66,7 +66,7 @@
     ANDROID_API void updateSurface(const sp<ANativeWindow>& window);
     ANDROID_API void pauseSurface(const sp<ANativeWindow>& window);
     ANDROID_API void setup(int width, int height);
-    ANDROID_API void syncAndDrawFrame(nsecs_t frameTimeNanos,
+    ANDROID_API int syncAndDrawFrame(nsecs_t frameTimeNanos,
             int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
     ANDROID_API void destroyCanvasAndSurface();