1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <cutils/compiler.h> 20 #include <utils/Macros.h> 21 #include <utils/RefBase.h> 22 #include <utils/Timers.h> 23 24 #include <SkAnimatedImage.h> 25 #include <SkCanvas.h> 26 #include <SkColorFilter.h> 27 #include <SkDrawable.h> 28 #include <SkPicture.h> 29 30 #include <future> 31 #include <mutex> 32 33 namespace android { 34 35 class OnAnimationEndListener { 36 public: ~OnAnimationEndListener()37 virtual ~OnAnimationEndListener() {} 38 39 virtual void onAnimationEnd() = 0; 40 }; 41 42 /** 43 * Native component of android.graphics.drawable.AnimatedImageDrawables.java. 44 * This class can be drawn into Canvas.h and maintains the state needed to drive 45 * the animation from the RenderThread. 46 */ 47 class AnimatedImageDrawable : public SkDrawable { 48 public: 49 // bytesUsed includes the approximate sizes of the SkAnimatedImage and the SkPictures in the 50 // Snapshots. 51 AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed); 52 53 /** 54 * This updates the internal time and returns true if the image needs 55 * to be redrawn this frame. 56 * 57 * This is called on RenderThread, while the UI thread is locked. 58 * 59 * @param outDelay Nanoseconds in the future when the following frame 60 * will need to be drawn. 0 if not running. 61 */ 62 bool isDirty(nsecs_t* outDelay); 63 getStagingAlpha()64 int getStagingAlpha() const { return mStagingProperties.mAlpha; } setStagingAlpha(int alpha)65 void setStagingAlpha(int alpha) { mStagingProperties.mAlpha = alpha; } setStagingColorFilter(sk_sp<SkColorFilter> filter)66 void setStagingColorFilter(sk_sp<SkColorFilter> filter) { 67 mStagingProperties.mColorFilter = filter; 68 } setStagingMirrored(bool mirrored)69 void setStagingMirrored(bool mirrored) { mStagingProperties.mMirrored = mirrored; } setStagingBounds(const SkRect & bounds)70 void setStagingBounds(const SkRect& bounds) { mStagingProperties.mBounds = bounds; } 71 void syncProperties(); 72 73 SkRect onGetBounds() override; 74 75 // Draw to software canvas, and return time to next draw. 76 // 0 means the animation is not running. 77 // -1 means the animation advanced to the final frame. 78 int drawStaging(SkCanvas* canvas); 79 80 // Returns true if the animation was started; false otherwise (e.g. it was 81 // already running) 82 bool start(); 83 // Returns true if the animation was stopped; false otherwise (e.g. it was 84 // already stopped) 85 bool stop(); 86 bool isRunning(); getRepetitionCount()87 int getRepetitionCount() const { return mSkAnimatedImage->getRepetitionCount(); } setRepetitionCount(int count)88 void setRepetitionCount(int count) { mSkAnimatedImage->setRepetitionCount(count); } 89 setOnAnimationEndListener(std::unique_ptr<OnAnimationEndListener> listener)90 void setOnAnimationEndListener(std::unique_ptr<OnAnimationEndListener> listener) { 91 mEndListener = std::move(listener); 92 } 93 94 struct Snapshot { 95 sk_sp<SkPicture> mPic; 96 int mDurationMS; 97 98 Snapshot() = default; 99 100 Snapshot(Snapshot&&) = default; 101 Snapshot& operator=(Snapshot&&) = default; 102 103 PREVENT_COPY_AND_ASSIGN(Snapshot); 104 }; 105 106 // These are only called on AnimatedImageThread. 107 Snapshot decodeNextFrame(); 108 Snapshot reset(); 109 byteSize()110 size_t byteSize() const { return sizeof(*this) + mBytesUsed; } 111 112 protected: 113 void onDraw(SkCanvas* canvas) override; 114 115 private: 116 sk_sp<SkAnimatedImage> mSkAnimatedImage; 117 const size_t mBytesUsed; 118 119 bool mRunning = false; 120 bool mStarting = false; 121 122 // A snapshot of the current frame to draw. 123 Snapshot mSnapshot; 124 125 std::future<Snapshot> mNextSnapshot; 126 127 bool nextSnapshotReady() const; 128 129 // When to switch from mSnapshot to mNextSnapshot. 130 nsecs_t mTimeToShowNextSnapshot = 0; 131 132 // The current time for the drawable itself. 133 nsecs_t mCurrentTime = 0; 134 135 // The wall clock of the last time we called isDirty. 136 nsecs_t mLastWallTime = 0; 137 138 // Locked when assigning snapshots and times. Operations while this is held 139 // should be short. 140 std::mutex mSwapLock; 141 142 // Locked when mSkAnimatedImage is being updated or drawn. 143 std::mutex mImageLock; 144 145 struct Properties { 146 int mAlpha = SK_AlphaOPAQUE; 147 sk_sp<SkColorFilter> mColorFilter; 148 bool mMirrored = false; 149 SkRect mBounds; 150 151 Properties() = default; 152 Properties(Properties&) = default; 153 Properties& operator=(Properties&) = default; 154 }; 155 156 Properties mStagingProperties; 157 Properties mProperties; 158 159 std::unique_ptr<OnAnimationEndListener> mEndListener; 160 }; 161 162 } // namespace android 163