/* * 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.mms.util; import java.io.IOException; import java.nio.ByteBuffer; import android.content.Context; public class ImageCacheService { @SuppressWarnings("unused") private static final String TAG = "ImageCacheService"; public static final String IMAGE_CACHE_FILE = "imgcache"; private static final int IMAGE_CACHE_MAX_ENTRIES = 500; private static final int IMAGE_CACHE_MAX_BYTES = 20 * 1024 * 1024; private static final int IMAGE_CACHE_VERSION = 3; private BlobCache mCache; private static long[] sCrcTable = new long[256]; private static final long POLY64REV = 0x95AC9329AC4BC9B5L; private static final long INITIALCRC = 0xFFFFFFFFFFFFFFFFL; private Context mContext; public ImageCacheService(Context context) { mCache = CacheManager.getCache(context, IMAGE_CACHE_FILE, IMAGE_CACHE_MAX_ENTRIES, IMAGE_CACHE_MAX_BYTES, IMAGE_CACHE_VERSION); mContext = context; } public static class ImageData { public ImageData(byte[] data, int offset) { mData = data; mOffset = offset; } public byte[] mData; public int mOffset; } public ImageData getImageData(String path, int type) { byte[] key = makeKey(path, type); long cacheKey = crc64Long(key); try { byte[] value = null; synchronized (mCache) { value = mCache.lookup(cacheKey); } if (value == null) return null; if (isSameKey(key, value)) { int offset = key.length; return new ImageData(value, offset); } } catch (IOException ex) { // ignore. } return null; } public void putImageData(String path, int type, byte[] value) { byte[] key = makeKey(path, type); long cacheKey = crc64Long(key); ByteBuffer buffer = ByteBuffer.allocate(key.length + value.length); buffer.put(key); buffer.put(value); synchronized (mCache) { try { mCache.insert(cacheKey, buffer.array()); } catch (IOException ex) { // ignore. } } } public void clear() { CacheManager.clear(mContext); } private static byte[] makeKey(String path, int type) { return getBytes(path + "+" + type); } private static boolean isSameKey(byte[] key, byte[] buffer) { int n = key.length; if (buffer.length < n) { return false; } for (int i = 0; i < n; ++i) { if (key[i] != buffer[i]) { return false; } } return true; } /** * A function thats returns a 64-bit crc for string * * @param in input string * @return a 64-bit crc value */ public static final long crc64Long(String in) { if (in == null || in.length() == 0) { return 0; } return crc64Long(getBytes(in)); } static { // http://bioinf.cs.ucl.ac.uk/downloads/crc64/crc64.c long part; for (int i = 0; i < 256; i++) { part = i; for (int j = 0; j < 8; j++) { long x = ((int) part & 1) != 0 ? POLY64REV : 0; part = (part >> 1) ^ x; } sCrcTable[i] = part; } } public static final long crc64Long(byte[] buffer) { long crc = INITIALCRC; for (int k = 0, n = buffer.length; k < n; ++k) { crc = sCrcTable[(((int) crc) ^ buffer[k]) & 0xff] ^ (crc >> 8); } return crc; } public static byte[] getBytes(String in) { byte[] result = new byte[in.length() * 2]; int output = 0; for (char ch : in.toCharArray()) { result[output++] = (byte) (ch & 0xFF); result[output++] = (byte) (ch >> 8); } return result; } }