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.app.GalleryApp; 20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.common.Utils; 21f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaSet.ItemConsumer; 22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaSource.PathId; 23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.picasasource.PicasaSource; 24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.database.ContentObserver; 26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.net.Uri; 27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.os.Handler; 28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.ArrayList; 30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.Comparator; 31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.HashMap; 32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.LinkedHashMap; 33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.Map.Entry; 34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.WeakHashMap; 35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// DataManager manages all media sets and media items in the system. 37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// 38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// Each MediaSet and MediaItem has a unique 64 bits id. The most significant 39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// 32 bits represents its parent, and the least significant 32 bits represents 40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// the self id. For MediaSet the self id is is globally unique, but for 41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// MediaItem it's unique only relative to its parent. 42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// 43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// To make sure the id is the same when the MediaSet is re-created, a child key 44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// is provided to obtainSetId() to make sure the same self id will be used as 45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// when the parent and key are the same. A sequence of child keys is called a 46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// path. And it's used to identify a specific media set even if the process is 47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// killed and re-created, so child keys should be stable identifiers. 48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class DataManager { 50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final int INCLUDE_IMAGE = 1; 51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final int INCLUDE_VIDEO = 2; 52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final int INCLUDE_ALL = INCLUDE_IMAGE | INCLUDE_VIDEO; 53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final int INCLUDE_LOCAL_ONLY = 4; 54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final int INCLUDE_LOCAL_IMAGE_ONLY = 55f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin INCLUDE_LOCAL_ONLY | INCLUDE_IMAGE; 56f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final int INCLUDE_LOCAL_VIDEO_ONLY = 57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin INCLUDE_LOCAL_ONLY | INCLUDE_VIDEO; 58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final int INCLUDE_LOCAL_ALL_ONLY = 59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin INCLUDE_LOCAL_ONLY | INCLUDE_IMAGE | INCLUDE_VIDEO; 60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Any one who would like to access data should require this lock 62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // to prevent concurrency issue. 63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final Object LOCK = new Object(); 64f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TAG = "DataManager"; 66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // This is the path for the media set seen by the user at top level. 68f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TOP_SET_PATH = 69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin "/combo/{/mtp,/local/all,/picasa/all}"; 70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TOP_IMAGE_SET_PATH = 71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin "/combo/{/mtp,/local/image,/picasa/image}"; 72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TOP_VIDEO_SET_PATH = 73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin "/combo/{/local/video,/picasa/video}"; 74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TOP_LOCAL_SET_PATH = 75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin "/local/all"; 76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TOP_LOCAL_IMAGE_SET_PATH = 77f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin "/local/image"; 78f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TOP_LOCAL_VIDEO_SET_PATH = 79f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin "/local/video"; 80f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final Comparator<MediaItem> sDateTakenComparator = 82f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin new DateTakenComparator(); 83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static class DateTakenComparator implements Comparator<MediaItem> { 85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int compare(MediaItem item1, MediaItem item2) { 86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return -Utils.compare(item1.getDateInMs(), item2.getDateInMs()); 87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private final Handler mDefaultMainHandler; 91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private GalleryApp mApplication; 93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int mActiveCount = 0; 94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private HashMap<Uri, NotifyBroker> mNotifierMap = 96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin new HashMap<Uri, NotifyBroker>(); 97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private HashMap<String, MediaSource> mSourceMap = 100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin new LinkedHashMap<String, MediaSource>(); 101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public DataManager(GalleryApp application) { 103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mApplication = application; 104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mDefaultMainHandler = new Handler(application.getMainLooper()); 105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public synchronized void initializeSourceMap() { 108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (!mSourceMap.isEmpty()) return; 109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // the order matters, the UriSource must come last 111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin addSource(new LocalSource(mApplication)); 112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin addSource(new PicasaSource(mApplication)); 113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin addSource(new MtpSource(mApplication)); 114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin addSource(new ComboSource(mApplication)); 115f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin addSource(new ClusterSource(mApplication)); 116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin addSource(new FilterSource(mApplication)); 117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin addSource(new UriSource(mApplication)); 118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mActiveCount > 0) { 120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (MediaSource source : mSourceMap.values()) { 121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin source.resume(); 122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 124f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 125f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public String getTopSetPath(int typeBits) { 127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin switch (typeBits) { 129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case INCLUDE_IMAGE: return TOP_IMAGE_SET_PATH; 130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case INCLUDE_VIDEO: return TOP_VIDEO_SET_PATH; 131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case INCLUDE_ALL: return TOP_SET_PATH; 132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case INCLUDE_LOCAL_IMAGE_ONLY: return TOP_LOCAL_IMAGE_SET_PATH; 133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case INCLUDE_LOCAL_VIDEO_ONLY: return TOP_LOCAL_VIDEO_SET_PATH; 134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case INCLUDE_LOCAL_ALL_ONLY: return TOP_LOCAL_SET_PATH; 135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin default: throw new IllegalArgumentException(); 136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 137f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // open for debug 140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin void addSource(MediaSource source) { 141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mSourceMap.put(source.getPrefix(), source); 142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public MediaObject peekMediaObject(Path path) { 145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return path.getObject(); 146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public MediaSet peekMediaSet(Path path) { 149f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return (MediaSet) path.getObject(); 150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public MediaObject getMediaObject(Path path) { 153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin MediaObject obj = path.getObject(); 154f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (obj != null) return obj; 155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin MediaSource source = mSourceMap.get(path.getPrefix()); 157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (source == null) { 158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.w(TAG, "cannot find media source for path: " + path); 159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin MediaObject object = source.createMediaObject(path); 163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (object == null) { 164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.w(TAG, "cannot create media object: " + path); 165f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 166f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return object; 167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 168f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 169f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public MediaObject getMediaObject(String s) { 170f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return getMediaObject(Path.fromString(s)); 171f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 172f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 173f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public MediaSet getMediaSet(Path path) { 174f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return (MediaSet) getMediaObject(path); 175f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 176f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 177f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public MediaSet getMediaSet(String s) { 178f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return (MediaSet) getMediaObject(s); 179f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 180f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 181f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public MediaSet[] getMediaSetsFromString(String segment) { 182f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String[] seq = Path.splitSequence(segment); 183f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int n = seq.length; 184f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin MediaSet[] sets = new MediaSet[n]; 185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = 0; i < n; i++) { 186f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin sets[i] = getMediaSet(seq[i]); 187f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 188f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return sets; 189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Maps a list of Paths to MediaItems, and invoke consumer.consume() 192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // for each MediaItem (may not be in the same order as the input list). 193f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // An index number is also passed to consumer.consume() to identify 194f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // the original position in the input list of the corresponding Path (plus 195f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // startIndex). 196f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void mapMediaItems(ArrayList<Path> list, ItemConsumer consumer, 197f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int startIndex) { 198f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin HashMap<String, ArrayList<PathId>> map = 199f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin new HashMap<String, ArrayList<PathId>>(); 200f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 201f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Group the path by the prefix. 202f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int n = list.size(); 203f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = 0; i < n; i++) { 204f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Path path = list.get(i); 205f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String prefix = path.getPrefix(); 206f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ArrayList<PathId> group = map.get(prefix); 207f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (group == null) { 208f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin group = new ArrayList<PathId>(); 209f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin map.put(prefix, group); 210f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 211f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin group.add(new PathId(path, i + startIndex)); 212f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 213f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 214f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // For each group, ask the corresponding media source to map it. 215f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (Entry<String, ArrayList<PathId>> entry : map.entrySet()) { 216f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String prefix = entry.getKey(); 217f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin MediaSource source = mSourceMap.get(prefix); 218f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin source.mapMediaItems(entry.getValue(), consumer); 219f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 220f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 221f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 222f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // The following methods forward the request to the proper object. 223f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int getSupportedOperations(Path path) { 224f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return getMediaObject(path).getSupportedOperations(); 225f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 226f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 227f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void delete(Path path) { 228f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin getMediaObject(path).delete(); 229f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 230f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 231f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void rotate(Path path, int degrees) { 232f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin getMediaObject(path).rotate(degrees); 233f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 234f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 235f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public Uri getContentUri(Path path) { 236f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return getMediaObject(path).getContentUri(); 237f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 238f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 239f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int getMediaType(Path path) { 240f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return getMediaObject(path).getMediaType(); 241f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 242f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 243f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public MediaDetails getDetails(Path path) { 244f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return getMediaObject(path).getDetails(); 245f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 246f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 247f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void cache(Path path, int flag) { 248f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin getMediaObject(path).cache(flag); 249f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 250f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 251f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public Path findPathByUri(Uri uri) { 252f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (uri == null) return null; 253f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (MediaSource source : mSourceMap.values()) { 254f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Path path = source.findPathByUri(uri); 255f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (path != null) return path; 256f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 257f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 258f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 259f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 260f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public Path getDefaultSetOf(Path item) { 261f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin MediaSource source = mSourceMap.get(item.getPrefix()); 262f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return source == null ? null : source.getDefaultSetOf(item); 263f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 264f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 265f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Returns number of bytes used by cached pictures currently downloaded. 266f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public long getTotalUsedCacheSize() { 267f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin long sum = 0; 268f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (MediaSource source : mSourceMap.values()) { 269f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin sum += source.getTotalUsedCacheSize(); 270f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 271f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return sum; 272f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 273f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 274f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Returns number of bytes used by cached pictures if all pending 275f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // downloads and removals are completed. 276f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public long getTotalTargetCacheSize() { 277f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin long sum = 0; 278f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (MediaSource source : mSourceMap.values()) { 279f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin sum += source.getTotalTargetCacheSize(); 280f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 281f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return sum; 282f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 283f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 284f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void registerChangeNotifier(Uri uri, ChangeNotifier notifier) { 285f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin NotifyBroker broker = null; 286f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin synchronized (mNotifierMap) { 287f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin broker = mNotifierMap.get(uri); 288f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (broker == null) { 289f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin broker = new NotifyBroker(mDefaultMainHandler); 290f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mApplication.getContentResolver() 291f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin .registerContentObserver(uri, true, broker); 292f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mNotifierMap.put(uri, broker); 293f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 294f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 295f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin broker.registerNotifier(notifier); 296f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 297f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 298f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void resume() { 299f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (++mActiveCount == 1) { 300f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (MediaSource source : mSourceMap.values()) { 301f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin source.resume(); 302f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 303f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 304f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 305f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 306f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void pause() { 307f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (--mActiveCount == 0) { 308f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (MediaSource source : mSourceMap.values()) { 309f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin source.pause(); 310f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 311f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 312f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 313f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 314f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static class NotifyBroker extends ContentObserver { 315f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private WeakHashMap<ChangeNotifier, Object> mNotifiers = 316f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin new WeakHashMap<ChangeNotifier, Object>(); 317f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 318f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public NotifyBroker(Handler handler) { 319f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin super(handler); 320f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 321f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 322f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public synchronized void registerNotifier(ChangeNotifier notifier) { 323f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mNotifiers.put(notifier, null); 324f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 325f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 326f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 327f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public synchronized void onChange(boolean selfChange) { 328f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for(ChangeNotifier notifier : mNotifiers.keySet()) { 329f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin notifier.onChange(selfChange); 330f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 331f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 332f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 333f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin} 334