diff options
24 files changed, 300 insertions, 213 deletions
diff --git a/src/com/android/gallery3d/app/AlbumDataLoader.java b/src/com/android/gallery3d/app/AlbumDataLoader.java index 28a822830..77fd0db8a 100644 --- a/src/com/android/gallery3d/app/AlbumDataLoader.java +++ b/src/com/android/gallery3d/app/AlbumDataLoader.java @@ -368,7 +368,7 @@ public class AlbumDataLoader { mDirty = false; } updateLoading(true); - long version = mSource.reload(); + long version = mSource.loadIfDirty(); UpdateInfo info = executeAndWait(new GetUpdateInfo(version)); updateComplete = info == null; if (updateComplete) continue; diff --git a/src/com/android/gallery3d/app/AlbumSetDataLoader.java b/src/com/android/gallery3d/app/AlbumSetDataLoader.java index cf380f812..8c73d4ef5 100644 --- a/src/com/android/gallery3d/app/AlbumSetDataLoader.java +++ b/src/com/android/gallery3d/app/AlbumSetDataLoader.java @@ -343,7 +343,7 @@ public class AlbumSetDataLoader { while (mActive) { synchronized (this) { if (mActive && !mDirty && updateComplete) { - if (!mSource.isLoading()) updateLoading(false); + updateLoading(false); Utils.waitWithoutInterrupt(this); continue; } @@ -351,7 +351,7 @@ public class AlbumSetDataLoader { mDirty = false; updateLoading(true); - long version = mSource.reload(); + long version = mSource.loadIfDirty(); UpdateInfo info = executeAndWait(new GetUpdateInfo(version)); updateComplete = info == null; if (updateComplete) continue; diff --git a/src/com/android/gallery3d/app/PhotoDataAdapter.java b/src/com/android/gallery3d/app/PhotoDataAdapter.java index 2b586da94..faff14674 100644 --- a/src/com/android/gallery3d/app/PhotoDataAdapter.java +++ b/src/com/android/gallery3d/app/PhotoDataAdapter.java @@ -1033,7 +1033,7 @@ public class PhotoDataAdapter implements PhotoPage.Model { mDirty = false; UpdateInfo info = executeAndWait(new GetUpdateInfo()); updateLoading(true); - long version = mSource.reload(); + long version = mSource.loadIfDirty(); if (info.version != version) { info.reloadContent = true; info.size = mSource.getMediaItemCount(); diff --git a/src/com/android/gallery3d/app/SlideshowPage.java b/src/com/android/gallery3d/app/SlideshowPage.java index 54aae67ab..51bc70feb 100644 --- a/src/com/android/gallery3d/app/SlideshowPage.java +++ b/src/com/android/gallery3d/app/SlideshowPage.java @@ -272,7 +272,7 @@ public class SlideshowPage extends ActivityState { @Override public long reload() { - long version = mMediaSet.reload(); + long version = mMediaSet.loadIfDirty(); if (version != mSourceVersion) { mSourceVersion = version; int count = mMediaSet.getTotalMediaItemCount(); @@ -346,7 +346,7 @@ public class SlideshowPage extends ActivityState { @Override public long reload() { - long version = mMediaSet.reload(); + long version = mMediaSet.loadIfDirty(); if (version != mDataVersion) { mDataVersion = version; mData.clear(); diff --git a/src/com/android/gallery3d/data/ClusterAlbum.java b/src/com/android/gallery3d/data/ClusterAlbum.java index 8681952bf..684e6109f 100644 --- a/src/com/android/gallery3d/data/ClusterAlbum.java +++ b/src/com/android/gallery3d/data/ClusterAlbum.java @@ -18,7 +18,7 @@ package com.android.gallery3d.data; import java.util.ArrayList; -public class ClusterAlbum extends MediaSet implements ContentListener { +public class ClusterAlbum extends MediaSetWrapper implements ContentListener { @SuppressWarnings("unused") private static final String TAG = "ClusterAlbum"; private ArrayList<Path> mPaths = new ArrayList<Path>(); @@ -29,7 +29,7 @@ public class ClusterAlbum extends MediaSet implements ContentListener { public ClusterAlbum(Path path, DataManager dataManager, MediaSet clusterAlbumSet) { - super(path, nextVersionNumber()); + super(clusterAlbumSet, path, nextVersionNumber()); mDataManager = dataManager; mClusterAlbumSet = clusterAlbumSet; mClusterAlbumSet.addContentListener(this); @@ -106,14 +106,6 @@ public class ClusterAlbum extends MediaSet implements ContentListener { } @Override - public long reload() { - if (mClusterAlbumSet.reload() > mDataVersion) { - mDataVersion = nextVersionNumber(); - } - return mDataVersion; - } - - @Override public void onContentDirty() { notifyContentChanged(); } diff --git a/src/com/android/gallery3d/data/ClusterAlbumSet.java b/src/com/android/gallery3d/data/ClusterAlbumSet.java index cb212ba36..a551de2ab 100644 --- a/src/com/android/gallery3d/data/ClusterAlbumSet.java +++ b/src/com/android/gallery3d/data/ClusterAlbumSet.java @@ -24,7 +24,7 @@ import com.android.gallery3d.app.GalleryApp; import java.util.ArrayList; import java.util.HashSet; -public class ClusterAlbumSet extends MediaSet implements ContentListener { +public class ClusterAlbumSet extends MediaSetWrapper implements ContentListener { @SuppressWarnings("unused") private static final String TAG = "ClusterAlbumSet"; private GalleryApp mApplication; @@ -35,7 +35,7 @@ public class ClusterAlbumSet extends MediaSet implements ContentListener { public ClusterAlbumSet(Path path, GalleryApp application, MediaSet baseSet, int kind) { - super(path, INVALID_DATA_VERSION); + super(baseSet, path, INVALID_DATA_VERSION); mApplication = application; mBaseSet = baseSet; mKind = kind; @@ -58,17 +58,20 @@ public class ClusterAlbumSet extends MediaSet implements ContentListener { } @Override - public long reload() { - if (mBaseSet.reload() > mDataVersion) { - if (mFirstReloadDone) { - updateClustersContents(); - } else { - updateClusters(); - mFirstReloadDone = true; - } - mDataVersion = nextVersionNumber(); + protected boolean isDirtyLocked() { + return super.isDirtyLocked() + || !mFirstReloadDone; + } + + @Override + public void load() throws InterruptedException { + super.load(); + if (mFirstReloadDone) { + updateClustersContents(); + } else { + updateClusters(); + mFirstReloadDone = true; } - return mDataVersion; } @Override diff --git a/src/com/android/gallery3d/data/ComboAlbum.java b/src/com/android/gallery3d/data/ComboAlbum.java index cadd9f8af..e193afa6d 100644 --- a/src/com/android/gallery3d/data/ComboAlbum.java +++ b/src/com/android/gallery3d/data/ComboAlbum.java @@ -27,11 +27,13 @@ public class ComboAlbum extends MediaSet implements ContentListener { @SuppressWarnings("unused") private static final String TAG = "ComboAlbum"; private final MediaSet[] mSets; + private final boolean[] mDirtySets; private String mName; public ComboAlbum(Path path, MediaSet[] mediaSets, String name) { super(path, nextVersionNumber()); mSets = mediaSets; + mDirtySets = new boolean[mSets.length]; for (MediaSet set : mSets) { set.addContentListener(this); } @@ -81,14 +83,24 @@ public class ComboAlbum extends MediaSet implements ContentListener { } @Override - public long reload() { - boolean changed = false; + protected boolean isDirtyLocked() { + boolean dirty = false; + for (int i = 0; i < mSets.length; i++) { + mDirtySets[i] = mSets[i].isDirtyLocked(); + dirty |= mDirtySets[i] + || mSets[i].getDataVersion() > getDataVersion(); + } + return dirty; + } + + @Override + protected void load() throws InterruptedException { for (int i = 0, n = mSets.length; i < n; ++i) { - long version = mSets[i].reload(); - if (version > mDataVersion) changed = true; + if (mDirtySets[i]) { + mDirtySets[i] = false; + mSets[i].load(); + } } - if (changed) mDataVersion = nextVersionNumber(); - return mDataVersion; } @Override diff --git a/src/com/android/gallery3d/data/ComboAlbumSet.java b/src/com/android/gallery3d/data/ComboAlbumSet.java index a2a041279..528ffcf41 100644 --- a/src/com/android/gallery3d/data/ComboAlbumSet.java +++ b/src/com/android/gallery3d/data/ComboAlbumSet.java @@ -27,11 +27,13 @@ public class ComboAlbumSet extends MediaSet implements ContentListener { @SuppressWarnings("unused") private static final String TAG = "ComboAlbumSet"; private final MediaSet[] mSets; + private final boolean[] mDirtySets; private final String mName; public ComboAlbumSet(Path path, GalleryApp application, MediaSet[] mediaSets) { super(path, nextVersionNumber()); mSets = mediaSets; + mDirtySets = new boolean[mSets.length]; for (MediaSet set : mSets) { set.addContentListener(this); } @@ -66,31 +68,24 @@ public class ComboAlbumSet extends MediaSet implements ContentListener { } @Override - public boolean isLoading() { - for (int i = 0, n = mSets.length; i < n; ++i) { - if (mSets[i].isLoading()) return true; + protected boolean isDirtyLocked() { + boolean dirty = false; + for (int i = 0; i < mSets.length; i++) { + mDirtySets[i] = mSets[i].isDirtyLocked(); + dirty |= mDirtySets[i] + || mSets[i].getDataVersion() > getDataVersion(); } - return false; + return dirty; } @Override - public long reload() { - boolean changed = false; + protected void load() throws InterruptedException { for (int i = 0, n = mSets.length; i < n; ++i) { - long version = mSets[i].reload(); - if (version > mDataVersion) changed = true; - } - if (changed) mDataVersion = nextVersionNumber(); - return mDataVersion; - } - - @Override - public boolean loadIfDirty() { - boolean changed = false; - for (int i = 0; i < mSets.length; i++) { - changed |= mSets[i].loadIfDirty(); + if (mDirtySets[i]) { + mDirtySets[i] = false; + mSets[i].load(); + } } - return changed; } @Override diff --git a/src/com/android/gallery3d/data/FilterDeleteSet.java b/src/com/android/gallery3d/data/FilterDeleteSet.java index c76412ff8..7970d7c4a 100644 --- a/src/com/android/gallery3d/data/FilterDeleteSet.java +++ b/src/com/android/gallery3d/data/FilterDeleteSet.java @@ -27,7 +27,7 @@ import java.util.ArrayList; // void clearDeletion(); // int getNumberOfDeletions(); // -public class FilterDeleteSet extends MediaSet implements ContentListener { +public class FilterDeleteSet extends MediaSetWrapper implements ContentListener { @SuppressWarnings("unused") private static final String TAG = "FilterDeleteSet"; @@ -65,7 +65,7 @@ public class FilterDeleteSet extends MediaSet implements ContentListener { private ArrayList<Deletion> mCurrent = new ArrayList<Deletion>(); public FilterDeleteSet(Path path, MediaSet baseSet) { - super(path, INVALID_DATA_VERSION); + super(baseSet, path, INVALID_DATA_VERSION); mBaseSet = baseSet; mBaseSet.addContentListener(this); } @@ -141,14 +141,18 @@ public class FilterDeleteSet extends MediaSet implements ContentListener { return base; } + @Override + protected boolean isDirtyLocked() { + synchronized (mRequests) { + return super.isDirtyLocked() || !mRequests.isEmpty(); + } + } + // We apply the pending requests in the mRequests to construct mCurrent in reload(). @Override - public long reload() { - boolean newData = mBaseSet.reload() > mDataVersion; + protected void load() throws InterruptedException { + super.load(); synchronized (mRequests) { - if (!newData && mRequests.isEmpty()) { - return mDataVersion; - } for (int i = 0; i < mRequests.size(); i++) { Request r = mRequests.get(i); switch (r.type) { @@ -218,9 +222,6 @@ public class FilterDeleteSet extends MediaSet implements ContentListener { } mCurrent = result; } - - mDataVersion = nextVersionNumber(); - return mDataVersion; } private void sendRequest(int type, Path path, int indexHint) { diff --git a/src/com/android/gallery3d/data/FilterEmptyPromptSet.java b/src/com/android/gallery3d/data/FilterEmptyPromptSet.java index b576e06d4..f2623fb00 100644 --- a/src/com/android/gallery3d/data/FilterEmptyPromptSet.java +++ b/src/com/android/gallery3d/data/FilterEmptyPromptSet.java @@ -18,7 +18,7 @@ package com.android.gallery3d.data; import java.util.ArrayList; -public class FilterEmptyPromptSet extends MediaSet implements ContentListener { +public class FilterEmptyPromptSet extends MediaSetWrapper implements ContentListener { @SuppressWarnings("unused") private static final String TAG = "FilterEmptyPromptSet"; @@ -26,7 +26,7 @@ public class FilterEmptyPromptSet extends MediaSet implements ContentListener { private MediaSet mBaseSet; public FilterEmptyPromptSet(Path path, MediaSet baseSet, MediaItem emptyItem) { - super(path, INVALID_DATA_VERSION); + super(baseSet, path, INVALID_DATA_VERSION); mEmptyItem = new ArrayList<MediaItem>(1); mEmptyItem.add(emptyItem); mBaseSet = baseSet; @@ -71,11 +71,6 @@ public class FilterEmptyPromptSet extends MediaSet implements ContentListener { } @Override - public long reload() { - return mBaseSet.reload(); - } - - @Override public String getName() { return mBaseSet.getName(); } diff --git a/src/com/android/gallery3d/data/FilterTypeSet.java b/src/com/android/gallery3d/data/FilterTypeSet.java index 477ef73ad..d6fbbdb9a 100644 --- a/src/com/android/gallery3d/data/FilterTypeSet.java +++ b/src/com/android/gallery3d/data/FilterTypeSet.java @@ -25,6 +25,7 @@ public class FilterTypeSet extends MediaSet implements ContentListener { private final DataManager mDataManager; private final MediaSet mBaseSet; + private boolean mBaseSetIsDirty; private final int mMediaType; private final ArrayList<Path> mPaths = new ArrayList<Path>(); private final ArrayList<MediaSet> mAlbums = new ArrayList<MediaSet>(); @@ -65,12 +66,17 @@ public class FilterTypeSet extends MediaSet implements ContentListener { } @Override - public long reload() { - if (mBaseSet.reload() > mDataVersion) { - updateData(); - mDataVersion = nextVersionNumber(); + protected boolean isDirtyLocked() { + mBaseSetIsDirty = mBaseSet.isDirtyLocked(); + return mBaseSetIsDirty || mBaseSet.getDataVersion() > getDataVersion(); + } + + @Override + public void load() throws InterruptedException { + if (mBaseSetIsDirty) { + mBaseSet.load(); } - return mDataVersion; + updateData(); } @Override @@ -78,7 +84,7 @@ public class FilterTypeSet extends MediaSet implements ContentListener { notifyContentChanged(); } - private void updateData() { + private void updateData() throws InterruptedException { // Albums mAlbums.clear(); String basePath = "/filter/mediatype/" + mMediaType; @@ -87,7 +93,7 @@ public class FilterTypeSet extends MediaSet implements ContentListener { MediaSet set = mBaseSet.getSubMediaSet(i); String filteredPath = basePath + "/{" + set.getPath().toString() + "}"; MediaSet filteredSet = mDataManager.getMediaSet(filteredPath); - filteredSet.reload(); + filteredSet.loadIfDirty(); if (filteredSet.getMediaItemCount() > 0 || filteredSet.getSubMediaSetCount() > 0) { mAlbums.add(filteredSet); diff --git a/src/com/android/gallery3d/data/LocalAlbum.java b/src/com/android/gallery3d/data/LocalAlbum.java index 7b7015af6..8c92d3aa5 100644 --- a/src/com/android/gallery3d/data/LocalAlbum.java +++ b/src/com/android/gallery3d/data/LocalAlbum.java @@ -252,12 +252,12 @@ public class LocalAlbum extends MediaSet { } @Override - public long reload() { - if (mNotifier.isDirty()) { - mDataVersion = nextVersionNumber(); - mCachedCount = INVALID_COUNT; - } - return mDataVersion; + protected boolean isDirtyLocked() { + return mNotifier.isDirty(); + } + @Override + public void load() { + mCachedCount = INVALID_COUNT; } @Override diff --git a/src/com/android/gallery3d/data/LocalAlbumSet.java b/src/com/android/gallery3d/data/LocalAlbumSet.java index b2b4b8c5d..d71c9f700 100644 --- a/src/com/android/gallery3d/data/LocalAlbumSet.java +++ b/src/com/android/gallery3d/data/LocalAlbumSet.java @@ -17,26 +17,20 @@ package com.android.gallery3d.data; import android.net.Uri; -import android.os.Handler; import android.provider.MediaStore.Images; import android.provider.MediaStore.Video; import com.android.gallery3d.R; import com.android.gallery3d.app.GalleryApp; import com.android.gallery3d.data.BucketHelper.BucketEntry; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.FutureListener; import com.android.gallery3d.util.MediaSetUtils; -import com.android.gallery3d.util.ThreadPool; -import com.android.gallery3d.util.ThreadPool.JobContext; import java.util.ArrayList; import java.util.Comparator; // LocalAlbumSet lists all image or video albums in the local storage. // The path should be "/local/image", "local/video" or "/local/all" -public class LocalAlbumSet extends MediaSet - implements FutureListener<ArrayList<MediaSet>> { +public class LocalAlbumSet extends MediaSet { @SuppressWarnings("unused") private static final String TAG = "LocalAlbumSet"; @@ -52,16 +46,10 @@ public class LocalAlbumSet extends MediaSet private ArrayList<MediaSet> mAlbums = new ArrayList<MediaSet>(); private final ChangeNotifier mNotifier; private final String mName; - private final Handler mHandler; - private boolean mIsLoading; - - private Future<ArrayList<MediaSet>> mLoadTask; - private ArrayList<MediaSet> mLoadBuffer; public LocalAlbumSet(Path path, GalleryApp application) { super(path, nextVersionNumber()); mApplication = application; - mHandler = new Handler(application.getMainLooper()); mType = getTypeFromPath(path); mNotifier = new ChangeNotifier(this, mWatchUris, application); mName = application.getResources().getString( @@ -98,41 +86,6 @@ public class LocalAlbumSet extends MediaSet return -1; } - private class AlbumsLoader implements ThreadPool.Job<ArrayList<MediaSet>> { - - @Override - @SuppressWarnings("unchecked") - public ArrayList<MediaSet> run(JobContext jc) { - // Note: it will be faster if we only select media_type and bucket_id. - // need to test the performance if that is worth - BucketEntry[] entries = BucketHelper.loadBucketEntries( - jc, mApplication.getContentResolver(), mType); - - if (jc.isCancelled()) return null; - - int offset = 0; - // Move camera and download bucket to the front, while keeping the - // order of others. - int index = findBucket(entries, MediaSetUtils.CAMERA_BUCKET_ID); - if (index != -1) { - circularShiftRight(entries, offset++, index); - } - index = findBucket(entries, MediaSetUtils.DOWNLOAD_BUCKET_ID); - if (index != -1) { - circularShiftRight(entries, offset++, index); - } - - ArrayList<MediaSet> albums = new ArrayList<MediaSet>(); - DataManager dataManager = mApplication.getDataManager(); - for (BucketEntry entry : entries) { - MediaSet album = getLocalAlbum(dataManager, - mType, mPath, entry.bucketId, entry.bucketName); - albums.add(album); - } - return albums; - } - } - private MediaSet getLocalAlbum( DataManager manager, int type, Path parent, int id, String name) { synchronized (DataManager.LOCK) { @@ -155,43 +108,45 @@ public class LocalAlbumSet extends MediaSet } @Override - public synchronized boolean isLoading() { - return mIsLoading; + protected boolean isDirtyLocked() { + return mNotifier.isDirty(); } @Override - // synchronized on this function for - // 1. Prevent calling reload() concurrently. - // 2. Prevent calling onFutureDone() and reload() concurrently - public synchronized long reload() { - if (mNotifier.isDirty()) { - if (mLoadTask != null) mLoadTask.cancel(); - mIsLoading = true; - mLoadTask = mApplication.getThreadPool().submit(new AlbumsLoader(), this); + protected void load() throws InterruptedException { + // Note: it will be faster if we only select media_type and bucket_id. + // need to test the performance if that is worth + BucketEntry[] entries = BucketHelper.loadBucketEntries( + createJobContextCompat(), mApplication.getContentResolver(), mType); + + // BucketHelper.loadBucketEntries returns null if it was canceled + if (entries == null || Thread.interrupted()) { + throw new InterruptedException(); } - if (mLoadBuffer != null) { - mAlbums = mLoadBuffer; - mLoadBuffer = null; - for (MediaSet album : mAlbums) { - album.reload(); - } - mDataVersion = nextVersionNumber(); + + int offset = 0; + // Move camera and download bucket to the front, while keeping the + // order of others. + int index = findBucket(entries, MediaSetUtils.CAMERA_BUCKET_ID); + if (index != -1) { + circularShiftRight(entries, offset++, index); + } + index = findBucket(entries, MediaSetUtils.DOWNLOAD_BUCKET_ID); + if (index != -1) { + circularShiftRight(entries, offset++, index); } - return mDataVersion; - } - @Override - public synchronized void onFutureDone(Future<ArrayList<MediaSet>> future) { - if (mLoadTask != future) return; // ignore, wait for the latest task - mLoadBuffer = future.get(); - mIsLoading = false; - if (mLoadBuffer == null) mLoadBuffer = new ArrayList<MediaSet>(); - mHandler.post(new Runnable() { - @Override - public void run() { - notifyContentChanged(); - } - }); + mAlbums.clear(); + DataManager dataManager = mApplication.getDataManager(); + for (BucketEntry entry : entries) { + MediaSet album = getLocalAlbum(dataManager, + mType, mPath, entry.bucketId, entry.bucketName); + mAlbums.add(album); + } + + for (MediaSet album : mAlbums) { + album.loadIfDirty(); + } } // For debug only. Fake there is a ContentObserver.onChange() event. diff --git a/src/com/android/gallery3d/data/LocalMergeAlbum.java b/src/com/android/gallery3d/data/LocalMergeAlbum.java index f0b5e5726..e07dc5ed8 100644 --- a/src/com/android/gallery3d/data/LocalMergeAlbum.java +++ b/src/com/android/gallery3d/data/LocalMergeAlbum.java @@ -24,7 +24,6 @@ import com.android.gallery3d.common.ApiHelper; import java.lang.ref.SoftReference; import java.util.ArrayList; import java.util.Comparator; -import java.util.NoSuchElementException; import java.util.SortedMap; import java.util.TreeMap; @@ -40,6 +39,7 @@ public class LocalMergeAlbum extends MediaSet implements ContentListener { private final Comparator<MediaItem> mComparator; private final MediaSet[] mSources; + private final boolean[] mDirtySources; private FetchCache[] mFetcher; private int mSupportedOperation; @@ -53,11 +53,11 @@ public class LocalMergeAlbum extends MediaSet implements ContentListener { super(path, INVALID_DATA_VERSION); mComparator = comparator; mSources = sources; + mDirtySources = new boolean[mSources.length]; mBucketId = bucketId; for (MediaSet set : mSources) { set.addContentListener(this); } - reload(); } @Override @@ -70,7 +70,6 @@ public class LocalMergeAlbum extends MediaSet implements ContentListener { } private void updateData() { - ArrayList<MediaSet> matches = new ArrayList<MediaSet>(); int supported = mSources.length == 0 ? 0 : MediaItem.SUPPORT_ALL; mFetcher = new FetchCache[mSources.length]; for (int i = 0, n = mSources.length; i < n; ++i) { @@ -173,17 +172,26 @@ public class LocalMergeAlbum extends MediaSet implements ContentListener { } @Override - public long reload() { - boolean changed = false; + protected boolean isDirtyLocked() { + boolean dirty = false; for (int i = 0, n = mSources.length; i < n; ++i) { - if (mSources[i].reload() > mDataVersion) changed = true; + mDirtySources[i] = mSources[i].isDirtyLocked(); + dirty |= mDirtySources[i] + || mSources[i].getDataVersion() > getDataVersion(); } - if (changed) { - mDataVersion = nextVersionNumber(); - updateData(); - invalidateCache(); + return dirty; + } + + @Override + public void load() throws InterruptedException { + for (int i = 0, n = mSources.length; i < n; ++i) { + if (mDirtySources[i]) { + mSources[i].load(); + mDirtySources[i] = false; + } } - return mDataVersion; + updateData(); + invalidateCache(); } @Override diff --git a/src/com/android/gallery3d/data/MediaSet.java b/src/com/android/gallery3d/data/MediaSet.java index 9bc148f89..cc8a4a71a 100644 --- a/src/com/android/gallery3d/data/MediaSet.java +++ b/src/com/android/gallery3d/data/MediaSet.java @@ -18,6 +18,8 @@ package com.android.gallery3d.data; import com.android.gallery3d.common.Utils; import com.android.gallery3d.util.Future; +import com.android.gallery3d.util.ThreadPool.CancelListener; +import com.android.gallery3d.util.ThreadPool.JobContext; import java.util.ArrayList; import java.util.WeakHashMap; @@ -54,6 +56,9 @@ public abstract class MediaSet extends MediaObject { void onSyncDone(MediaSet mediaSet, int resultCode); } + private Object mLoadLock = new Object(); + private boolean mIsLoading; + public MediaSet(Path path, long version) { super(path, version); } @@ -99,14 +104,6 @@ public abstract class MediaSet extends MediaObject { return false; } - /** - * Method {@link #reload()} may process the loading task in background, this method tells - * its client whether the loading is still in process or not. - */ - public boolean isLoading() { - return false; - } - public int getTotalMediaItemCount() { int total = getMediaItemCount(); for (int i = 0, n = getSubMediaSetCount(); i < n; i++) { @@ -176,15 +173,76 @@ public abstract class MediaSet extends MediaObject { } } - // Reload the content. Return the current data version. reload() should be called - // in the same thread as getMediaItem(int, int) and getSubMediaSet(int). - public abstract long reload(); + // TODO: Remove this once createJobContextCompat is no longer needed + // Note that canceling a load is not strictly supported as it can leave + // MediaSets with bad internal state. Fortunately they are never canceled + // anywhere, so the isCancelled() exists purely for completeness sake + private static class LoadJobContextCompat implements JobContext { + + @Override + public boolean isCancelled() { + return Thread.interrupted(); + } + + @Override + public void setCancelListener(CancelListener listener) { + } + + @Override + public boolean setMode(int mode) { + return false; + } + } + + @Deprecated + protected final JobContext createJobContextCompat() { + return new LoadJobContextCompat(); + } + + /** + * Synchronously load if the MediaSet is dirty. Note that this must be called + * on the same thread as getMediaItem(int, int) and getSubMediaSet(int) + * @return DataVersion + */ + public final long loadIfDirty() { + try { + boolean doLoad = false; + synchronized (mLoadLock) { + if (mIsLoading) { + mLoadLock.wait(); + } + doLoad = isDirtyLocked(); + if (doLoad) { + mIsLoading = true; + } + } + if (doLoad) { + load(); + synchronized (mLoadLock) { + mDataVersion = nextVersionNumber(); + mIsLoading = false; + mLoadLock.notifyAll(); + } + } + } catch (InterruptedException ex) { + } + return getDataVersion(); + } + + /** + * Called inside of synchronized(mLoadLock). It is guaranteed this will only + * be called once before a call to load() if this returns true. It is + * acceptable to clear any internal dirty flags in this function as a result. + * @return true if the set wants a load() call, false otherwise + */ + protected abstract boolean isDirtyLocked(); /** - * Synchronously load if the MediaSet is dirty - * @return True if new data was loaded, false otherwise + * Synchronously load the MediaSet. Only called if {@link #isDirtyLocked()} + * returned true + * @throws InterruptedException if the load was interrupted */ - public boolean loadIfDirty() { throw new IllegalStateException("not implemented"); } + protected abstract void load() throws InterruptedException; @Override public MediaDetails getDetails() { @@ -283,7 +341,6 @@ public abstract class MediaSet extends MediaObject { } private class MultiSetSyncFuture implements Future<Integer>, SyncListener { - @SuppressWarnings("hiding") private static final String TAG = "Gallery.MultiSetSync"; private final SyncListener mListener; diff --git a/src/com/android/gallery3d/data/MediaSetWrapper.java b/src/com/android/gallery3d/data/MediaSetWrapper.java new file mode 100644 index 000000000..986c51fa5 --- /dev/null +++ b/src/com/android/gallery3d/data/MediaSetWrapper.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.data; + +public abstract class MediaSetWrapper extends MediaSet { + + private MediaSet mWrappedSet; + private boolean mWrappedIsDirty; + + public MediaSetWrapper(MediaSet wrappedSet, Path path, long version) { + super(path, version); + mWrappedSet = wrappedSet; + } + + @Override + protected boolean isDirtyLocked() { + mWrappedIsDirty = mWrappedSet.isDirtyLocked(); + return mWrappedIsDirty; + } + + @Override + protected void load() throws InterruptedException { + if (mWrappedIsDirty) { + mWrappedSet.load(); + } + } + + @Override + public long getDataVersion() { + return mWrappedSet.getDataVersion(); + } + +} diff --git a/src/com/android/gallery3d/data/SecureAlbum.java b/src/com/android/gallery3d/data/SecureAlbum.java index 204f848f8..04d51d11c 100644 --- a/src/com/android/gallery3d/data/SecureAlbum.java +++ b/src/com/android/gallery3d/data/SecureAlbum.java @@ -122,12 +122,13 @@ public class SecureAlbum extends MediaSet implements StitchingChangeListener { } @Override - public long reload() { - if (mNotifier.isDirty()) { - mDataVersion = nextVersionNumber(); - updateExistingItems(); - } - return mDataVersion; + protected boolean isDirtyLocked() { + return mNotifier.isDirty(); + } + + @Override + public void load() { + updateExistingItems(); } private ArrayList<Integer> queryExistingIds(Uri uri, int minId, int maxId) { diff --git a/src/com/android/gallery3d/data/SingleItemAlbum.java b/src/com/android/gallery3d/data/SingleItemAlbum.java index a0093e0c3..a404fa770 100644 --- a/src/com/android/gallery3d/data/SingleItemAlbum.java +++ b/src/com/android/gallery3d/data/SingleItemAlbum.java @@ -62,7 +62,12 @@ public class SingleItemAlbum extends MediaSet { } @Override - public long reload() { - return mDataVersion; + protected boolean isDirtyLocked() { + return false; } + + @Override + protected void load() throws InterruptedException { + } + } diff --git a/src/com/android/gallery3d/data/SnailAlbum.java b/src/com/android/gallery3d/data/SnailAlbum.java index 7bce7a695..78f718806 100644 --- a/src/com/android/gallery3d/data/SnailAlbum.java +++ b/src/com/android/gallery3d/data/SnailAlbum.java @@ -29,12 +29,13 @@ public class SnailAlbum extends SingleItemAlbum { } @Override - public long reload() { - if (mDirty.compareAndSet(true, false)) { - ((SnailItem) getItem()).updateVersion(); - mDataVersion = nextVersionNumber(); - } - return mDataVersion; + protected void load() throws InterruptedException { + ((SnailItem) getItem()).updateVersion(); + } + + @Override + protected boolean isDirtyLocked() { + return mDirty.compareAndSet(true, false); } public void notifyChange() { diff --git a/src/com/android/gallery3d/gadget/MediaSetSource.java b/src/com/android/gallery3d/gadget/MediaSetSource.java index caeff2a87..0e7e6bd57 100644 --- a/src/com/android/gallery3d/gadget/MediaSetSource.java +++ b/src/com/android/gallery3d/gadget/MediaSetSource.java @@ -83,7 +83,7 @@ public class MediaSetSource implements WidgetSource, ContentListener { @Override public void reload() { - long version = mSource.reload(); + long version = mSource.loadIfDirty(); if (mSourceVersion != version) { mSourceVersion = version; mCacheStart = 0; diff --git a/src_pd/com/android/gallery3d/picasasource/PicasaSource.java b/src_pd/com/android/gallery3d/picasasource/PicasaSource.java index 041829169..702b3b5db 100644 --- a/src_pd/com/android/gallery3d/picasasource/PicasaSource.java +++ b/src_pd/com/android/gallery3d/picasasource/PicasaSource.java @@ -67,8 +67,12 @@ public class PicasaSource extends MediaSource { } @Override - public long reload() { - return mDataVersion; + protected boolean isDirtyLocked() { + return false; + } + + @Override + protected void load() { } } diff --git a/tests/src/com/android/gallery3d/data/LocalDataTest.java b/tests/src/com/android/gallery3d/data/LocalDataTest.java index 8f6a46b8e..67fc97ac3 100644 --- a/tests/src/com/android/gallery3d/data/LocalDataTest.java +++ b/tests/src/com/android/gallery3d/data/LocalDataTest.java @@ -66,7 +66,7 @@ public class LocalDataTest extends AndroidTestCase { Path path = Path.fromString( mIsImage ? "/local/image" : "/local/video"); mAlbumSet = new LocalAlbumSet(path, mApp); - mAlbumSet.reload(); + mAlbumSet.loadIfDirty(); verifyResult(); } @@ -200,7 +200,7 @@ public class LocalDataTest extends AndroidTestCase { sub.delete(); mAlbumSet.fakeChange(); latch.isOnContentDirtyBeCalled(DEFAULT_TIMEOUT); - mAlbumSet.reload(); + mAlbumSet.loadIfDirty(); assertEquals(1, mAlbumSet.getSubMediaSetCount()); } } @@ -220,7 +220,7 @@ public class LocalDataTest extends AndroidTestCase { assertEquals(1, sub.getMediaItemCount()); assertTrue((sub.getSupportedOperations() & MediaSet.SUPPORT_DELETE) != 0); sub.delete(); - sub.reload(); + sub.loadIfDirty(); assertEquals(0, sub.getMediaItemCount()); } } diff --git a/tests/src/com/android/gallery3d/data/MockSet.java b/tests/src/com/android/gallery3d/data/MockSet.java index fa83c796f..42f874bdc 100644 --- a/tests/src/com/android/gallery3d/data/MockSet.java +++ b/tests/src/com/android/gallery3d/data/MockSet.java @@ -82,7 +82,12 @@ public class MockSet extends MediaSet { } @Override - public long reload() { - return 0; + protected boolean isDirtyLocked() { + return false; } + + @Override + protected void load() throws InterruptedException { + } + } diff --git a/tests/src/com/android/gallery3d/data/RealDataTest.java b/tests/src/com/android/gallery3d/data/RealDataTest.java index 526cfe357..7a984ef93 100644 --- a/tests/src/com/android/gallery3d/data/RealDataTest.java +++ b/tests/src/com/android/gallery3d/data/RealDataTest.java @@ -53,7 +53,7 @@ public class RealDataTest extends AndroidTestCase { class TestLocalImage { public void run() { MediaSet set = mDataManager.getMediaSet("/local/image"); - set.reload(); + set.loadIfDirty(); Log.v(TAG, "LocalAlbumSet (Image)"); dumpMediaSet(set, ""); } @@ -62,7 +62,7 @@ public class RealDataTest extends AndroidTestCase { class TestLocalVideo { public void run() { MediaSet set = mDataManager.getMediaSet("/local/video"); - set.reload(); + set.loadIfDirty(); Log.v(TAG, "LocalAlbumSet (Video)"); dumpMediaSet(set, ""); } @@ -71,7 +71,7 @@ public class RealDataTest extends AndroidTestCase { class TestPicasa implements Runnable { public void run() { MediaSet set = mDataManager.getMediaSet("/picasa"); - set.reload(); + set.loadIfDirty(); Log.v(TAG, "PicasaAlbumSet"); dumpMediaSet(set, ""); } |