Skip to content
Snippets Groups Projects
Commit bc8c5eb3 authored by Ido Ben-Hur's avatar Ido Ben-Hur Committed by Mohammad Hasan Keramat J
Browse files

Messaging: FrameSequence -> ImageDecoder

fixes playing / displaying gifs
replaces old deprecated FrameSequence & FrameSequenceDrawable libs

Change-Id: I58a99dbe92896216462d788069095fe2f9a909f7
parent e70dcfac
No related branches found
No related tags found
No related merge requests found
......@@ -17,30 +17,51 @@ package com.android.messaging.datamodel.media;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.ImageDecoder;
import android.graphics.drawable.AnimatedImageDrawable;
import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
import android.support.rastermill.FrameSequence;
import android.support.rastermill.FrameSequenceDrawable;
import com.android.messaging.util.Assert;
import com.android.messaging.util.LogUtil;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class GifImageResource extends ImageResource {
private FrameSequence mFrameSequence;
private ImageDecoder.Source mImageDecoderSource;
public GifImageResource(String key, FrameSequence frameSequence) {
public GifImageResource(String key, ImageDecoder.Source imageDecoderSource) {
// GIF does not support exif tags
super(key, ExifInterface.ORIENTATION_NORMAL);
mFrameSequence = frameSequence;
mImageDecoderSource = imageDecoderSource;
}
public static GifImageResource createGifImageResource(String key, InputStream inputStream) {
final FrameSequence frameSequence;
// create a temp file
File file = null;
try {
frameSequence = FrameSequence.decodeStream(inputStream);
file = File.createTempFile("gifRes", ".gif");
} catch (Exception e) {
e.printStackTrace();
}
if (file == null) {
return null;
}
// write inputStream to the temp file
try (OutputStream out = new FileOutputStream(file)) {
byte[] buffer = new byte[4 * 1024];
int len;
while ((len = inputStream.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
try {
inputStream.close();
......@@ -48,16 +69,20 @@ public class GifImageResource extends ImageResource {
// Nothing to do if we fail closing the stream
}
}
if (frameSequence == null) {
// prepare mImageDecoderSource
final ImageDecoder imageDecoder;
ImageDecoder.Source source = ImageDecoder.createSource(file);
if (source == null) {
return null;
}
return new GifImageResource(key, frameSequence);
return new GifImageResource(key, source);
}
@Override
public Drawable getDrawable(Resources resources) {
try {
return new FrameSequenceDrawable(mFrameSequence);
return (AnimatedImageDrawable) ImageDecoder.decodeDrawable(mImageDecoderSource);
} catch (final Throwable t) {
// Malicious gif images can make the platform throw different kind of throwables, such
// as OutOfMemoryError and NullPointerException. Catch them all.
......@@ -85,9 +110,6 @@ public class GifImageResource extends ImageResource {
@Override
public boolean supportsBitmapReuse() {
// FrameSequenceDrawable a.) takes two bitmaps and thus does not fit into the current
// bitmap pool architecture b.) will rarely use bitmaps from one FrameSequenceDrawable to
// the next that are the same sizes since they are used by attachments.
return false;
}
......@@ -107,12 +129,11 @@ public class GifImageResource extends ImageResource {
protected void close() {
acquireLock();
try {
if (mFrameSequence != null) {
mFrameSequence = null;
if (mImageDecoderSource != null) {
mImageDecoderSource = null;
}
} finally {
releaseLock();
}
}
}
......@@ -22,10 +22,10 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.drawable.AnimatedImageDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import androidx.annotation.Nullable;
import android.support.rastermill.FrameSequenceDrawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.ImageView;
......@@ -194,8 +194,8 @@ public class AsyncImageView extends ImageView implements MediaResourceLoadListen
mImageResource = resource;
mImageResource.addRef();
setImageDrawable(drawable);
if (drawable instanceof FrameSequenceDrawable) {
((FrameSequenceDrawable) drawable).start();
if (drawable instanceof AnimatedImageDrawable) {
((AnimatedImageDrawable) drawable).start();
}
if (getVisibility() == VISIBLE) {
......@@ -249,9 +249,8 @@ public class AsyncImageView extends ImageView implements MediaResourceLoadListen
private void releaseImageResource() {
final Drawable drawable = getDrawable();
if (drawable instanceof FrameSequenceDrawable) {
((FrameSequenceDrawable) drawable).stop();
((FrameSequenceDrawable) drawable).destroy();
if (drawable instanceof AnimatedImageDrawable) {
((AnimatedImageDrawable) drawable).stop();
}
if (mImageResource != null) {
mImageResource.release();
......
......@@ -18,7 +18,6 @@ package com.android.messaging.ui.photoviewer;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.rastermill.FrameSequenceDrawable;
import androidx.loader.content.AsyncTaskLoader;
import com.android.ex.photo.PhotoViewController;
......@@ -91,7 +90,6 @@ public class BuglePhotoBitmapLoader extends AsyncTaskLoader<BitmapResult>
final Drawable drawable = result != null ? result.drawable : null;
if (isReset()) {
// An async query came in while the loader is stopped. We don't need the result.
releaseDrawable(drawable);
return;
}
......@@ -140,11 +138,6 @@ public class BuglePhotoBitmapLoader extends AsyncTaskLoader<BitmapResult>
@Override
public void onCanceled(BitmapResult result) {
super.onCanceled(result);
// At this point we can release the resources associated with 'drawable' if needed.
if (result != null) {
releaseDrawable(result.drawable);
}
}
/**
......@@ -160,14 +153,6 @@ public class BuglePhotoBitmapLoader extends AsyncTaskLoader<BitmapResult>
releaseImageResource();
}
private void releaseDrawable(Drawable drawable) {
if (drawable != null && drawable instanceof FrameSequenceDrawable
&& !((FrameSequenceDrawable) drawable).isDestroyed()) {
((FrameSequenceDrawable) drawable).destroy();
}
}
private void setImageResource(final ImageResource resource) {
if (mImageResource != resource) {
// Clear out any information for what is currently used
......@@ -181,7 +166,6 @@ public class BuglePhotoBitmapLoader extends AsyncTaskLoader<BitmapResult>
private void releaseImageResource() {
// If we are getting rid of the imageResource backing the drawable, we must also
// destroy the drawable before releasing it.
releaseDrawable(mDrawable);
mDrawable = null;
if (mImageResource != null) {
......@@ -189,4 +173,4 @@ public class BuglePhotoBitmapLoader extends AsyncTaskLoader<BitmapResult>
}
mImageResource = null;
}
}
\ No newline at end of file
}
......@@ -16,8 +16,8 @@
package com.android.messaging.ui.photoviewer;
import android.content.Intent;
import android.graphics.drawable.AnimatedImageDrawable;
import android.graphics.drawable.Drawable;
import android.support.rastermill.FrameSequenceDrawable;
import androidx.loader.content.Loader;
import com.android.ex.photo.PhotoViewCallbacks;
......@@ -75,15 +75,15 @@ public class BuglePhotoViewFragment extends PhotoViewFragment {
private void stopGif() {
final Drawable drawable = getDrawable();
if (drawable != null && drawable instanceof FrameSequenceDrawable) {
((FrameSequenceDrawable) drawable).stop();
if (drawable != null && drawable instanceof AnimatedImageDrawable) {
((AnimatedImageDrawable) drawable).stop();
}
}
private void startGif() {
final Drawable drawable = getDrawable();
if (drawable != null && drawable instanceof FrameSequenceDrawable) {
((FrameSequenceDrawable) drawable).start();
if (drawable != null && drawable instanceof AnimatedImageDrawable) {
((AnimatedImageDrawable) drawable).start();
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment