1 /* 2 * Copyright (C) 2015 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 package com.android.messaging.datamodel.media; 17 18 import android.content.res.Resources; 19 import android.graphics.Bitmap; 20 import android.graphics.drawable.Drawable; 21 import android.media.ExifInterface; 22 import android.support.rastermill.FrameSequence; 23 import android.support.rastermill.FrameSequenceDrawable; 24 25 import com.android.messaging.util.Assert; 26 import com.android.messaging.util.LogUtil; 27 28 import java.io.IOException; 29 import java.io.InputStream; 30 31 public class GifImageResource extends ImageResource { 32 private FrameSequence mFrameSequence; 33 GifImageResource(String key, FrameSequence frameSequence)34 public GifImageResource(String key, FrameSequence frameSequence) { 35 // GIF does not support exif tags 36 super(key, ExifInterface.ORIENTATION_NORMAL); 37 mFrameSequence = frameSequence; 38 } 39 createGifImageResource(String key, InputStream inputStream)40 public static GifImageResource createGifImageResource(String key, InputStream inputStream) { 41 final FrameSequence frameSequence; 42 try { 43 frameSequence = FrameSequence.decodeStream(inputStream); 44 } finally { 45 try { 46 inputStream.close(); 47 } catch (IOException e) { 48 // Nothing to do if we fail closing the stream 49 } 50 } 51 if (frameSequence == null) { 52 return null; 53 } 54 return new GifImageResource(key, frameSequence); 55 } 56 57 @Override getDrawable(Resources resources)58 public Drawable getDrawable(Resources resources) { 59 try { 60 return new FrameSequenceDrawable(mFrameSequence); 61 } catch (final Throwable t) { 62 // Malicious gif images can make the platform throw different kind of throwables, such 63 // as OutOfMemoryError and NullPointerException. Catch them all. 64 LogUtil.e(LogUtil.BUGLE_TAG, "Error getting drawable for GIF", t); 65 return null; 66 } 67 } 68 69 @Override getBitmap()70 public Bitmap getBitmap() { 71 Assert.fail("GetBitmap() should never be called on a gif."); 72 return null; 73 } 74 75 @Override getBytes()76 public byte[] getBytes() { 77 Assert.fail("GetBytes() should never be called on a gif."); 78 return null; 79 } 80 81 @Override reuseBitmap()82 public Bitmap reuseBitmap() { 83 return null; 84 } 85 86 @Override supportsBitmapReuse()87 public boolean supportsBitmapReuse() { 88 // FrameSequenceDrawable a.) takes two bitmaps and thus does not fit into the current 89 // bitmap pool architecture b.) will rarely use bitmaps from one FrameSequenceDrawable to 90 // the next that are the same sizes since they are used by attachments. 91 return false; 92 } 93 94 @Override getMediaSize()95 public int getMediaSize() { 96 Assert.fail("GifImageResource should not be used by a media cache"); 97 // Only used by the media cache, which this does not use. 98 return 0; 99 } 100 101 @Override isCacheable()102 public boolean isCacheable() { 103 return false; 104 } 105 106 @Override close()107 protected void close() { 108 acquireLock(); 109 try { 110 if (mFrameSequence != null) { 111 mFrameSequence = null; 112 } 113 } finally { 114 releaseLock(); 115 } 116 } 117 118 } 119