Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.mms.util;
     18 
     19 import java.io.IOException;
     20 import java.nio.ByteBuffer;
     21 
     22 import android.content.Context;
     23 
     24 public class ImageCacheService {
     25     public static final String IMAGE_CACHE_FILE = "imgcache";
     26     private static final int IMAGE_CACHE_MAX_ENTRIES = 500;
     27     private static final int IMAGE_CACHE_MAX_BYTES = 20 * 1024 * 1024;
     28     private static final int IMAGE_CACHE_VERSION = 3;
     29 
     30     private BlobCache mCache;
     31 
     32     private static long[] sCrcTable = new long[256];
     33     private static final long POLY64REV = 0x95AC9329AC4BC9B5L;
     34     private static final long INITIALCRC = 0xFFFFFFFFFFFFFFFFL;
     35 
     36     private Context mContext;
     37 
     38     public ImageCacheService(Context context) {
     39         mCache = CacheManager.getCache(context, IMAGE_CACHE_FILE,
     40                 IMAGE_CACHE_MAX_ENTRIES, IMAGE_CACHE_MAX_BYTES,
     41                 IMAGE_CACHE_VERSION);
     42         mContext = context;
     43     }
     44 
     45     public static class ImageData {
     46         public ImageData(byte[] data, int offset) {
     47             mData = data;
     48             mOffset = offset;
     49         }
     50         public byte[] mData;
     51         public int mOffset;
     52     }
     53 
     54     public ImageData getImageData(String path, int type) {
     55         byte[] key = makeKey(path, type);
     56         long cacheKey = crc64Long(key);
     57         try {
     58             byte[] value = null;
     59             synchronized (mCache) {
     60                 value = mCache.lookup(cacheKey);
     61             }
     62             if (value == null) return null;
     63             if (isSameKey(key, value)) {
     64                 int offset = key.length;
     65                 return new ImageData(value, offset);
     66             }
     67         } catch (IOException ex) {
     68             // ignore.
     69         }
     70         return null;
     71     }
     72 
     73     public void putImageData(String path, int type, byte[] value) {
     74         byte[] key = makeKey(path, type);
     75         long cacheKey = crc64Long(key);
     76         ByteBuffer buffer = ByteBuffer.allocate(key.length + value.length);
     77         buffer.put(key);
     78         buffer.put(value);
     79         synchronized (mCache) {
     80             try {
     81                 mCache.insert(cacheKey, buffer.array());
     82             } catch (IOException ex) {
     83                 // ignore.
     84             }
     85         }
     86     }
     87 
     88     public void clear() {
     89         CacheManager.clear(mContext);
     90     }
     91 
     92     private static byte[] makeKey(String path, int type) {
     93         return getBytes(path + "+" + type);
     94     }
     95 
     96     private static boolean isSameKey(byte[] key, byte[] buffer) {
     97         int n = key.length;
     98         if (buffer.length < n) {
     99             return false;
    100         }
    101         for (int i = 0; i < n; ++i) {
    102             if (key[i] != buffer[i]) {
    103                 return false;
    104             }
    105         }
    106         return true;
    107     }
    108 
    109     /**
    110      * A function thats returns a 64-bit crc for string
    111      *
    112      * @param in input string
    113      * @return a 64-bit crc value
    114      */
    115     public static final long crc64Long(String in) {
    116         if (in == null || in.length() == 0) {
    117             return 0;
    118         }
    119         return crc64Long(getBytes(in));
    120     }
    121 
    122     static {
    123         // http://bioinf.cs.ucl.ac.uk/downloads/crc64/crc64.c
    124         long part;
    125         for (int i = 0; i < 256; i++) {
    126             part = i;
    127             for (int j = 0; j < 8; j++) {
    128                 long x = ((int) part & 1) != 0 ? POLY64REV : 0;
    129                 part = (part >> 1) ^ x;
    130             }
    131             sCrcTable[i] = part;
    132         }
    133     }
    134 
    135     public static final long crc64Long(byte[] buffer) {
    136         long crc = INITIALCRC;
    137         for (int k = 0, n = buffer.length; k < n; ++k) {
    138             crc = sCrcTable[(((int) crc) ^ buffer[k]) & 0xff] ^ (crc >> 8);
    139         }
    140         return crc;
    141     }
    142 
    143     public static byte[] getBytes(String in) {
    144         byte[] result = new byte[in.length() * 2];
    145         int output = 0;
    146         for (char ch : in.toCharArray()) {
    147             result[output++] = (byte) (ch & 0xFF);
    148             result[output++] = (byte) (ch >> 8);
    149         }
    150         return result;
    151     }
    152 
    153 }
    154