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