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
19f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.common.BlobCache;
20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.common.Utils;
21f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.util.CacheManager;
22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.util.GalleryUtils;
23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.content.Context;
25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.io.IOException;
27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.nio.ByteBuffer;
28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class ImageCacheService {
30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @SuppressWarnings("unused")
31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final String TAG = "ImageCacheService";
32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final String IMAGE_CACHE_FILE = "imgcache";
34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final int IMAGE_CACHE_MAX_ENTRIES = 5000;
35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final int IMAGE_CACHE_MAX_BYTES = 200 * 1024 * 1024;
36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final int IMAGE_CACHE_VERSION = 3;
37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private BlobCache mCache;
39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public ImageCacheService(Context context) {
41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mCache = CacheManager.getCache(context, IMAGE_CACHE_FILE,
42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                IMAGE_CACHE_MAX_ENTRIES, IMAGE_CACHE_MAX_BYTES,
43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                IMAGE_CACHE_VERSION);
44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public static class ImageData {
47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public ImageData(byte[] data, int offset) {
48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mData = data;
49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mOffset = offset;
50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public byte[] mData;
52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public int mOffset;
53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
55f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public ImageData getImageData(Path path, int type) {
56f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        byte[] key = makeKey(path, type);
57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        long cacheKey = Utils.crc64Long(key);
58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        try {
59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            byte[] value = null;
60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            synchronized (mCache) {
61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                value = mCache.lookup(cacheKey);
62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (value == null) return null;
64f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (isSameKey(key, value)) {
65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                int offset = key.length;
66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return new ImageData(value, offset);
67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
68f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } catch (IOException ex) {
69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            // ignore.
70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return null;
72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void putImageData(Path path, int type, byte[] value) {
75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        byte[] key = makeKey(path, type);
76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        long cacheKey = Utils.crc64Long(key);
77f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        ByteBuffer buffer = ByteBuffer.allocate(key.length + value.length);
78f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        buffer.put(key);
79f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        buffer.put(value);
80f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        synchronized (mCache) {
81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            try {
82f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mCache.insert(cacheKey, buffer.array());
83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } catch (IOException ex) {
84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                // ignore.
85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static byte[] makeKey(Path path, int type) {
90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return GalleryUtils.getBytes(path.toString() + "+" + type);
91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static boolean isSameKey(byte[] key, byte[] buffer) {
94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        int n = key.length;
95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (buffer.length < n) {
96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return false;
97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        for (int i = 0; i < n; ++i) {
99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (key[i] != buffer[i]) {
100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return false;
101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return true;
104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin}
106