1403e82bd940231d26041bff179da98eabaddc60cRay Chen/* 24177add422a041ea9f1007c05ff42361bf529d52Chih-Chung Chang * Copyright (C) 2009 The Android Open Source Project 3403e82bd940231d26041bff179da98eabaddc60cRay Chen * 4403e82bd940231d26041bff179da98eabaddc60cRay Chen * Licensed under the Apache License, Version 2.0 (the "License"); 5403e82bd940231d26041bff179da98eabaddc60cRay Chen * you may not use this file except in compliance with the License. 6403e82bd940231d26041bff179da98eabaddc60cRay Chen * You may obtain a copy of the License at 7403e82bd940231d26041bff179da98eabaddc60cRay Chen * 8403e82bd940231d26041bff179da98eabaddc60cRay Chen * http://www.apache.org/licenses/LICENSE-2.0 9403e82bd940231d26041bff179da98eabaddc60cRay Chen * 10403e82bd940231d26041bff179da98eabaddc60cRay Chen * Unless required by applicable law or agreed to in writing, software 11403e82bd940231d26041bff179da98eabaddc60cRay Chen * distributed under the License is distributed on an "AS IS" BASIS, 12403e82bd940231d26041bff179da98eabaddc60cRay Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13403e82bd940231d26041bff179da98eabaddc60cRay Chen * See the License for the specific language governing permissions and 14403e82bd940231d26041bff179da98eabaddc60cRay Chen * limitations under the License. 15403e82bd940231d26041bff179da98eabaddc60cRay Chen */ 16403e82bd940231d26041bff179da98eabaddc60cRay Chen 17403e82bd940231d26041bff179da98eabaddc60cRay Chenpackage com.android.camera; 18403e82bd940231d26041bff179da98eabaddc60cRay Chen 1928f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chenimport android.content.ContentResolver; 20403e82bd940231d26041bff179da98eabaddc60cRay Chenimport android.graphics.Bitmap; 21403e82bd940231d26041bff179da98eabaddc60cRay Chenimport android.graphics.BitmapFactory; 2228f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chenimport android.provider.MediaStore.Images; 2328f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chenimport android.provider.MediaStore.Video; 24403e82bd940231d26041bff179da98eabaddc60cRay Chenimport android.util.Log; 25403e82bd940231d26041bff179da98eabaddc60cRay Chen 26403e82bd940231d26041bff179da98eabaddc60cRay Chenimport java.io.FileDescriptor; 27403e82bd940231d26041bff179da98eabaddc60cRay Chenimport java.util.WeakHashMap; 28403e82bd940231d26041bff179da98eabaddc60cRay Chen 29403e82bd940231d26041bff179da98eabaddc60cRay Chen/** 30271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * Provides utilities to decode bitmap, get thumbnail, and cancel the 31271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * operations. 32937fc48b37fafe3ffc8f4b52bd9a171bbb4d3a37Owen Lin * 33271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * <p>The function {@link #decodeFileDescriptor(FileDescriptor, 34271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * BitmapFactory.Options)} is used to decode a bitmap. During decoding another 35271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * thread can cancel it using the function {@link #cancelThreadDecoding(Thread, 36271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * ContentResolver)} specifying the {@code Thread} which is in decoding. 37403e82bd940231d26041bff179da98eabaddc60cRay Chen * 38271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * <p>{@code cancelThreadDecoding(Thread,ContentResolver)} is sticky until 39271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * {@code allowThreadDecoding(Thread) } is called. 40403e82bd940231d26041bff179da98eabaddc60cRay Chen */ 41403e82bd940231d26041bff179da98eabaddc60cRay Chenpublic class BitmapManager { 42403e82bd940231d26041bff179da98eabaddc60cRay Chen private static final String TAG = "BitmapManager"; 434177add422a041ea9f1007c05ff42361bf529d52Chih-Chung Chang private static enum State {CANCEL, ALLOW} 44403e82bd940231d26041bff179da98eabaddc60cRay Chen private static class ThreadStatus { 454177add422a041ea9f1007c05ff42361bf529d52Chih-Chung Chang public State mState = State.ALLOW; 464177add422a041ea9f1007c05ff42361bf529d52Chih-Chung Chang public BitmapFactory.Options mOptions; 4782544b4564c079ece1a9065d19add36b2635bb8fOwen Lin 48937fc48b37fafe3ffc8f4b52bd9a171bbb4d3a37Owen Lin @Override 49403e82bd940231d26041bff179da98eabaddc60cRay Chen public String toString() { 50403e82bd940231d26041bff179da98eabaddc60cRay Chen String s; 514177add422a041ea9f1007c05ff42361bf529d52Chih-Chung Chang if (mState == State.CANCEL) { 52403e82bd940231d26041bff179da98eabaddc60cRay Chen s = "Cancel"; 534177add422a041ea9f1007c05ff42361bf529d52Chih-Chung Chang } else if (mState == State.ALLOW) { 544177add422a041ea9f1007c05ff42361bf529d52Chih-Chung Chang s = "Allow"; 55937fc48b37fafe3ffc8f4b52bd9a171bbb4d3a37Owen Lin } else { 564177add422a041ea9f1007c05ff42361bf529d52Chih-Chung Chang s = "?"; 57403e82bd940231d26041bff179da98eabaddc60cRay Chen } 584177add422a041ea9f1007c05ff42361bf529d52Chih-Chung Chang s = "thread state = " + s + ", options = " + mOptions; 59403e82bd940231d26041bff179da98eabaddc60cRay Chen return s; 60403e82bd940231d26041bff179da98eabaddc60cRay Chen } 61403e82bd940231d26041bff179da98eabaddc60cRay Chen } 62896182a590fc1bbed5dfb78a74e9a71b30d8f9aaRay Chen 63d30b5877fbdedcebc0af5cccffddccfe9b11cb0bOwen Lin private final WeakHashMap<Thread, ThreadStatus> mThreadStatus = 64403e82bd940231d26041bff179da98eabaddc60cRay Chen new WeakHashMap<Thread, ThreadStatus>(); 65896182a590fc1bbed5dfb78a74e9a71b30d8f9aaRay Chen 66896182a590fc1bbed5dfb78a74e9a71b30d8f9aaRay Chen private static BitmapManager sManager = null; 67403e82bd940231d26041bff179da98eabaddc60cRay Chen 68403e82bd940231d26041bff179da98eabaddc60cRay Chen private BitmapManager() { 69403e82bd940231d26041bff179da98eabaddc60cRay Chen } 70937fc48b37fafe3ffc8f4b52bd9a171bbb4d3a37Owen Lin 71403e82bd940231d26041bff179da98eabaddc60cRay Chen /** 72403e82bd940231d26041bff179da98eabaddc60cRay Chen * Get thread status and create one if specified. 73403e82bd940231d26041bff179da98eabaddc60cRay Chen */ 744177add422a041ea9f1007c05ff42361bf529d52Chih-Chung Chang private synchronized ThreadStatus getOrCreateThreadStatus(Thread t) { 75403e82bd940231d26041bff179da98eabaddc60cRay Chen ThreadStatus status = mThreadStatus.get(t); 764177add422a041ea9f1007c05ff42361bf529d52Chih-Chung Chang if (status == null) { 77403e82bd940231d26041bff179da98eabaddc60cRay Chen status = new ThreadStatus(); 78403e82bd940231d26041bff179da98eabaddc60cRay Chen mThreadStatus.put(t, status); 79403e82bd940231d26041bff179da98eabaddc60cRay Chen } 80403e82bd940231d26041bff179da98eabaddc60cRay Chen return status; 81403e82bd940231d26041bff179da98eabaddc60cRay Chen } 82403e82bd940231d26041bff179da98eabaddc60cRay Chen 83403e82bd940231d26041bff179da98eabaddc60cRay Chen public synchronized boolean canThreadDecoding(Thread t) { 84403e82bd940231d26041bff179da98eabaddc60cRay Chen ThreadStatus status = mThreadStatus.get(t); 85403e82bd940231d26041bff179da98eabaddc60cRay Chen if (status == null) { 8627576d1b5abbddfc3da7add5a9b9f602d9e9e954Ray Chen // allow decoding by default 874177add422a041ea9f1007c05ff42361bf529d52Chih-Chung Chang return true; 88403e82bd940231d26041bff179da98eabaddc60cRay Chen } 89937fc48b37fafe3ffc8f4b52bd9a171bbb4d3a37Owen Lin 904177add422a041ea9f1007c05ff42361bf529d52Chih-Chung Chang boolean result = (status.mState != State.CANCEL); 91403e82bd940231d26041bff179da98eabaddc60cRay Chen return result; 92403e82bd940231d26041bff179da98eabaddc60cRay Chen } 93937fc48b37fafe3ffc8f4b52bd9a171bbb4d3a37Owen Lin 94271b3095b9f763421c0547109da9de774795072dChih-Chung Chang /** 95271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * Gets the thumbnail of the given ID of the original image. 96271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * 97271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * <p> This method wraps around @{code getThumbnail} in {@code 98271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * android.provider.MediaStore}. It provides the ability to cancel it. 99271b3095b9f763421c0547109da9de774795072dChih-Chung Chang */ 10028f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen public Bitmap getThumbnail(ContentResolver cr, long origId, int kind, 10128f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen BitmapFactory.Options options, boolean isVideo) { 10228f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen Thread t = Thread.currentThread(); 10328f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen ThreadStatus status = getOrCreateThreadStatus(t); 10428f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen 10528f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen if (!canThreadDecoding(t)) { 10628f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen Log.d(TAG, "Thread " + t + " is not allowed to decode."); 10728f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen return null; 10828f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen } 10928f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen 11028f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen try { 11128f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen if (isVideo) { 11228f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen return Video.Thumbnails.getThumbnail(cr, origId, t.getId(), 11328f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen kind, null); 11428f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen } else { 11528f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen return Images.Thumbnails.getThumbnail(cr, origId, t.getId(), 11628f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen kind, null); 11728f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen } 11828f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen } finally { 11928f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen synchronized (status) { 12028f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen status.notifyAll(); 12128f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen } 12228f3595372cfbff1a2e5e83bf59d8dff76e14215Ray Chen } 123403e82bd940231d26041bff179da98eabaddc60cRay Chen } 124937fc48b37fafe3ffc8f4b52bd9a171bbb4d3a37Owen Lin 125896182a590fc1bbed5dfb78a74e9a71b30d8f9aaRay Chen public static synchronized BitmapManager instance() { 126896182a590fc1bbed5dfb78a74e9a71b30d8f9aaRay Chen if (sManager == null) { 127896182a590fc1bbed5dfb78a74e9a71b30d8f9aaRay Chen sManager = new BitmapManager(); 128896182a590fc1bbed5dfb78a74e9a71b30d8f9aaRay Chen } 129896182a590fc1bbed5dfb78a74e9a71b30d8f9aaRay Chen return sManager; 130896182a590fc1bbed5dfb78a74e9a71b30d8f9aaRay Chen } 131403e82bd940231d26041bff179da98eabaddc60cRay Chen} 132