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