1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/* 2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2010 The Android Open Source Project 3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License. 6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at 7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software 11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and 14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License. 15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.data; 18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 194bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Linimport android.content.Context; 204bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin 21f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.common.BlobCache; 22cafd30f96355ad446943d60cd2595d08423944e2Owen Linimport com.android.gallery3d.common.BlobCache.LookupRequest; 23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.common.Utils; 24cafd30f96355ad446943d60cd2595d08423944e2Owen Linimport com.android.gallery3d.data.BytesBufferPool.BytesBuffer; 25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.util.CacheManager; 26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.util.GalleryUtils; 27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.io.IOException; 29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.nio.ByteBuffer; 30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class ImageCacheService { 32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @SuppressWarnings("unused") 33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TAG = "ImageCacheService"; 34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String IMAGE_CACHE_FILE = "imgcache"; 36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int IMAGE_CACHE_MAX_ENTRIES = 5000; 37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int IMAGE_CACHE_MAX_BYTES = 200 * 1024 * 1024; 38adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin private static final int IMAGE_CACHE_VERSION = 7; 39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private BlobCache mCache; 41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public ImageCacheService(Context context) { 43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mCache = CacheManager.getCache(context, IMAGE_CACHE_FILE, 44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin IMAGE_CACHE_MAX_ENTRIES, IMAGE_CACHE_MAX_BYTES, 45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin IMAGE_CACHE_VERSION); 46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 48cafd30f96355ad446943d60cd2595d08423944e2Owen Lin /** 4909169dd269f1a82efb83ea1cebf75abe4daabd26ztenghui * Gets the cached image data for the given <code>path</code>, 5009169dd269f1a82efb83ea1cebf75abe4daabd26ztenghui * <code>timeModified</code> and <code>type</code>. 51cafd30f96355ad446943d60cd2595d08423944e2Owen Lin * 52cafd30f96355ad446943d60cd2595d08423944e2Owen Lin * The image data will be stored in <code>buffer.data</code>, started from 53cafd30f96355ad446943d60cd2595d08423944e2Owen Lin * <code>buffer.offset</code> for <code>buffer.length</code> bytes. If the 54cafd30f96355ad446943d60cd2595d08423944e2Owen Lin * buffer.data is not big enough, a new byte array will be allocated and returned. 55cafd30f96355ad446943d60cd2595d08423944e2Owen Lin * 56cafd30f96355ad446943d60cd2595d08423944e2Owen Lin * @return true if the image data is found; false if not found. 57cafd30f96355ad446943d60cd2595d08423944e2Owen Lin */ 5809169dd269f1a82efb83ea1cebf75abe4daabd26ztenghui public boolean getImageData(Path path, long timeModified, int type, BytesBuffer buffer) { 5909169dd269f1a82efb83ea1cebf75abe4daabd26ztenghui byte[] key = makeKey(path, timeModified, type); 60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin long cacheKey = Utils.crc64Long(key); 61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 62cafd30f96355ad446943d60cd2595d08423944e2Owen Lin LookupRequest request = new LookupRequest(); 63cafd30f96355ad446943d60cd2595d08423944e2Owen Lin request.key = cacheKey; 64cafd30f96355ad446943d60cd2595d08423944e2Owen Lin request.buffer = buffer.data; 65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin synchronized (mCache) { 66cafd30f96355ad446943d60cd2595d08423944e2Owen Lin if (!mCache.lookup(request)) return false; 67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 68cafd30f96355ad446943d60cd2595d08423944e2Owen Lin if (isSameKey(key, request.buffer)) { 69cafd30f96355ad446943d60cd2595d08423944e2Owen Lin buffer.data = request.buffer; 70cafd30f96355ad446943d60cd2595d08423944e2Owen Lin buffer.offset = key.length; 71cafd30f96355ad446943d60cd2595d08423944e2Owen Lin buffer.length = request.length - buffer.offset; 72cafd30f96355ad446943d60cd2595d08423944e2Owen Lin return true; 73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (IOException ex) { 75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // ignore. 76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 77cafd30f96355ad446943d60cd2595d08423944e2Owen Lin return false; 78f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 79f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 8009169dd269f1a82efb83ea1cebf75abe4daabd26ztenghui public void putImageData(Path path, long timeModified, int type, byte[] value) { 8109169dd269f1a82efb83ea1cebf75abe4daabd26ztenghui byte[] key = makeKey(path, timeModified, type); 82f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin long cacheKey = Utils.crc64Long(key); 83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ByteBuffer buffer = ByteBuffer.allocate(key.length + value.length); 84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin buffer.put(key); 85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin buffer.put(value); 86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin synchronized (mCache) { 87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mCache.insert(cacheKey, buffer.array()); 89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (IOException ex) { 90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // ignore. 91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 9509169dd269f1a82efb83ea1cebf75abe4daabd26ztenghui public void clearImageData(Path path, long timeModified, int type) { 9609169dd269f1a82efb83ea1cebf75abe4daabd26ztenghui byte[] key = makeKey(path, timeModified, type); 971c35ad56a274a8c1b6a60197855c0b838c4e1022George Mount long cacheKey = Utils.crc64Long(key); 981c35ad56a274a8c1b6a60197855c0b838c4e1022George Mount synchronized (mCache) { 991c35ad56a274a8c1b6a60197855c0b838c4e1022George Mount try { 1001c35ad56a274a8c1b6a60197855c0b838c4e1022George Mount mCache.clearEntry(cacheKey); 1011c35ad56a274a8c1b6a60197855c0b838c4e1022George Mount } catch (IOException ex) { 1021c35ad56a274a8c1b6a60197855c0b838c4e1022George Mount // ignore. 1031c35ad56a274a8c1b6a60197855c0b838c4e1022George Mount } 1041c35ad56a274a8c1b6a60197855c0b838c4e1022George Mount } 1051c35ad56a274a8c1b6a60197855c0b838c4e1022George Mount } 1061c35ad56a274a8c1b6a60197855c0b838c4e1022George Mount 10709169dd269f1a82efb83ea1cebf75abe4daabd26ztenghui private static byte[] makeKey(Path path, long timeModified, int type) { 10809169dd269f1a82efb83ea1cebf75abe4daabd26ztenghui return GalleryUtils.getBytes(path.toString() + "+" + timeModified + "+" + type); 109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static boolean isSameKey(byte[] key, byte[] buffer) { 112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int n = key.length; 113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (buffer.length < n) { 114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return false; 115f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = 0; i < n; ++i) { 117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (key[i] != buffer[i]) { 118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return false; 119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return true; 122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin} 124