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