OSDN Git Service

Don't reuse bitmap before HoneyComb.
authorOwen Lin <owenlin@google.com>
Thu, 28 Jun 2012 09:12:20 +0000 (17:12 +0800)
committerOwen Lin <owenlin@google.com>
Tue, 3 Jul 2012 10:05:47 +0000 (18:05 +0800)
Change-Id: I0df9bf0a8f43e28ed25b436d4c584dc3ceb43c1d

14 files changed:
gallerycommon/src/com/android/gallery3d/common/ApiHelper.java
src/com/android/gallery3d/app/AbstractGalleryActivity.java
src/com/android/gallery3d/app/CropImage.java
src/com/android/gallery3d/app/MoviePlayer.java
src/com/android/gallery3d/app/Wallpaper.java
src/com/android/gallery3d/data/BitmapPool.java
src/com/android/gallery3d/data/DecodeUtils.java
src/com/android/gallery3d/data/ImageCacheRequest.java
src/com/android/gallery3d/data/LocalImage.java
src/com/android/gallery3d/data/MediaItem.java
src/com/android/gallery3d/ui/AlbumSetSlidingWindow.java
src/com/android/gallery3d/ui/AlbumSlidingWindow.java
src/com/android/gallery3d/ui/BitmapScreenNail.java
src/com/android/gallery3d/ui/GLRootView.java

index 85b0925..32c3a9c 100644 (file)
@@ -44,6 +44,9 @@ public class ApiHelper {
     public static final boolean HAS_REUSING_BITMAP_IN_BITMAP_REGION_DECODER =
             Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN;
 
+    public static final boolean HAS_REUSING_BITMAP_IN_BITMAP_FACTORY =
+            Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB;
+
     private static boolean hasField(Class<?> klass, String fieldName) {
         try {
             klass.getDeclaredField(fieldName);
index 0987ac3..9b2a85e 100644 (file)
@@ -32,6 +32,7 @@ import android.view.Window;
 import android.view.WindowManager;
 
 import com.android.gallery3d.R;
+import com.android.gallery3d.data.BitmapPool;
 import com.android.gallery3d.data.DataManager;
 import com.android.gallery3d.data.MediaItem;
 import com.android.gallery3d.ui.GLRoot;
@@ -188,11 +189,16 @@ public class AbstractGalleryActivity extends Activity implements GalleryActivity
         } finally {
             mGLRootView.unlockRenderThread();
         }
-        MediaItem.getMicroThumbPool().clear();
-        MediaItem.getThumbPool().clear();
+        clearBitmapPool(MediaItem.getMicroThumbPool());
+        clearBitmapPool(MediaItem.getThumbPool());
+
         MediaItem.getBytesBufferPool().clear();
     }
 
+    private static void clearBitmapPool(BitmapPool pool) {
+        if (pool != null) pool.clear();
+    }
+
     @Override
     protected void onDestroy() {
         super.onDestroy();
index f264697..294e285 100644 (file)
@@ -33,6 +33,7 @@ import android.graphics.Rect;
 import android.graphics.RectF;
 import android.media.ExifInterface;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.Handler;
@@ -369,7 +370,7 @@ public class CropImage extends AbstractGalleryActivity {
         }
     }
 
-    @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN)
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
     private static void setImageSize(ContentValues values, int width, int height) {
         // The two fields are available since ICS but got published in JB
         if (ApiHelper.HAS_MEDIA_COLUMNS_WIDTH_AND_HEIGHT) {
index 4f72c13..660c4d9 100644 (file)
@@ -29,6 +29,7 @@ import android.graphics.Color;
 import android.media.AudioManager;
 import android.media.MediaPlayer;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.view.KeyEvent;
@@ -178,7 +179,7 @@ public class MoviePlayer implements
         }
     }
 
