1b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen/*
2b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen * Copyright (C) 2009 The Android Open Source Project
3b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen *
4b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen * Licensed under the Apache License, Version 2.0 (the "License");
5b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen * you may not use this file except in compliance with the License.
6b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen * You may obtain a copy of the License at
7b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen *
8b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen *      http://www.apache.org/licenses/LICENSE-2.0
9b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen *
10b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen * Unless required by applicable law or agreed to in writing, software
11b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen * distributed under the License is distributed on an "AS IS" BASIS,
12b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen * See the License for the specific language governing permissions and
14b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen * limitations under the License.
15b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen */
16b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen
17b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chenpackage com.android.providers.media;
18b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen
191373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chenimport java.io.ByteArrayOutputStream;
20b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chenimport java.io.IOException;
217a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chenimport java.io.OutputStream;
22b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chenimport java.util.Comparator;
23b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chenimport java.util.Random;
24b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen
25b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chenimport android.content.ContentResolver;
26b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chenimport android.content.ContentUris;
27b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chenimport android.content.ContentValues;
28b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chenimport android.database.Cursor;
29b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chenimport android.graphics.Bitmap;
30b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chenimport android.graphics.BitmapFactory;
31b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chenimport android.media.MiniThumbFile;
32ee8598a7e70b10fbcb1c43ade5cf838c6172fe57Ray Chenimport android.media.ThumbnailUtils;
33b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chenimport android.net.Uri;
3420434e032e498b716f87cce2f23dd646819218bfRay Chenimport android.os.Binder;
351373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chenimport android.os.ParcelFileDescriptor;
36b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chenimport android.provider.BaseColumns;
3701a6f2f96c5b483f5281f6d3066380a129c06021Ray Chenimport android.provider.MediaStore.Images;
387a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chenimport android.provider.MediaStore.Video;
391373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chenimport android.provider.MediaStore.MediaColumns;
40b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chenimport android.provider.MediaStore.Images.ImageColumns;
41b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chenimport android.util.Log;
42b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen
43b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen/**
44b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen * Instances of this class are created and put in a queue to be executed sequentially to see if
45b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen * it needs to (re)generate the thumbnails.
46b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen */
47b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chenclass MediaThumbRequest {
48b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen    private static final String TAG = "MediaThumbRequest";
49b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen    static final int PRIORITY_LOW = 20;
50b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen    static final int PRIORITY_NORMAL = 10;
51b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen    static final int PRIORITY_HIGH = 5;
5220434e032e498b716f87cce2f23dd646819218bfRay Chen    static final int PRIORITY_CRITICAL = 0;
5320434e032e498b716f87cce2f23dd646819218bfRay Chen    static enum State {WAIT, DONE, CANCEL}
54b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen    private static final String[] THUMB_PROJECTION = new String[] {
55b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen        BaseColumns._ID // 0
56b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen    };
57b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen
58b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen    ContentResolver mCr;
59b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen    String mPath;
60b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen    long mRequestTime = System.currentTimeMillis();
6120434e032e498b716f87cce2f23dd646819218bfRay Chen    int mCallingPid = Binder.getCallingPid();
62e7219b83c17d75151746d6cad1b61d447910ae92Ray Chen    long mGroupId;
63b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen    int mPriority;
64b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen    Uri mUri;
657a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen    Uri mThumbUri;
667a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen    String mOrigColumnName;
67b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen    boolean mIsVideo;
68b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen    long mOrigId;
6920434e032e498b716f87cce2f23dd646819218bfRay Chen    State mState = State.WAIT;
70b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen    long mMagic;
71b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen
72bf86108d222677067674c0947e8dc2b2bc9cadc2John Eckerdal    private static final Random sRandom = new Random();
73b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen
74b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen    static Comparator<MediaThumbRequest> getComparator() {
75b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen        return new Comparator<MediaThumbRequest>() {
76b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen            public int compare(MediaThumbRequest r1, MediaThumbRequest r2) {
77b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen                if (r1.mPriority != r2.mPriority) {
78b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen                    return r1.mPriority < r2.mPriority ? -1 : 1;
79b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen                }
80b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen                return r1.mRequestTime == r2.mRequestTime ? 0 :
81b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen                        r1.mRequestTime < r2.mRequestTime ? -1 : 1;
82b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen            }
83b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen        };
84b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen    }
85b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen
869299727714ad25618a1a77eeca7f1e9c72f1e510Ray Chen    MediaThumbRequest(ContentResolver cr, String path, Uri uri, int priority, long magic) {
87b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen        mCr = cr;
88b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen        mPath = path;
894d96d72ea42c2ec41a891f65623270473ae8eebdRay Chen        mPriority = priority;
909299727714ad25618a1a77eeca7f1e9c72f1e510Ray Chen        mMagic = magic;
91b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen        mUri = uri;
92b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen        mIsVideo = "video".equals(uri.getPathSegments().get(1));
93b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen        mOrigId = ContentUris.parseId(uri);
947a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen        mThumbUri = mIsVideo
957a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                ? Video.Thumbnails.EXTERNAL_CONTENT_URI
967a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                : Images.Thumbnails.EXTERNAL_CONTENT_URI;
977a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen        mOrigColumnName = mIsVideo
987a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                ? Video.Thumbnails.VIDEO_ID
997a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                : Images.Thumbnails.IMAGE_ID;
100e7219b83c17d75151746d6cad1b61d447910ae92Ray Chen        // Only requests from Thumbnail API has this group_id parameter. In other cases,
101e7219b83c17d75151746d6cad1b61d447910ae92Ray Chen        // mGroupId will always be zero and can't be canceled due to pid mismatch.
102e7219b83c17d75151746d6cad1b61d447910ae92Ray Chen        String groupIdParam = uri.getQueryParameter("group_id");
103e7219b83c17d75151746d6cad1b61d447910ae92Ray Chen        if (groupIdParam != null) {
104e7219b83c17d75151746d6cad1b61d447910ae92Ray Chen            mGroupId = Long.parseLong(groupIdParam);
105e7219b83c17d75151746d6cad1b61d447910ae92Ray Chen        }
106b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen    }
107b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen
10854cb8ab64f5cbd33257a926a6a2b588b3106b115Ray Chen    Uri updateDatabase(Bitmap thumbnail) {
1097a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen        Cursor c = mCr.query(mThumbUri, THUMB_PROJECTION,
1107a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                mOrigColumnName+ " = " + mOrigId, null, null);
1117a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen        if (c == null) return null;
1127a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen        try {
1137a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen            if (c.moveToFirst()) {
1147a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                return ContentUris.withAppendedId(mThumbUri, c.getLong(0));
1157a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen            }
1167a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen        } finally {
1177a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen            if (c != null) c.close();
1187a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen        }
1197a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen
12054cb8ab64f5cbd33257a926a6a2b588b3106b115Ray Chen        ContentValues values = new ContentValues(4);
1217a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen        values.put(Images.Thumbnails.KIND, Images.Thumbnails.MINI_KIND);
1227a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen        values.put(mOrigColumnName, mOrigId);
12354cb8ab64f5cbd33257a926a6a2b588b3106b115Ray Chen        values.put(Images.Thumbnails.WIDTH, thumbnail.getWidth());
12454cb8ab64f5cbd33257a926a6a2b588b3106b115Ray Chen        values.put(Images.Thumbnails.HEIGHT, thumbnail.getHeight());
1257a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen        try {
1267a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen            return mCr.insert(mThumbUri, values);
1277a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen        } catch (Exception ex) {
1287a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen            Log.w(TAG, ex);
1297a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen            return null;
1307a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen        }
1317a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen    }
1327a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen
133b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen    /**
134b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen     * Check if the corresponding thumbnail and mini-thumb have been created
135b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen     * for the given uri. This method creates both of them if they do not
136b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen     * exist yet or have been changed since last check. After thumbnails are
137b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen     * created, MINI_KIND thumbnail is stored in JPEG file and MICRO_KIND
138b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen     * thumbnail is stored in a random access file (MiniThumbFile).
139b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen     *
140b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen     * @throws IOException
141b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen     */
142b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen    void execute() throws IOException {
143b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen        MiniThumbFile miniThumbFile = MiniThumbFile.instance(mUri);
144b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen        long magic = mMagic;
145b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen        if (magic != 0) {
146b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen            long fileMagic = miniThumbFile.getMagic(mOrigId);
147b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen            if (fileMagic == magic) {
1487a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                Cursor c = null;
1491373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen                ParcelFileDescriptor pfd = null;
1501373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen                try {
1517a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                    c = mCr.query(mThumbUri, THUMB_PROJECTION,
1527a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                            mOrigColumnName + " = " + mOrigId, null, null);
1531373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen                    if (c != null && c.moveToFirst()) {
1541373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen                        pfd = mCr.openFileDescriptor(
1557a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                                mThumbUri.buildUpon().appendPath(c.getString(0)).build(), "r");
1561373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen                    }
157cf85fbdb58b153eaa1876449dba0bff5ae66bea5Ray Chen                } catch (IOException ex) {
158cf85fbdb58b153eaa1876449dba0bff5ae66bea5Ray Chen                    // MINI_THUMBNAIL not exists, ignore the exception and generate one.
1591373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen                } finally {
1601373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen                    if (c != null) c.close();
1611373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen                    if (pfd != null) {
1621373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen                        pfd.close();
1631373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen                        return;
1641373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen                    }
1651373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen                }
166b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen            }
167b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen        }
168b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen
169b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen        // If we can't retrieve the thumbnail, first check if there is one
170b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen        // embedded in the EXIF data. If not, or it's not big enough,
171b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen        // decompress the full size image.
172b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen        Bitmap bitmap = null;
173b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen
174b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen        if (mPath != null) {
175b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen            if (mIsVideo) {
1767a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                bitmap = ThumbnailUtils.createVideoThumbnail(mPath,
1777a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                        Video.Thumbnails.MINI_KIND);
178b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen            } else {
1797a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                bitmap = ThumbnailUtils.createImageThumbnail(mPath,
1807a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                        Images.Thumbnails.MINI_KIND);
1817a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen            }
1827a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen            if (bitmap == null) {
1837a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                Log.w(TAG, "Can't create mini thumbnail for " + mPath);
1847a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                return;
1857a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen            }
1867a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen
18754cb8ab64f5cbd33257a926a6a2b588b3106b115Ray Chen            Uri uri = updateDatabase(bitmap);
1887a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen            if (uri != null) {
1897a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                OutputStream thumbOut = mCr.openOutputStream(uri);
1907a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                bitmap.compress(Bitmap.CompressFormat.JPEG, 85, thumbOut);
1917a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                thumbOut.close();
192b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen            }
193b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen        }
194b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen
1957a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen        bitmap = ThumbnailUtils.extractThumbnail(bitmap,
1967a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                        ThumbnailUtils.TARGET_SIZE_MICRO_THUMBNAIL,
1977a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                        ThumbnailUtils.TARGET_SIZE_MICRO_THUMBNAIL,
1987a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                        ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
199b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen
200b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen        if (bitmap != null) {
2011373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen            ByteArrayOutputStream miniOutStream = new ByteArrayOutputStream();
2021373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen            bitmap.compress(Bitmap.CompressFormat.JPEG, 75, miniOutStream);
2031373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen            bitmap.recycle();
2041373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen            byte [] data = null;
2051373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen
2061373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen            try {
2071373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen                miniOutStream.close();
2081373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen                data = miniOutStream.toByteArray();
2091373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen            } catch (java.io.IOException ex) {
2101373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen                Log.e(TAG, "got exception ex " + ex);
2111373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen            }
212b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen
213b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen            // We may consider retire this proprietary format, after all it's size is only
214b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen            // 128 x 128 at most, which is still reasonable to be stored in database.
215b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen            // Gallery application can use the MINI_THUMB_MAGIC value to determine if it's
216b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen            // time to query and fetch by using Cursor.getBlob
2171373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen            if (data != null) {
2187a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                // make a new magic number since things are out of sync
2197a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                do {
220bf86108d222677067674c0947e8dc2b2bc9cadc2John Eckerdal                    magic = sRandom.nextLong();
2217a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen                } while (magic == 0);
2227a7691e1208a6d39d54de9b520a1bbf1c3c911f2Ray Chen
2231373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen                miniThumbFile.saveMiniThumbToFile(data, mOrigId, magic);
2241373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen                ContentValues values = new ContentValues();
2251373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen                // both video/images table use the same column name "mini_thumb_magic"
2261373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen                values.put(ImageColumns.MINI_THUMB_MAGIC, magic);
2271373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen                mCr.update(mUri, values, null, null);
2281373bc6df8faed91034ccbd785474cdc84bc1fd6Ray Chen            }
229b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen        } else {
230b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen            Log.w(TAG, "can't create bitmap for thumbnail.");
231b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen        }
232b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen    }
233b386112a8c5e5bd2d3d77e5398bea26b2172dffcRay Chen}
234