1721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor/* 2721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * Copyright (C) 2012 The Android Open Source Project 3721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * 4721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * Licensed under the Apache License, Version 2.0 (the "License"); 5721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * you may not use this file except in compliance with the License. 6721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * You may obtain a copy of the License at 7721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * 8721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * http://www.apache.org/licenses/LICENSE-2.0 9721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * 10721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * Unless required by applicable law or agreed to in writing, software 11721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * distributed under the License is distributed on an "AS IS" BASIS, 12721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * See the License for the specific language governing permissions and 14721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * limitations under the License. 15721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor */ 16721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor 17721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylorpackage com.android.mms.util; 18721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor 19721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylorimport java.io.IOException; 20721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylorimport java.nio.ByteBuffer; 21721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor 22d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport android.content.Context; 23d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chen 24721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylorpublic class ImageCacheService { 25721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor @SuppressWarnings("unused") 26721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor private static final String TAG = "ImageCacheService"; 27721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor 287b6fe946f2e1020432e3600c8863f72449cd4e68Tom Taylor public static final String IMAGE_CACHE_FILE = "imgcache"; 29721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor private static final int IMAGE_CACHE_MAX_ENTRIES = 500; 30721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor private static final int IMAGE_CACHE_MAX_BYTES = 20 * 1024 * 1024; 31721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor private static final int IMAGE_CACHE_VERSION = 3; 32721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor 33721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor private BlobCache mCache; 34721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor 35721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor private static long[] sCrcTable = new long[256]; 36721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor private static final long POLY64REV = 0x95AC9329AC4BC9B5L; 37721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor private static final long INITIALCRC = 0xFFFFFFFFFFFFFFFFL; 38721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor 397b6fe946f2e1020432e3600c8863f72449cd4e68Tom Taylor private Context mContext; 407b6fe946f2e1020432e3600c8863f72449cd4e68Tom Taylor 41721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor public ImageCacheService(Context context) { 42721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor mCache = CacheManager.getCache(context, IMAGE_CACHE_FILE, 43721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor IMAGE_CACHE_MAX_ENTRIES, IMAGE_CACHE_MAX_BYTES, 44721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor IMAGE_CACHE_VERSION); 457b6fe946f2e1020432e3600c8863f72449cd4e68Tom Taylor mContext = context; 46721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 47721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor 48721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor public static class ImageData { 49721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor public ImageData(byte[] data, int offset) { 50721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor mData = data; 51721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor mOffset = offset; 52721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 53721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor public byte[] mData; 54721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor public int mOffset; 55721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 56721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor 57721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor public ImageData getImageData(String path, int type) { 58721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor byte[] key = makeKey(path, type); 59721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor long cacheKey = crc64Long(key); 60721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor try { 61721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor byte[] value = null; 62721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor synchronized (mCache) { 63721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor value = mCache.lookup(cacheKey); 64721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 65721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor if (value == null) return null; 66721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor if (isSameKey(key, value)) { 67721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor int offset = key.length; 68721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor return new ImageData(value, offset); 69721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 70721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } catch (IOException ex) { 71721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor // ignore. 72721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 73721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor return null; 74721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 75721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor 76721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor public void putImageData(String path, int type, byte[] value) { 77721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor byte[] key = makeKey(path, type); 78721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor long cacheKey = crc64Long(key); 79721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor ByteBuffer buffer = ByteBuffer.allocate(key.length + value.length); 80721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor buffer.put(key); 81721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor buffer.put(value); 82721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor synchronized (mCache) { 83721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor try { 84721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor mCache.insert(cacheKey, buffer.array()); 85721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } catch (IOException ex) { 86721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor // ignore. 87721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 88721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 89721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 90721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor 917b6fe946f2e1020432e3600c8863f72449cd4e68Tom Taylor public void clear() { 927b6fe946f2e1020432e3600c8863f72449cd4e68Tom Taylor CacheManager.clear(mContext); 937b6fe946f2e1020432e3600c8863f72449cd4e68Tom Taylor } 947b6fe946f2e1020432e3600c8863f72449cd4e68Tom Taylor 95721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor private static byte[] makeKey(String path, int type) { 96721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor return getBytes(path + "+" + type); 97721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 98721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor 99721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor private static boolean isSameKey(byte[] key, byte[] buffer) { 100721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor int n = key.length; 101721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor if (buffer.length < n) { 102721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor return false; 103721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 104721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor for (int i = 0; i < n; ++i) { 105721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor if (key[i] != buffer[i]) { 106721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor return false; 107721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 108721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 109721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor return true; 110721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 111721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor 112721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor /** 113721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * A function thats returns a 64-bit crc for string 114721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * 115721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * @param in input string 116721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * @return a 64-bit crc value 117721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor */ 118721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor public static final long crc64Long(String in) { 119721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor if (in == null || in.length() == 0) { 120721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor return 0; 121721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 122721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor return crc64Long(getBytes(in)); 123721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 124721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor 125721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor static { 126721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor // http://bioinf.cs.ucl.ac.uk/downloads/crc64/crc64.c 127721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor long part; 128721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor for (int i = 0; i < 256; i++) { 129721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor part = i; 130721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor for (int j = 0; j < 8; j++) { 131721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor long x = ((int) part & 1) != 0 ? POLY64REV : 0; 132721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor part = (part >> 1) ^ x; 133721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 134721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor sCrcTable[i] = part; 135721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 136721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 137721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor 138721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor public static final long crc64Long(byte[] buffer) { 139721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor long crc = INITIALCRC; 140721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor for (int k = 0, n = buffer.length; k < n; ++k) { 141721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor crc = sCrcTable[(((int) crc) ^ buffer[k]) & 0xff] ^ (crc >> 8); 142721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 143721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor return crc; 144721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 145721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor 146721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor public static byte[] getBytes(String in) { 147721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor byte[] result = new byte[in.length() * 2]; 148721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor int output = 0; 149721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor for (char ch : in.toCharArray()) { 150721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor result[output++] = (byte) (ch & 0xFF); 151721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor result[output++] = (byte) (ch >> 8); 152721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 153721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor return result; 154721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 155721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor 156721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor} 157