-    @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN)
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
     private void setOnSystemUiVisibilityChangeListener() {
         if (!ApiHelper.HAS_VIEW_SYSTEM_UI_FLAG_HIDE_NAVIGATION) return;
 
@@ -212,7 +213,7 @@ public class MoviePlayer implements
         });
     }
 
-    @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN)
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
     private void showSystemUi(boolean visible) {
         if (!ApiHelper.HAS_VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE) return;
 
index 1ece66c..996d3f0 100644 (file)
@@ -63,7 +63,7 @@ public class Wallpaper extends Activity {
     }
 
     @SuppressWarnings("deprecation")
-    @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB_MR2)
+    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
     private Point getDefaultDisplaySize(Point size) {
         Display d = getWindowManager().getDefaultDisplay();
         if (Build.VERSION.SDK_INT >= ApiHelper.VERSION_CODES.HONEYCOMB_MR2) {
index 0fbd84e..1151dde 100644 (file)
 package com.android.gallery3d.data;
 
 import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapFactory.Options;
 
 import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.ui.Log;
-import com.android.gallery3d.util.ThreadPool.JobContext;
 
-import java.io.FileDescriptor;
 import java.util.ArrayList;
 
 public class BitmapPool {
@@ -94,67 +89,7 @@ public class BitmapPool {
         mPool.clear();
     }
 
-    private Bitmap findCachedBitmap(JobContext jc,
-            byte[] data, int offset, int length, Options options) {
-        if (mOneSize) return getBitmap();
-        DecodeUtils.decodeBounds(jc, data, offset, length, options);
-        return getBitmap(options.outWidth, options.outHeight);
-    }
-
-    private Bitmap findCachedBitmap(JobContext jc,
-            FileDescriptor fileDescriptor, Options options) {
-        if (mOneSize) return getBitmap();
-        DecodeUtils.decodeBounds(jc, fileDescriptor, options);
-        return getBitmap(options.outWidth, options.outHeight);
-    }
-
-    public Bitmap decode(JobContext jc,
-            byte[] data, int offset, int length, BitmapFactory.Options options) {
-        if (options == null) options = new BitmapFactory.Options();
-        if (options.inSampleSize < 1) options.inSampleSize = 1;
-        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-        options.inBitmap = (options.inSampleSize == 1)
-                ? findCachedBitmap(jc, data, offset, length, options) : null;
-        try {
-            Bitmap bitmap = DecodeUtils.decode(jc, data, offset, length, options);
-            if (options.inBitmap != null && options.inBitmap != bitmap) {
-                recycle(options.inBitmap);
-                options.inBitmap = null;
-            }
-            return bitmap;
-        } catch (IllegalArgumentException e) {
-            if (options.inBitmap == null) throw e;
-
-            Log.w(TAG, "decode fail with a given bitmap, try decode to a new bitmap");
-            recycle(options.inBitmap);
-            options.inBitmap = null;
-            return DecodeUtils.decode(jc, data, offset, length, options);
-        }
-    }
-
-    // This is the same as the method above except the source data comes
-    // from a file descriptor instead of a byte array.
-    public Bitmap decode(JobContext jc,
-            FileDescriptor fileDescriptor, Options options) {
-        if (options == null) options = new BitmapFactory.Options();
-        if (options.inSampleSize < 1) options.inSampleSize = 1;
-        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-        options.inBitmap = (options.inSampleSize == 1)
-                ? findCachedBitmap(jc, fileDescriptor, options) : null;
-        try {
-            Bitmap bitmap = DecodeUtils.decode(jc, fileDescriptor, options);
-            if (options.inBitmap != null&& options.inBitmap != bitmap) {
-                recycle(options.inBitmap);
-                options.inBitmap = null;
-            }
-            return bitmap;
-        } catch (IllegalArgumentException e) {
-            if (options.inBitmap == null) throw e;
-
-            Log.w(TAG, "decode fail with a given bitmap, try decode to a new bitmap");
-            recycle(options.inBitmap);
-            options.inBitmap = null;
-            return DecodeUtils.decode(jc, fileDescriptor, options);
-        }
+    public boolean isOneSize() {
+        return mOneSize;
     }
 }
index e51dc3f..773af74 100644 (file)
 
 package com.android.gallery3d.data;
 
+import android.annotation.TargetApi;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
 import android.graphics.BitmapFactory;
 import android.graphics.BitmapFactory.Options;
 import android.graphics.BitmapRegionDecoder;
+import android.os.Build;
 import android.util.FloatMath;
 
 import com.android.gallery3d.common.BitmapUtils;
 import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.ui.Log;
 import com.android.gallery3d.util.ThreadPool.CancelListener;
 import com.android.gallery3d.util.ThreadPool.JobContext;
 
@@ -33,7 +36,7 @@ import java.io.FileInputStream;
 import java.io.InputStream;
 
 public class DecodeUtils {
-    private static final String TAG = "DecodeService";
+    private static final String TAG = "DecodeUtils";
 
     private static class DecodeCanceller implements CancelListener {
         Options mOptions;
@@ -230,4 +233,78 @@ public class DecodeUtils {
             return null;
         }
     }
+
+    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+    public static Bitmap decode(JobContext jc, byte[] data, int offset,
+            int length, BitmapFactory.Options options, BitmapPool pool) {
+        if (pool == null) {
+            return decode(jc, data, offset, length, options);
+        }
+
+        if (options == null) options = new BitmapFactory.Options();
+        if (options.inSampleSize < 1) options.inSampleSize = 1;
+        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+        options.inBitmap = (options.inSampleSize == 1)
+                ? findCachedBitmap(pool, jc, data, offset, length, options) : null;
+        try {
+            Bitmap bitmap = decode(jc, data, offset, length, options);
+            if (options.inBitmap != null && options.inBitmap != bitmap) {
+                pool.recycle(options.inBitmap);
+                options.inBitmap = null;
+            }
+            return bitmap;
+        } catch (IllegalArgumentException e) {
+            if (options.inBitmap == null) throw e;
+
+            Log.w(TAG, "decode fail with a given bitmap, try decode to a new bitmap");
+            pool.recycle(options.inBitmap);
+            options.inBitmap = null;
+            return decode(jc, data, offset, length, options);
+        }
+    }
+
+    // This is the same as the method above except the source data comes
+    // from a file descriptor instead of a byte array.
+    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+    public static Bitmap decode(JobContext jc,
+            FileDescriptor fileDescriptor, Options options, BitmapPool pool) {
+        if (pool == null) {
+            return decode(jc, fileDescriptor, options);
+        }
+
+        if (options == null) options = new BitmapFactory.Options();
+        if (options.inSampleSize < 1) options.inSampleSize = 1;
+        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+        options.inBitmap = (options.inSampleSize == 1)
+                ? findCachedBitmap(pool, jc, fileDescriptor, options) : null;
+        try {
+            Bitmap bitmap = DecodeUtils.decode(jc, fileDescriptor, options);
+            if (options.inBitmap != null && options.inBitmap != bitmap) {
+                pool.recycle(options.inBitmap);
+                options.inBitmap = null;
+            }
+            return bitmap;
+        } catch (IllegalArgumentException e) {
+            if (options.inBitmap == null) throw e;
+
+            Log.w(TAG, "decode fail with a given bitmap, try decode to a new bitmap");
+            pool.recycle(options.inBitmap);
+            options.inBitmap = null;
+            return decode(jc, fileDescriptor, options);
+        }
+    }
+
+    private static Bitmap findCachedBitmap(BitmapPool pool, JobContext jc,
+            byte[] data, int offset, int length, Options options) {
+        if (pool.isOneSize()) return pool.getBitmap();
+        decodeBounds(jc, data, offset, length, options);
+        return pool.getBitmap(options.outWidth, options.outHeight);
+    }
+
+    private static Bitmap findCachedBitmap(BitmapPool pool, JobContext jc,
+            FileDescriptor fileDescriptor, Options options) {
+        if (pool.isOneSize()) return pool.getBitmap();
+        decodeBounds(jc, fileDescriptor, options);
+        return pool.getBitmap(options.outWidth, options.outHeight);
+    }
 }
index 81660c9..b977b10 100644 (file)
@@ -57,11 +57,13 @@ abstract class ImageCacheRequest implements Job<Bitmap> {
                 options.inPreferredConfig = Bitmap.Config.ARGB_8888;
                 Bitmap bitmap;
                 if (mType == MediaItem.TYPE_MICROTHUMBNAIL) {
-                    bitmap = MediaItem.getMicroThumbPool().decode(jc,
-                            buffer.data, buffer.offset, buffer.length, options);
+                    bitmap = DecodeUtils.decode(jc,
+                            buffer.data, buffer.offset, buffer.length, options,
+                            MediaItem.getMicroThumbPool());
                 } else {
-                    bitmap = MediaItem.getThumbPool().decode(jc,
-                            buffer.data, buffer.offset, buffer.length, options);
+                    bitmap = DecodeUtils.decode(jc,
+                            buffer.data, buffer.offset, buffer.length, options,
+                            MediaItem.getThumbPool());
                 }
                 if (bitmap == null && !jc.isCancelled()) {
                     Log.w(TAG, "decode cached failed " + debugTag);
index 316e324..c432ab4 100644 (file)
@@ -25,6 +25,7 @@ import android.graphics.BitmapFactory;
 import android.graphics.BitmapRegionDecoder;
 import android.media.ExifInterface;
 import android.net.Uri;
+import android.os.Build;
 import android.provider.MediaStore.Images;
 import android.provider.MediaStore.Images.ImageColumns;
 import android.provider.MediaStore.MediaColumns;
@@ -85,7 +86,7 @@ public class LocalImage extends LocalMediaItem {
         updateWidthAndHeightProjection();
     }
 
-    @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN)
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
     private static void updateWidthAndHeightProjection() {
         if (ApiHelper.HAS_MEDIA_COLUMNS_WIDTH_AND_HEIGHT) {
             PROJECTION[INDEX_WIDTH] = MediaColumns.WIDTH;
index f0f1af4..15bb176 100644 (file)
@@ -19,6 +19,7 @@ package com.android.gallery3d.data;
 import android.graphics.Bitmap;
 import android.graphics.BitmapRegionDecoder;
 
+import com.android.gallery3d.common.ApiHelper;
 import com.android.gallery3d.ui.ScreenNail;
 import com.android.gallery3d.util.ThreadPool.Job;
 
@@ -42,9 +43,16 @@ public abstract class MediaItem extends MediaObject {
     private static final int BYTESBUFFE_POOL_SIZE = 4;
     private static final int BYTESBUFFER_SIZE = 200 * 1024;
 
-    private static final BitmapPool sMicroThumbPool = new BitmapPool(
-            MICROTHUMBNAIL_TARGET_SIZE, MICROTHUMBNAIL_TARGET_SIZE, 16);
-    private static final BitmapPool sThumbPool = new BitmapPool(4);
+    private static final BitmapPool sMicroThumbPool =
+            ApiHelper.HAS_REUSING_BITMAP_IN_BITMAP_FACTORY
+            ? new BitmapPool(MICROTHUMBNAIL_TARGET_SIZE, MICROTHUMBNAIL_TARGET_SIZE, 16)
+            : null;
+
+    private static final BitmapPool sThumbPool =
+            ApiHelper.HAS_REUSING_BITMAP_IN_BITMAP_FACTORY
+            ? new BitmapPool(4)
+            : null;
+
     private static final BytesBufferPool sMicroThumbBufferPool =
             new BytesBufferPool(BYTESBUFFE_POOL_SIZE, BYTESBUFFER_SIZE);
 
index 6561a23..449c6f9 100644 (file)
@@ -23,6 +23,7 @@ import com.android.gallery3d.R;
 import com.android.gallery3d.app.AlbumSetDataLoader;
 import com.android.gallery3d.app.GalleryActivity;
 import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.data.BitmapPool;
 import com.android.gallery3d.data.DataSourceType;
 import com.android.gallery3d.data.MediaItem;
 import com.android.gallery3d.data.MediaObject;
@@ -423,7 +424,8 @@ public class AlbumSetSlidingWindow implements AlbumSetDataLoader.DataListener {
 
         @Override
         protected void recycleBitmap(Bitmap bitmap) {
-            MediaItem.getMicroThumbPool().recycle(bitmap);
+            BitmapPool pool = MediaItem.getMicroThumbPool();
+            if (pool != null) pool.recycle(bitmap);
         }
 
         @Override
index deec171..d5d90a9 100644 (file)
@@ -22,6 +22,7 @@ import android.os.Message;
 import com.android.gallery3d.app.AlbumDataLoader;
 import com.android.gallery3d.app.GalleryActivity;
 import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.data.BitmapPool;
 import com.android.gallery3d.data.MediaItem;
 import com.android.gallery3d.data.Path;
 import com.android.gallery3d.util.Future;
@@ -277,7 +278,8 @@ public class AlbumSlidingWindow implements AlbumDataLoader.DataListener {
 
         @Override
         protected void recycleBitmap(Bitmap bitmap) {
-            MediaItem.getMicroThumbPool().recycle(bitmap);
+            BitmapPool pool = MediaItem.getMicroThumbPool();
+            if (pool != null) pool.recycle(bitmap);
         }
 
         @Override
index 5c91757..0043e0c 100644 (file)
@@ -20,6 +20,7 @@ import android.graphics.Bitmap;
 import android.graphics.RectF;
 
 import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.data.BitmapPool;
 import com.android.gallery3d.data.MediaItem;
 
 // This is a ScreenNail wraps a Bitmap. There are some extra functions:
@@ -70,6 +71,11 @@ public class BitmapScreenNail implements ScreenNail {
         mHeight = Math.round(scale * height);
     }
 
+    private static void recycleBitmap(BitmapPool pool, Bitmap bitmap) {
+        if (pool == null || bitmap == null) return;
+        pool.recycle(bitmap);
+    }
+
     // Combines the two ScreenNails.
     // Returns the used one and recycle the unused one.
     public ScreenNail combine(ScreenNail other) {
@@ -88,9 +94,7 @@ public class BitmapScreenNail implements ScreenNail {
         mWidth = newer.mWidth;
         mHeight = newer.mHeight;
         if (newer.mBitmap != null) {
-            if (mBitmap != null) {
-                MediaItem.getThumbPool().recycle(mBitmap);
-            }
+            recycleBitmap(MediaItem.getThumbPool(), mBitmap);
             mBitmap = newer.mBitmap;
             newer.mBitmap = null;
 
@@ -130,10 +134,8 @@ public class BitmapScreenNail implements ScreenNail {
             mTexture.recycle();
             mTexture = null;
         }
-        if (mBitmap != null) {
-            MediaItem.getThumbPool().recycle(mBitmap);
-            mBitmap = null;
-        }
+        recycleBitmap(MediaItem.getThumbPool(), mBitmap);
+        mBitmap = null;
     }
 
     @Override
index 401ca59..fe4e19d 100644 (file)
@@ -21,6 +21,7 @@ import android.content.Context;
 import android.graphics.Matrix;
 import android.graphics.PixelFormat;
 import android.opengl.GLSurfaceView;
+import android.os.Build;
 import android.os.Process;
 import android.os.SystemClock;
 import android.util.AttributeSet;
@@ -536,7 +537,7 @@ public class GLRootView extends GLSurfaceView
     }
 
     @Override
-    @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN)
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
     public void setLightsOutMode(boolean enabled) {
         int flags = 0;
         if (enabled) {