15f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck/* 25f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * Copyright (C) 2013 The Android Open Source Project 35f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * 45f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * Licensed under the Apache License, Version 2.0 (the "License"); 55f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * you may not use this file except in compliance with the License. 65f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * You may obtain a copy of the License at 75f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * 85f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * http://www.apache.org/licenses/LICENSE-2.0 95f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * 105f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * Unless required by applicable law or agreed to in writing, software 115f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * distributed under the License is distributed on an "AS IS" BASIS, 125f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * See the License for the specific language governing permissions and 145f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * limitations under the License. 155f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck */ 165f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck 17d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckpackage com.android.photos.shims; 185f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck 195f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reckimport android.content.AsyncTaskLoader; 205f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reckimport android.content.Context; 218c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescuimport android.database.Cursor; 228c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescuimport android.database.MatrixCursor; 238c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescuimport android.graphics.drawable.Drawable; 24f6e687bc30887695374580712092aeb917c84253John Reckimport android.net.Uri; 255f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck 265f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reckimport com.android.gallery3d.data.ContentListener; 275f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reckimport com.android.gallery3d.data.DataManager; 288c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescuimport com.android.gallery3d.data.MediaItem; 29869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescuimport com.android.gallery3d.data.MediaObject; 305f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reckimport com.android.gallery3d.data.MediaSet; 31869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescuimport com.android.gallery3d.data.Path; 325f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reckimport com.android.gallery3d.data.MediaSet.SyncListener; 335f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reckimport com.android.gallery3d.util.Future; 348c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescuimport com.android.photos.data.AlbumSetLoader; 358c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu 368c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescuimport java.util.ArrayList; 375f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck 385f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck/** 398c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu * Returns all MediaSets in a MediaSet, wrapping them in a cursor to appear 408c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu * like a AlbumSetLoader. 415f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck */ 42f6e687bc30887695374580712092aeb917c84253John Reckpublic class MediaSetLoader extends AsyncTaskLoader<Cursor> implements LoaderCompatShim<Cursor>{ 435f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck 445f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck private static final SyncListener sNullListener = new SyncListener() { 455f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck @Override 465f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck public void onSyncDone(MediaSet mediaSet, int resultCode) { 475f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck } 485f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck }; 495f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck 50638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck private final MediaSet mMediaSet; 51869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu private final DataManager mDataManager; 525f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck private Future<Integer> mSyncTask = null; 535f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck private ContentListener mObserver = new ContentListener() { 545f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck @Override 555f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck public void onContentDirty() { 565f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck onContentChanged(); 575f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck } 585f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck }; 595f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck 60638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck private ArrayList<MediaItem> mCoverItems; 618c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu 628c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu public MediaSetLoader(Context context) { 638c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu super(context); 64869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu mDataManager = DataManager.from(context); 65869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu String path = mDataManager.getTopSetPath(DataManager.INCLUDE_ALL); 66869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu mMediaSet = mDataManager.getMediaSet(path); 678c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu } 688c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu 695f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck public MediaSetLoader(Context context, String path) { 705f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck super(context); 71869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu mDataManager = DataManager.from(getContext()); 72869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu mMediaSet = mDataManager.getMediaSet(path); 735f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck } 745f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck 755f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck @Override 765f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck protected void onStartLoading() { 775f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck super.onStartLoading(); 785f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck mMediaSet.addContentListener(mObserver); 795f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck mSyncTask = mMediaSet.requestSync(sNullListener); 805f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck forceLoad(); 815f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck } 825f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck 835f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck @Override 845f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck protected boolean onCancelLoad() { 855f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck if (mSyncTask != null) { 865f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck mSyncTask.cancel(); 875f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck mSyncTask = null; 885f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck } 895f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck return super.onCancelLoad(); 905f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck } 915f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck 925f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck @Override 935f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck protected void onStopLoading() { 945f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck super.onStopLoading(); 955f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck cancelLoad(); 965f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck mMediaSet.removeContentListener(mObserver); 975f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck } 985f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck 995f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck @Override 1005f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck protected void onReset() { 1015f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck super.onReset(); 1025f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck onStopLoading(); 1035f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck } 1045f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck 1055f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck @Override 1068c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu public Cursor loadInBackground() { 107705dc819661cb8c8e839a04577b0641bd6caad53John Reck // TODO: This probably doesn't work 108705dc819661cb8c8e839a04577b0641bd6caad53John Reck mMediaSet.reload(); 1098c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu final MatrixCursor cursor = new MatrixCursor(AlbumSetLoader.PROJECTION); 1108c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu final Object[] row = new Object[AlbumSetLoader.PROJECTION.length]; 1118c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu int count = mMediaSet.getSubMediaSetCount(); 112638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck ArrayList<MediaItem> coverItems = new ArrayList<MediaItem>(count); 1138c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu for (int i = 0; i < count; i++) { 1148c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu MediaSet m = mMediaSet.getSubMediaSet(i); 115705dc819661cb8c8e839a04577b0641bd6caad53John Reck m.reload(); 1168c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu row[AlbumSetLoader.INDEX_ID] = i; 1178c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu row[AlbumSetLoader.INDEX_TITLE] = m.getName(); 1188c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu row[AlbumSetLoader.INDEX_COUNT] = m.getMediaItemCount(); 119869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu row[AlbumSetLoader.INDEX_SUPPORTED_OPERATIONS] = m.getSupportedOperations(); 1208c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu MediaItem coverItem = m.getCoverMediaItem(); 121638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck if (coverItem != null) { 122638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck row[AlbumSetLoader.INDEX_TIMESTAMP] = coverItem.getDateInMs(); 123638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck } 124638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck coverItems.add(coverItem); 1258c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu cursor.addRow(row); 1268c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu } 127638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck synchronized (mMediaSet) { 128638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck mCoverItems = coverItems; 129638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck } 1308c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu return cursor; 1315f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck } 1325f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck 1338c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu @Override 1348c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu public Drawable drawableForItem(Cursor item, Drawable recycle) { 1358c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu BitmapJobDrawable drawable = null; 1368c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu if (recycle == null || !(recycle instanceof BitmapJobDrawable)) { 1378c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu drawable = new BitmapJobDrawable(); 1388c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu } else { 1398c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu drawable = (BitmapJobDrawable) recycle; 1408c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu } 1418c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu int index = item.getInt(AlbumSetLoader.INDEX_ID); 1428c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu drawable.setMediaItem(mCoverItems.get(index)); 1438c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu return drawable; 1448c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu } 1458c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu 1468c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu public static int getThumbnailSize() { 1478c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu return MediaItem.getTargetSize(MediaItem.TYPE_MICROTHUMBNAIL); 1488c12028e716792bb083dc57dda58b8be26a16ef7Bobby Georgescu } 149f6e687bc30887695374580712092aeb917c84253John Reck 150f6e687bc30887695374580712092aeb917c84253John Reck @Override 151f6e687bc30887695374580712092aeb917c84253John Reck public Uri uriForItem(Cursor item) { 152f6e687bc30887695374580712092aeb917c84253John Reck int index = item.getInt(AlbumSetLoader.INDEX_ID); 153f6e687bc30887695374580712092aeb917c84253John Reck MediaSet ms = mMediaSet.getSubMediaSet(index); 154f6e687bc30887695374580712092aeb917c84253John Reck return ms == null ? null : ms.getContentUri(); 155f6e687bc30887695374580712092aeb917c84253John Reck } 156869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu 157869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu @Override 158869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu public ArrayList<Uri> urisForSubItems(Cursor item) { 159869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu int index = item.getInt(AlbumSetLoader.INDEX_ID); 160869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu MediaSet ms = mMediaSet.getSubMediaSet(index); 161869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu if (ms == null) return null; 162869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu final ArrayList<Uri> result = new ArrayList<Uri>(); 163869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu ms.enumerateMediaItems(new MediaSet.ItemConsumer() { 164869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu @Override 165869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu public void consume(int index, MediaItem item) { 166869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu if (item != null) { 167869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu result.add(item.getContentUri()); 168869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu } 169869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu } 170869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu }); 171869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu return result; 172869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu } 173869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu 174869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu @Override 175869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu public void deleteItemWithPath(Object path) { 176869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu MediaObject o = mDataManager.getMediaObject((Path) path); 177869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu if (o != null) { 178869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu o.delete(); 179869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu } 180869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu } 181869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu 182869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu @Override 183869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu public Object getPathForItem(Cursor item) { 184869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu int index = item.getInt(AlbumSetLoader.INDEX_ID); 185869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu MediaSet ms = mMediaSet.getSubMediaSet(index); 186869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu if (ms != null) { 187869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu return ms.getPath(); 188869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu } 189869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu return null; 190869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu } 1915f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck} 192