1d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck/* 2d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck * Copyright (C) 2013 The Android Open Source Project 3d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck * 4d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck * Licensed under the Apache License, Version 2.0 (the "License"); 5d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck * you may not use this file except in compliance with the License. 6d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck * You may obtain a copy of the License at 7d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck * 8d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck * http://www.apache.org/licenses/LICENSE-2.0 9d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck * 10d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck * Unless required by applicable law or agreed to in writing, software 11d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck * distributed under the License is distributed on an "AS IS" BASIS, 12d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck * See the License for the specific language governing permissions and 14d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck * limitations under the License. 15d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck */ 16d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 17d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckpackage com.android.photos.shims; 18d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 19d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport android.content.AsyncTaskLoader; 20d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport android.content.Context; 21d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport android.database.Cursor; 22d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport android.database.MatrixCursor; 23d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport android.graphics.drawable.Drawable; 24f6e687bc30887695374580712092aeb917c84253John Reckimport android.net.Uri; 25d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport android.provider.MediaStore.Files.FileColumns; 26638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reckimport android.util.SparseArray; 27d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 28d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport com.android.gallery3d.data.ContentListener; 29d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport com.android.gallery3d.data.DataManager; 30d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport com.android.gallery3d.data.MediaItem; 31869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescuimport com.android.gallery3d.data.MediaObject; 32d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport com.android.gallery3d.data.MediaSet; 33d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport com.android.gallery3d.data.MediaSet.ItemConsumer; 34d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport com.android.gallery3d.data.MediaSet.SyncListener; 35869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescuimport com.android.gallery3d.data.Path; 36d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport com.android.gallery3d.util.Future; 37d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport com.android.photos.data.PhotoSetLoader; 38d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 39869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescuimport java.util.ArrayList; 40869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu 41d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck/** 42d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck * Returns all MediaItems in a MediaSet, wrapping them in a cursor to appear 43d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck * like a PhotoSetLoader 44d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck */ 45f6e687bc30887695374580712092aeb917c84253John Reckpublic class MediaItemsLoader extends AsyncTaskLoader<Cursor> implements LoaderCompatShim<Cursor> { 46d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 47d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck private static final SyncListener sNullListener = new SyncListener() { 48d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck @Override 49d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck public void onSyncDone(MediaSet mediaSet, int resultCode) { 50d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 51d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck }; 52d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 53638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck private final MediaSet mMediaSet; 54869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu private final DataManager mDataManager; 55d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck private Future<Integer> mSyncTask = null; 56d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck private ContentListener mObserver = new ContentListener() { 57d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck @Override 58d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck public void onContentDirty() { 59d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck onContentChanged(); 60d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 61d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck }; 62638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck private SparseArray<MediaItem> mMediaItems; 63d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 64d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck public MediaItemsLoader(Context context) { 65d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck super(context); 66869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu mDataManager = DataManager.from(context); 67869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu String path = mDataManager.getTopSetPath(DataManager.INCLUDE_ALL); 68869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu mMediaSet = mDataManager.getMediaSet(path); 69d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 70d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 71d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck public MediaItemsLoader(Context context, String parentPath) { 72d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck super(context); 73869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu mDataManager = DataManager.from(getContext()); 74869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu mMediaSet = mDataManager.getMediaSet(parentPath); 75d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 76d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 77d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck @Override 78d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck protected void onStartLoading() { 79d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck super.onStartLoading(); 80d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mMediaSet.addContentListener(mObserver); 81d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mSyncTask = mMediaSet.requestSync(sNullListener); 82d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck forceLoad(); 83d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 84d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 85d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck @Override 86d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck protected boolean onCancelLoad() { 87d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck if (mSyncTask != null) { 88d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mSyncTask.cancel(); 89d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mSyncTask = null; 90d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 91d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck return super.onCancelLoad(); 92d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 93d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 94d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck @Override 95d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck protected void onStopLoading() { 96d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck super.onStopLoading(); 97d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck cancelLoad(); 98d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mMediaSet.removeContentListener(mObserver); 99d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 100d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 101d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck @Override 102d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck protected void onReset() { 103d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck super.onReset(); 104d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck onStopLoading(); 105d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 106d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 107d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck @Override 108d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck public Cursor loadInBackground() { 109705dc819661cb8c8e839a04577b0641bd6caad53John Reck // TODO: This probably doesn't work 110705dc819661cb8c8e839a04577b0641bd6caad53John Reck mMediaSet.reload(); 111d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck final MatrixCursor cursor = new MatrixCursor(PhotoSetLoader.PROJECTION); 112d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck final Object[] row = new Object[PhotoSetLoader.PROJECTION.length]; 113638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck final SparseArray<MediaItem> mediaItems = new SparseArray<MediaItem>(); 114d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mMediaSet.enumerateTotalMediaItems(new ItemConsumer() { 115d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck @Override 116d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck public void consume(int index, MediaItem item) { 117d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck row[PhotoSetLoader.INDEX_ID] = index; 118d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck row[PhotoSetLoader.INDEX_DATA] = item.getContentUri().toString(); 119d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck row[PhotoSetLoader.INDEX_DATE_ADDED] = item.getDateInMs(); 120d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck row[PhotoSetLoader.INDEX_HEIGHT] = item.getHeight(); 121d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck row[PhotoSetLoader.INDEX_WIDTH] = item.getWidth(); 122d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck row[PhotoSetLoader.INDEX_WIDTH] = item.getWidth(); 123d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck int rawMediaType = item.getMediaType(); 124d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck int mappedMediaType = FileColumns.MEDIA_TYPE_NONE; 125d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck if (rawMediaType == MediaItem.MEDIA_TYPE_IMAGE) { 126d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mappedMediaType = FileColumns.MEDIA_TYPE_IMAGE; 127d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } else if (rawMediaType == MediaItem.MEDIA_TYPE_VIDEO) { 128d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mappedMediaType = FileColumns.MEDIA_TYPE_VIDEO; 129d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 130d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck row[PhotoSetLoader.INDEX_MEDIA_TYPE] = mappedMediaType; 131fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu row[PhotoSetLoader.INDEX_SUPPORTED_OPERATIONS] = 132fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu item.getSupportedOperations(); 133d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck cursor.addRow(row); 134638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck mediaItems.append(index, item); 135d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 136d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck }); 137638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck synchronized (mMediaSet) { 138638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck mMediaItems = mediaItems; 139638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck } 140d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck return cursor; 141d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 142d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 143d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck @Override 144d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck public Drawable drawableForItem(Cursor item, Drawable recycle) { 145d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck BitmapJobDrawable drawable = null; 146d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck if (recycle == null || !(recycle instanceof BitmapJobDrawable)) { 147d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck drawable = new BitmapJobDrawable(); 148d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } else { 149d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck drawable = (BitmapJobDrawable) recycle; 150d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 151d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck int index = item.getInt(PhotoSetLoader.INDEX_ID); 152d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck drawable.setMediaItem(mMediaItems.get(index)); 153d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck return drawable; 154d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 155d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 156d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck public static int getThumbnailSize() { 157d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck return MediaItem.getTargetSize(MediaItem.TYPE_MICROTHUMBNAIL); 158d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 159d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 160f6e687bc30887695374580712092aeb917c84253John Reck @Override 161f6e687bc30887695374580712092aeb917c84253John Reck public Uri uriForItem(Cursor item) { 162f6e687bc30887695374580712092aeb917c84253John Reck int index = item.getInt(PhotoSetLoader.INDEX_ID); 163f6e687bc30887695374580712092aeb917c84253John Reck MediaItem mi = mMediaItems.get(index); 164f6e687bc30887695374580712092aeb917c84253John Reck return mi == null ? null : mi.getContentUri(); 165f6e687bc30887695374580712092aeb917c84253John Reck } 166f6e687bc30887695374580712092aeb917c84253John Reck 167869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu @Override 168869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu public ArrayList<Uri> urisForSubItems(Cursor item) { 169869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu return null; 170869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu } 171869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu 172869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu @Override 173869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu public void deleteItemWithPath(Object path) { 174869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu MediaObject o = mDataManager.getMediaObject((Path) path); 175869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu if (o != null) { 176869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu o.delete(); 177869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu } 178869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu } 179869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu 180869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu @Override 181869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu public Object getPathForItem(Cursor item) { 182869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu int index = item.getInt(PhotoSetLoader.INDEX_ID); 183869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu MediaItem mi = mMediaItems.get(index); 184869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu if (mi != null) { 185869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu return mi.getPath(); 186869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu } 187869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu return null; 188869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu } 189869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu 190d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck} 191