diff options
author | Owen Lin <owenlin@google.com> | 2012-04-09 10:15:35 +0800 |
---|---|---|
committer | Owen Lin <owenlin@google.com> | 2012-04-10 14:39:23 +0800 |
commit | d8d1cfdb80a7bcc950e8deb957a6c55ec83a68b0 (patch) | |
tree | c5a5f0dac151c4f4cec881e9862ce592343b9608 /src | |
parent | a66827d34d8c29a612787e3fa2557a53191494da (diff) | |
download | android_packages_apps_Snap-d8d1cfdb80a7bcc950e8deb957a6c55ec83a68b0.tar.gz android_packages_apps_Snap-d8d1cfdb80a7bcc950e8deb957a6c55ec83a68b0.tar.bz2 android_packages_apps_Snap-d8d1cfdb80a7bcc950e8deb957a6c55ec83a68b0.zip |
Add BytesBufferPool to prevent GC.
Change-Id: Ia8513ff380a60f102481cbf25650eca149b75064
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/gallery3d/app/AbstractGalleryActivity.java | 1 | ||||
-rw-r--r-- | src/com/android/gallery3d/data/BitmapPool.java (renamed from src/com/android/gallery3d/ui/BitmapPool.java) | 4 | ||||
-rw-r--r-- | src/com/android/gallery3d/data/BytesBufferPool.java | 91 | ||||
-rw-r--r-- | src/com/android/gallery3d/data/ImageCacheRequest.java | 76 | ||||
-rw-r--r-- | src/com/android/gallery3d/data/ImageCacheService.java | 39 | ||||
-rw-r--r-- | src/com/android/gallery3d/data/MediaItem.java | 11 | ||||
-rw-r--r-- | src/com/android/gallery3d/ui/AlbumLabelMaker.java | 1 | ||||
-rw-r--r-- | src/com/android/gallery3d/ui/TextureUploader.java | 6 |
8 files changed, 168 insertions, 61 deletions
diff --git a/src/com/android/gallery3d/app/AbstractGalleryActivity.java b/src/com/android/gallery3d/app/AbstractGalleryActivity.java index 64c430d7f..eddaea5cb 100644 --- a/src/com/android/gallery3d/app/AbstractGalleryActivity.java +++ b/src/com/android/gallery3d/app/AbstractGalleryActivity.java @@ -178,6 +178,7 @@ public class AbstractGalleryActivity extends Activity implements GalleryActivity mGLRootView.unlockRenderThread(); } MediaItem.getMicroThumbPool().clear(); + MediaItem.getBytesBufferPool().clear(); } @Override diff --git a/src/com/android/gallery3d/ui/BitmapPool.java b/src/com/android/gallery3d/data/BitmapPool.java index 2cd3a4e51..c52a57b0a 100644 --- a/src/com/android/gallery3d/ui/BitmapPool.java +++ b/src/com/android/gallery3d/data/BitmapPool.java @@ -1,12 +1,12 @@ // Copyright 2012 Google Inc. All Rights Reserved. -package com.android.gallery3d.ui; +package com.android.gallery3d.data; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BitmapFactory.Options; -import com.android.gallery3d.data.DecodeUtils; +import com.android.gallery3d.ui.Log; import com.android.gallery3d.util.ThreadPool.JobContext; import java.io.FileDescriptor; diff --git a/src/com/android/gallery3d/data/BytesBufferPool.java b/src/com/android/gallery3d/data/BytesBufferPool.java new file mode 100644 index 000000000..d2da323fc --- /dev/null +++ b/src/com/android/gallery3d/data/BytesBufferPool.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.data; + +import com.android.gallery3d.util.ThreadPool.JobContext; + +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; + +public class BytesBufferPool { + + private static final int READ_STEP = 4096; + + public static class BytesBuffer { + public byte[] data; + public int offset; + public int length; + + private BytesBuffer(int capacity) { + this.data = new byte[capacity]; + } + + // an helper function to read content from FileDescriptor + public void readFrom(JobContext jc, FileDescriptor fd) throws IOException { + FileInputStream fis = new FileInputStream(fd); + length = 0; + try { + int capacity = data.length; + while (true) { + int step = Math.min(READ_STEP, capacity - length); + int rc = fis.read(data, length, step); + if (rc < 0 || jc.isCancelled()) return; + length += rc; + + if (length == capacity) { + byte[] newData = new byte[data.length * 2]; + System.arraycopy(data, 0, newData, 0, data.length); + data = newData; + capacity = data.length; + } + } + } finally { + fis.close(); + } + } + } + + private final int mPoolSize; + private final int mBufferSize; + private final ArrayList<BytesBuffer> mList; + + public BytesBufferPool(int poolSize, int bufferSize) { + mList = new ArrayList<BytesBuffer>(poolSize); + mPoolSize = poolSize; + mBufferSize = bufferSize; + } + + public synchronized BytesBuffer get() { + int n = mList.size(); + return n > 0 ? mList.remove(n - 1) : new BytesBuffer(mBufferSize); + } + + public synchronized void recycle(BytesBuffer buffer) { + if (buffer.data.length != mBufferSize) return; + if (mList.size() < mPoolSize) { + buffer.offset = 0; + buffer.length = 0; + mList.add(buffer); + } + } + + public synchronized void clear() { + mList.clear(); + } +} diff --git a/src/com/android/gallery3d/data/ImageCacheRequest.java b/src/com/android/gallery3d/data/ImageCacheRequest.java index d3d4f51e7..c10158bcd 100644 --- a/src/com/android/gallery3d/data/ImageCacheRequest.java +++ b/src/com/android/gallery3d/data/ImageCacheRequest.java @@ -21,7 +21,7 @@ import android.graphics.BitmapFactory; import com.android.gallery3d.app.GalleryApp; import com.android.gallery3d.common.BitmapUtils; -import com.android.gallery3d.data.ImageCacheService.ImageData; +import com.android.gallery3d.data.BytesBufferPool.BytesBuffer; import com.android.gallery3d.util.ThreadPool.Job; import com.android.gallery3d.util.ThreadPool.JobContext; @@ -41,52 +41,56 @@ abstract class ImageCacheRequest implements Job<Bitmap> { mTargetSize = targetSize; } + @Override public Bitmap run(JobContext jc) { String debugTag = mPath + "," + ((mType == MediaItem.TYPE_THUMBNAIL) ? "THUMB" : (mType == MediaItem.TYPE_MICROTHUMBNAIL) ? "MICROTHUMB" : "?"); ImageCacheService cacheService = mApplication.getImageCacheService(); - ImageData data = cacheService.getImageData(mPath, mType); - if (jc.isCancelled()) return null; - - if (data != null) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inPreferredConfig = Bitmap.Config.ARGB_8888; - Bitmap bitmap; - if (mType == MediaItem.TYPE_MICROTHUMBNAIL) { - bitmap = MediaItem.getMicroThumbPool().decode(jc, - data.mData, data.mOffset, data.mData.length - data.mOffset, options); - } else { - bitmap = DecodeUtils.decode(jc, - data.mData, data.mOffset, data.mData.length - data.mOffset, options); - } - if (bitmap == null && !jc.isCancelled()) { - Log.w(TAG, "decode cached failed " + debugTag); - } - return bitmap; - } else { - Bitmap bitmap = onDecodeOriginal(jc, mType); + BytesBuffer buffer = MediaItem.getBytesBufferPool().get(); + try { + boolean found = cacheService.getImageData(mPath, mType, buffer); if (jc.isCancelled()) return null; - - if (bitmap == null) { - Log.w(TAG, "decode orig failed " + debugTag); - return null; - } - - if (mType == MediaItem.TYPE_MICROTHUMBNAIL) { - bitmap = BitmapUtils.resizeAndCropCenter(bitmap, mTargetSize, true); - } else { - bitmap = BitmapUtils.resizeDownBySideLength(bitmap, mTargetSize, true); + if (found) { + BitmapFactory.Options options = new BitmapFactory.Options(); + 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); + } else { + bitmap = DecodeUtils.decode(jc, + buffer.data, buffer.offset, buffer.length, options); + } + if (bitmap == null && !jc.isCancelled()) { + Log.w(TAG, "decode cached failed " + debugTag); + } + return bitmap; } - if (jc.isCancelled()) return null; + } finally { + MediaItem.getBytesBufferPool().recycle(buffer); + } + Bitmap bitmap = onDecodeOriginal(jc, mType); + if (jc.isCancelled()) return null; - byte[] array = BitmapUtils.compressToBytes(bitmap); - if (jc.isCancelled()) return null; + if (bitmap == null) { + Log.w(TAG, "decode orig failed " + debugTag); + return null; + } - cacheService.putImageData(mPath, mType, array); - return bitmap; + if (mType == MediaItem.TYPE_MICROTHUMBNAIL) { + bitmap = BitmapUtils.resizeAndCropCenter(bitmap, mTargetSize, true); + } else { + bitmap = BitmapUtils.resizeDownBySideLength(bitmap, mTargetSize, true); } + if (jc.isCancelled()) return null; + + byte[] array = BitmapUtils.compressToBytes(bitmap); + if (jc.isCancelled()) return null; + + cacheService.putImageData(mPath, mType, array); + return bitmap; } public abstract Bitmap onDecodeOriginal(JobContext jc, int targetSize); diff --git a/src/com/android/gallery3d/data/ImageCacheService.java b/src/com/android/gallery3d/data/ImageCacheService.java index fdc27749b..0e7931389 100644 --- a/src/com/android/gallery3d/data/ImageCacheService.java +++ b/src/com/android/gallery3d/data/ImageCacheService.java @@ -19,7 +19,9 @@ package com.android.gallery3d.data; import android.content.Context; import com.android.gallery3d.common.BlobCache; +import com.android.gallery3d.common.BlobCache.LookupRequest; import com.android.gallery3d.common.Utils; +import com.android.gallery3d.data.BytesBufferPool.BytesBuffer; import com.android.gallery3d.util.CacheManager; import com.android.gallery3d.util.GalleryUtils; @@ -43,32 +45,35 @@ public class ImageCacheService { IMAGE_CACHE_VERSION); } - public static class ImageData { - public ImageData(byte[] data, int offset) { - mData = data; - mOffset = offset; - } - public byte[] mData; - public int mOffset; - } - - public ImageData getImageData(Path path, int type) { + /** + * Gets the cached image data for the given <code>path</code> and <code>type</code>. + * + * The image data will be stored in <code>buffer.data</code>, started from + * <code>buffer.offset</code> for <code>buffer.length</code> bytes. If the + * buffer.data is not big enough, a new byte array will be allocated and returned. + * + * @return true if the image data is found; false if not found. + */ + public boolean getImageData(Path path, int type, BytesBuffer buffer) { byte[] key = makeKey(path, type); long cacheKey = Utils.crc64Long(key); try { - byte[] value = null; + LookupRequest request = new LookupRequest(); + request.key = cacheKey; + request.buffer = buffer.data; synchronized (mCache) { - value = mCache.lookup(cacheKey); + if (!mCache.lookup(request)) return false; } - if (value == null) return null; - if (isSameKey(key, value)) { - int offset = key.length; - return new ImageData(value, offset); + if (isSameKey(key, request.buffer)) { + buffer.data = request.buffer; + buffer.offset = key.length; + buffer.length = request.length - buffer.offset; + return true; } } catch (IOException ex) { // ignore. } - return null; + return false; } public void putImageData(Path path, int type, byte[] value) { diff --git a/src/com/android/gallery3d/data/MediaItem.java b/src/com/android/gallery3d/data/MediaItem.java index 2b8f8a353..3de70d954 100644 --- a/src/com/android/gallery3d/data/MediaItem.java +++ b/src/com/android/gallery3d/data/MediaItem.java @@ -19,7 +19,6 @@ package com.android.gallery3d.data; import android.graphics.Bitmap; import android.graphics.BitmapRegionDecoder; -import com.android.gallery3d.ui.BitmapPool; import com.android.gallery3d.ui.ScreenNail; import com.android.gallery3d.util.ThreadPool.Job; @@ -40,9 +39,15 @@ public abstract class MediaItem extends MediaObject { public static final String MIME_TYPE_JPEG = "image/jpeg"; + 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); + private static final BytesBufferPool sMicroThumbBufferPool = + new BytesBufferPool(BYTESBUFFE_POOL_SIZE, BYTESBUFFER_SIZE); + // TODO: fix default value for latlng and change this. public static final double INVALID_LATLNG = 0f; @@ -116,4 +121,8 @@ public abstract class MediaItem extends MediaObject { public static BitmapPool getMicroThumbPool() { return sMicroThumbPool; } + + public static BytesBufferPool getBytesBufferPool() { + return sMicroThumbBufferPool; + } } diff --git a/src/com/android/gallery3d/ui/AlbumLabelMaker.java b/src/com/android/gallery3d/ui/AlbumLabelMaker.java index 09c779b6c..43a9055a4 100644 --- a/src/com/android/gallery3d/ui/AlbumLabelMaker.java +++ b/src/com/android/gallery3d/ui/AlbumLabelMaker.java @@ -14,6 +14,7 @@ import android.text.TextPaint; import android.text.TextUtils; import com.android.gallery3d.R; +import com.android.gallery3d.data.BitmapPool; import com.android.gallery3d.data.DataSourceType; import com.android.gallery3d.util.ThreadPool; import com.android.gallery3d.util.ThreadPool.JobContext; diff --git a/src/com/android/gallery3d/ui/TextureUploader.java b/src/com/android/gallery3d/ui/TextureUploader.java index a372eab70..b651c69a4 100644 --- a/src/com/android/gallery3d/ui/TextureUploader.java +++ b/src/com/android/gallery3d/ui/TextureUploader.java @@ -84,11 +84,7 @@ public class TextureUploader implements OnGLIdleListener { int uploadQuota = QUOTA_PER_FRAME; uploadQuota = upload(canvas, mFgTextures, uploadQuota, false); if (uploadQuota < QUOTA_PER_FRAME) mGLRoot.requestRender(); - - // don't upload background texture if there is pending render request - if (!renderRequested) { - upload(canvas, mBgTextures, uploadQuota, true); - } + upload(canvas, mBgTextures, uploadQuota, true); synchronized (this) { mIsQueued = !mFgTextures.isEmpty() || !mBgTextures.isEmpty(); return mIsQueued; |