summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Reck <jreck@google.com>2013-01-16 14:10:30 -0800
committerJohn Reck <jreck@google.com>2013-01-16 18:05:07 -0800
commit9686d9d07e344fae2f2310ca544e5401b5e11d30 (patch)
tree7bc66a807f33e3aa016d0e9c977f85cfffbe62f1
parent9003bd581c00a31db4c8291c99a30d5e74fe2dde (diff)
downloadandroid_packages_apps_Snap-9686d9d07e344fae2f2310ca544e5401b5e11d30.tar.gz
android_packages_apps_Snap-9686d9d07e344fae2f2310ca544e5401b5e11d30.tar.bz2
android_packages_apps_Snap-9686d9d07e344fae2f2310ca544e5401b5e11d30.zip
New loading model
Rename reload() to loadIfDirty() loadIfDirty is implemented by MediaSet and is final loadIfDirty is now blocking instead of async Subclasses must implement two protected methods, isDirtyLocked() and load() The change from async reload() to sync loadIfDirty() should be fine since all users of reload() were doing so from a background thread already, and the longest load() is PicasaAlbumSet which is still a fairly brisk 40ms or so Change-Id: If5cc596a1c13e52e5f4efff1a144bd086d37cfb7
-rw-r--r--src/com/android/gallery3d/app/AlbumDataLoader.java2
-rw-r--r--src/com/android/gallery3d/app/AlbumSetDataLoader.java4
-rw-r--r--src/com/android/gallery3d/app/PhotoDataAdapter.java2
-rw-r--r--src/com/android/gallery3d/app/SlideshowPage.java4
-rw-r--r--src/com/android/gallery3d/data/ClusterAlbum.java12
-rw-r--r--src/com/android/gallery3d/data/ClusterAlbumSet.java27
-rw-r--r--src/com/android/gallery3d/data/ComboAlbum.java24
-rw-r--r--src/com/android/gallery3d/data/ComboAlbumSet.java33
-rw-r--r--src/com/android/gallery3d/data/FilterDeleteSet.java21
-rw-r--r--src/com/android/gallery3d/data/FilterEmptyPromptSet.java9
-rw-r--r--src/com/android/gallery3d/data/FilterTypeSet.java20
-rw-r--r--src/com/android/gallery3d/data/LocalAlbum.java12
-rw-r--r--src/com/android/gallery3d/data/LocalAlbumSet.java113
-rw-r--r--src/com/android/gallery3d/data/LocalMergeAlbum.java30
-rw-r--r--src/com/android/gallery3d/data/MediaSet.java87
-rw-r--r--src/com/android/gallery3d/data/MediaSetWrapper.java47
-rw-r--r--src/com/android/gallery3d/data/SecureAlbum.java13
-rw-r--r--src/com/android/gallery3d/data/SingleItemAlbum.java9
-rw-r--r--src/com/android/gallery3d/data/SnailAlbum.java13
-rw-r--r--src/com/android/gallery3d/gadget/MediaSetSource.java2
-rw-r--r--src_pd/com/android/gallery3d/picasasource/PicasaSource.java8
-rw-r--r--tests/src/com/android/gallery3d/data/LocalDataTest.java6
-rw-r--r--tests/src/com/android/gallery3d/data/MockSet.java9
-rw-r--r--tests/src/com/android/gallery3d/data/RealDataTest.java6
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, "");
}