Initial implmentation of AnimatedImageDrawables on the RenderThread.

The current implementation schedules the next frame of the images
to be decoded after the current frame completes but potentially
schedules tasks that will result in a no-op execution if a new
frame is not yet needed.

Test: HwAccelerationTest
Change-Id: I0510cb5a1b801abd651327e924deb586af0306d6
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index cb10901..cf0b6a4 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -31,6 +31,9 @@
     for (auto& functor : mChildFunctors) {
         functor.syncFunctor();
     }
+    for (auto& animatedImage : mAnimatedImages) {
+        animatedImage->syncProperties();
+    }
     for (auto& vectorDrawable : mVectorDrawables) {
         vectorDrawable->syncProperties();
     }
@@ -89,6 +92,18 @@
     }
 
     bool isDirty = false;
+    for (auto& animatedImage : mAnimatedImages) {
+        // If any animated image in the display list needs updated, then damage the node.
+        if (animatedImage->isDirty()) {
+            isDirty = true;
+        }
+        if (animatedImage->isRunning()) {
+            static_cast<SkiaPipeline*>(info.canvasContext.getRenderPipeline())
+                    ->scheduleDeferredUpdate(animatedImage);
+            info.out.hasAnimations = true;
+        }
+    }
+
     for (auto& vectorDrawable : mVectorDrawables) {
         // If any vector drawable in the display list needs update, damage the node.
         if (vectorDrawable->isDirty()) {
@@ -109,6 +124,7 @@
 
     mMutableImages.clear();
     mVectorDrawables.clear();
+    mAnimatedImages.clear();
     mChildFunctors.clear();
     mChildNodes.clear();
 
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index 6883d33..818ec11 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include "DisplayList.h"
+#include "hwui/AnimatedImageDrawable.h"
 #include "GLFunctorDrawable.h"
 #include "RenderNodeDrawable.h"
 
@@ -144,6 +145,7 @@
     std::deque<GLFunctorDrawable> mChildFunctors;
     std::vector<SkImage*> mMutableImages;
     std::vector<VectorDrawableRoot*> mVectorDrawables;
+    std::vector<AnimatedImageDrawable*> mAnimatedImages;
     SkLiteDL mDisplayList;
 
     // mProjectionReceiver points to a child node (stored in mChildNodes) that is as a projection
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 9db39d9..534782a 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -40,6 +40,7 @@
 Vector3 SkiaPipeline::mLightCenter = {FLT_MIN, FLT_MIN, FLT_MIN};
 
 SkiaPipeline::SkiaPipeline(RenderThread& thread) : mRenderThread(thread) {
+    mAnimatedImageDrawables.reserve(30);
     mVectorDrawables.reserve(30);
 }
 
@@ -326,6 +327,15 @@
 
     ATRACE_NAME("flush commands");
     surface->getCanvas()->flush();
+
+    // TODO move to another method
+    if (!mAnimatedImageDrawables.empty()) {
+        ATRACE_NAME("Update AnimatedImageDrawables");
+        for (auto animatedImage : mAnimatedImageDrawables) {
+            animatedImage->scheduleUpdate(getTaskManager());
+        }
+        mAnimatedImageDrawables.clear();
+    }
 }
 
 namespace {
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h
index 2709227..cc75e9c 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.h
@@ -18,6 +18,7 @@
 
 #include <SkSurface.h>
 #include "FrameBuilder.h"
+#include "hwui/AnimatedImageDrawable.h"
 #include "renderthread/CanvasContext.h"
 #include "renderthread/IRenderPipeline.h"
 
@@ -54,6 +55,12 @@
 
     std::vector<VectorDrawableRoot*>* getVectorDrawables() { return &mVectorDrawables; }
 
+    void scheduleDeferredUpdate(AnimatedImageDrawable* imageDrawable) {
+        mAnimatedImageDrawables.push_back(imageDrawable);
+    }
+
+    std::vector<AnimatedImageDrawable*>* getAnimatingImages() { return &mAnimatedImageDrawables; }
+
     static void destroyLayer(RenderNode* node);
 
     static void prepareToDraw(const renderthread::RenderThread& thread, Bitmap* bitmap);
@@ -137,6 +144,11 @@
      */
     std::vector<VectorDrawableRoot*> mVectorDrawables;
 
+    /**
+     * populated by prepareTree with images with active animations
+     */
+    std::vector<AnimatedImageDrawable*> mAnimatedImageDrawables;
+
     // Block of properties used only for debugging to record a SkPicture and save it in a file.
     /**
      * mCapturedFile is used to enforce we don't capture more than once for a given name (cause
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 035cea3..eabe2e8 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -246,6 +246,12 @@
     }
 }
 
+double SkiaRecordingCanvas::drawAnimatedImage(AnimatedImageDrawable* animatedImage) {
+    drawDrawable(animatedImage);
+    mDisplayList->mAnimatedImages.push_back(animatedImage);
+    return 0;
+}
+
 };  // namespace skiapipeline
 };  // namespace uirenderer
 };  // namespace android
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
index d35bbab..0e5dbdb 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
@@ -53,6 +53,7 @@
     virtual void drawNinePatch(Bitmap& hwuiBitmap, const android::Res_png_9patch& chunk,
                                float dstLeft, float dstTop, float dstRight, float dstBottom,
                                const SkPaint* paint) override;
+    virtual double drawAnimatedImage(AnimatedImageDrawable* animatedImage) override;
 
     virtual void drawRoundRect(uirenderer::CanvasPropertyPrimitive* left,
                                uirenderer::CanvasPropertyPrimitive* top,