Merge "Report native allocation size of AnimatedImageDrawable" into pi-dev am: d848f75f99
am: 6413aebc02
Change-Id: Id1a101b08f8f9b9b53875bd9c784dea04a5b4110
diff --git a/core/jni/android/graphics/AnimatedImageDrawable.cpp b/core/jni/android/graphics/AnimatedImageDrawable.cpp
index d6496cd..7166c75 100644
--- a/core/jni/android/graphics/AnimatedImageDrawable.cpp
+++ b/core/jni/android/graphics/AnimatedImageDrawable.cpp
@@ -42,7 +42,6 @@
}
auto* imageDecoder = reinterpret_cast<ImageDecoder*>(nativeImageDecoder);
- auto info = imageDecoder->mCodec->getInfo();
const SkISize scaledSize = SkISize::Make(width, height);
SkIRect subset;
if (jsubset) {
@@ -51,6 +50,35 @@
subset = SkIRect::MakeWH(width, height);
}
+ auto info = imageDecoder->mCodec->getInfo();
+ bool hasRestoreFrame = false;
+ if (imageDecoder->mCodec->getEncodedFormat() == SkEncodedImageFormat::kWEBP) {
+ if (width < info.width() && height < info.height()) {
+ // WebP will scale its SkBitmap to the scaled size.
+ // FIXME: b/73529447 GIF should do the same.
+ info = info.makeWH(width, height);
+ }
+ } else {
+ const int frameCount = imageDecoder->mCodec->codec()->getFrameCount();
+ for (int i = 0; i < frameCount; ++i) {
+ SkCodec::FrameInfo frameInfo;
+ if (!imageDecoder->mCodec->codec()->getFrameInfo(i, &frameInfo)) {
+ doThrowIOE(env, "Failed to read frame info!");
+ return 0;
+ }
+ if (frameInfo.fDisposalMethod == SkCodecAnimation::DisposalMethod::kRestorePrevious) {
+ hasRestoreFrame = true;
+ break;
+ }
+ }
+ }
+
+ size_t bytesUsed = info.computeMinByteSize();
+ // SkAnimatedImage has one SkBitmap for decoding, plus an extra one if there is a
+ // kRestorePrevious frame. AnimatedImageDrawable has two SkPictures storing the current
+ // frame and the next frame. (The former assumes that the image is animated, and the
+ // latter assumes that it is drawn to a hardware canvas.)
+ bytesUsed *= hasRestoreFrame ? 4 : 3;
sk_sp<SkPicture> picture;
if (jpostProcess) {
SkRect bounds = SkRect::MakeWH(subset.width(), subset.height());
@@ -63,6 +91,7 @@
return 0;
}
picture = recorder.finishRecordingAsPicture();
+ bytesUsed += picture->approximateBytesUsed();
}
@@ -74,7 +103,10 @@
return 0;
}
- sk_sp<AnimatedImageDrawable> drawable(new AnimatedImageDrawable(animatedImg));
+ bytesUsed += sizeof(animatedImg.get());
+
+ sk_sp<AnimatedImageDrawable> drawable(new AnimatedImageDrawable(std::move(animatedImg),
+ bytesUsed));
return reinterpret_cast<jlong>(drawable.release());
}
@@ -202,10 +234,9 @@
}
}
-static long AnimatedImageDrawable_nNativeByteSize(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
+static jlong AnimatedImageDrawable_nNativeByteSize(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
- // FIXME: Report the size of the internal SkBitmap etc.
- return sizeof(drawable);
+ return drawable->byteSize();
}
static void AnimatedImageDrawable_nMarkInvisible(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
diff --git a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
index c0f4920..a47ecf5 100644
--- a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
@@ -292,8 +292,7 @@
mState = new State(nCreate(nativeImageDecoder, decoder, width, height, cropRect),
inputStream, afd);
- // FIXME: Use the right size for the native allocation.
- long nativeSize = 200;
+ final long nativeSize = nNativeByteSize(mState.mNativePtr);
NativeAllocationRegistry registry = new NativeAllocationRegistry(
AnimatedImageDrawable.class.getClassLoader(), nGetNativeFinalizer(), nativeSize);
registry.registerNativeAllocation(mState, mState.mNativePtr);
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.cpp b/libs/hwui/hwui/AnimatedImageDrawable.cpp
index 28d0bc4..c529f87 100644
--- a/libs/hwui/hwui/AnimatedImageDrawable.cpp
+++ b/libs/hwui/hwui/AnimatedImageDrawable.cpp
@@ -26,8 +26,8 @@
namespace android {
-AnimatedImageDrawable::AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage)
- : mSkAnimatedImage(std::move(animatedImage)) {
+AnimatedImageDrawable::AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed)
+ : mSkAnimatedImage(std::move(animatedImage)), mBytesUsed(bytesUsed) {
mTimeToShowNextSnapshot = mSkAnimatedImage->currentFrameDuration();
}
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.h b/libs/hwui/hwui/AnimatedImageDrawable.h
index f4e2ba7..a92b62d 100644
--- a/libs/hwui/hwui/AnimatedImageDrawable.h
+++ b/libs/hwui/hwui/AnimatedImageDrawable.h
@@ -45,7 +45,9 @@
*/
class ANDROID_API AnimatedImageDrawable : public SkDrawable {
public:
- AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage);
+ // bytesUsed includes the approximate sizes of the SkAnimatedImage and the SkPictures in the
+ // Snapshots.
+ AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed);
/**
* This updates the internal time and returns true if the animation needs
@@ -100,11 +102,17 @@
Snapshot decodeNextFrame();
Snapshot reset();
+ size_t byteSize() const {
+ return sizeof(this) + mBytesUsed;
+ }
+
protected:
virtual void onDraw(SkCanvas* canvas) override;
private:
sk_sp<SkAnimatedImage> mSkAnimatedImage;
+ const size_t mBytesUsed;
+
bool mRunning = false;
bool mStarting = false;