1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.photos.shims; 18 19 import android.content.AsyncTaskLoader; 20 import android.content.Context; 21 import android.database.Cursor; 22 import android.database.MatrixCursor; 23 import android.graphics.drawable.Drawable; 24 import android.net.Uri; 25 26 import com.android.gallery3d.data.ContentListener; 27 import com.android.gallery3d.data.DataManager; 28 import com.android.gallery3d.data.MediaItem; 29 import com.android.gallery3d.data.MediaObject; 30 import com.android.gallery3d.data.MediaSet; 31 import com.android.gallery3d.data.Path; 32 import com.android.gallery3d.data.MediaSet.SyncListener; 33 import com.android.gallery3d.util.Future; 34 import com.android.photos.data.AlbumSetLoader; 35 36 import java.util.ArrayList; 37 38 /** 39 * Returns all MediaSets in a MediaSet, wrapping them in a cursor to appear 40 * like a AlbumSetLoader. 41 */ 42 public class MediaSetLoader extends AsyncTaskLoader<Cursor> implements LoaderCompatShim<Cursor>{ 43 44 private static final SyncListener sNullListener = new SyncListener() { 45 @Override 46 public void onSyncDone(MediaSet mediaSet, int resultCode) { 47 } 48 }; 49 50 private final MediaSet mMediaSet; 51 private final DataManager mDataManager; 52 private Future<Integer> mSyncTask = null; 53 private ContentListener mObserver = new ContentListener() { 54 @Override 55 public void onContentDirty() { 56 onContentChanged(); 57 } 58 }; 59 60 private ArrayList<MediaItem> mCoverItems; 61 MediaSetLoader(Context context)62 public MediaSetLoader(Context context) { 63 super(context); 64 mDataManager = DataManager.from(context); 65 String path = mDataManager.getTopSetPath(DataManager.INCLUDE_ALL); 66 mMediaSet = mDataManager.getMediaSet(path); 67 } 68 MediaSetLoader(Context context, String path)69 public MediaSetLoader(Context context, String path) { 70 super(context); 71 mDataManager = DataManager.from(getContext()); 72 mMediaSet = mDataManager.getMediaSet(path); 73 } 74 75 @Override onStartLoading()76 protected void onStartLoading() { 77 super.onStartLoading(); 78 mMediaSet.addContentListener(mObserver); 79 mSyncTask = mMediaSet.requestSync(sNullListener); 80 forceLoad(); 81 } 82 83 @Override onCancelLoad()84 protected boolean onCancelLoad() { 85 if (mSyncTask != null) { 86 mSyncTask.cancel(); 87 mSyncTask = null; 88 } 89 return super.onCancelLoad(); 90 } 91 92 @Override onStopLoading()93 protected void onStopLoading() { 94 super.onStopLoading(); 95 cancelLoad(); 96 mMediaSet.removeContentListener(mObserver); 97 } 98 99 @Override onReset()100 protected void onReset() { 101 super.onReset(); 102 onStopLoading(); 103 } 104 105 @Override loadInBackground()106 public Cursor loadInBackground() { 107 // TODO: This probably doesn't work 108 mMediaSet.reload(); 109 final MatrixCursor cursor = new MatrixCursor(AlbumSetLoader.PROJECTION); 110 final Object[] row = new Object[AlbumSetLoader.PROJECTION.length]; 111 int count = mMediaSet.getSubMediaSetCount(); 112 ArrayList<MediaItem> coverItems = new ArrayList<MediaItem>(count); 113 for (int i = 0; i < count; i++) { 114 MediaSet m = mMediaSet.getSubMediaSet(i); 115 m.reload(); 116 row[AlbumSetLoader.INDEX_ID] = i; 117 row[AlbumSetLoader.INDEX_TITLE] = m.getName(); 118 row[AlbumSetLoader.INDEX_COUNT] = m.getMediaItemCount(); 119 row[AlbumSetLoader.INDEX_SUPPORTED_OPERATIONS] = m.getSupportedOperations(); 120 MediaItem coverItem = m.getCoverMediaItem(); 121 if (coverItem != null) { 122 row[AlbumSetLoader.INDEX_TIMESTAMP] = coverItem.getDateInMs(); 123 } 124 coverItems.add(coverItem); 125 cursor.addRow(row); 126 } 127 synchronized (mMediaSet) { 128 mCoverItems = coverItems; 129 } 130 return cursor; 131 } 132 133 @Override drawableForItem(Cursor item, Drawable recycle)134 public Drawable drawableForItem(Cursor item, Drawable recycle) { 135 BitmapJobDrawable drawable = null; 136 if (recycle == null || !(recycle instanceof BitmapJobDrawable)) { 137 drawable = new BitmapJobDrawable(); 138 } else { 139 drawable = (BitmapJobDrawable) recycle; 140 } 141 int index = item.getInt(AlbumSetLoader.INDEX_ID); 142 drawable.setMediaItem(mCoverItems.get(index)); 143 return drawable; 144 } 145 getThumbnailSize()146 public static int getThumbnailSize() { 147 return MediaItem.getTargetSize(MediaItem.TYPE_MICROTHUMBNAIL); 148 } 149 150 @Override uriForItem(Cursor item)151 public Uri uriForItem(Cursor item) { 152 int index = item.getInt(AlbumSetLoader.INDEX_ID); 153 MediaSet ms = mMediaSet.getSubMediaSet(index); 154 return ms == null ? null : ms.getContentUri(); 155 } 156 157 @Override urisForSubItems(Cursor item)158 public ArrayList<Uri> urisForSubItems(Cursor item) { 159 int index = item.getInt(AlbumSetLoader.INDEX_ID); 160 MediaSet ms = mMediaSet.getSubMediaSet(index); 161 if (ms == null) return null; 162 final ArrayList<Uri> result = new ArrayList<Uri>(); 163 ms.enumerateMediaItems(new MediaSet.ItemConsumer() { 164 @Override 165 public void consume(int index, MediaItem item) { 166 if (item != null) { 167 result.add(item.getContentUri()); 168 } 169 } 170 }); 171 return result; 172 } 173 174 @Override deleteItemWithPath(Object path)175 public void deleteItemWithPath(Object path) { 176 MediaObject o = mDataManager.getMediaObject((Path) path); 177 if (o != null) { 178 o.delete(); 179 } 180 } 181 182 @Override getPathForItem(Cursor item)183 public Object getPathForItem(Cursor item) { 184 int index = item.getInt(AlbumSetLoader.INDEX_ID); 185 MediaSet ms = mMediaSet.getSubMediaSet(index); 186 if (ms != null) { 187 return ms.getPath(); 188 } 189 return null; 190 } 191 } 192