summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/data
diff options
context:
space:
mode:
authorOwen Lin <owenlin@google.com>2012-03-21 18:23:38 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-03-21 18:23:38 -0700
commit1955a95dabfab2a8320a99984ab482ef48c10783 (patch)
tree8c6d631b8852a08e38cde6f130f8e918ec83ceec /src/com/android/gallery3d/data
parent04ac045bf8da5082bbb0bdc9ea5f9c9b5b796ad0 (diff)
parentaa6ac7f6ce0e1cab5b36e6bba97d2fec082f4759 (diff)
downloadandroid_packages_apps_Gallery2-1955a95dabfab2a8320a99984ab482ef48c10783.tar.gz
android_packages_apps_Gallery2-1955a95dabfab2a8320a99984ab482ef48c10783.tar.bz2
android_packages_apps_Gallery2-1955a95dabfab2a8320a99984ab482ef48c10783.zip
Merge changes I1acef9fc,I53ddb3cd
* changes: Make top level albums can be loaded concurrently. Add log to debug loading time.
Diffstat (limited to 'src/com/android/gallery3d/data')
-rw-r--r--src/com/android/gallery3d/data/LocalAlbumSet.java138
-rw-r--r--src/com/android/gallery3d/data/MtpDeviceSet.java72
2 files changed, 135 insertions, 75 deletions
diff --git a/src/com/android/gallery3d/data/LocalAlbumSet.java b/src/com/android/gallery3d/data/LocalAlbumSet.java
index 35d87d765..0575e9b65 100644
--- a/src/com/android/gallery3d/data/LocalAlbumSet.java
+++ b/src/com/android/gallery3d/data/LocalAlbumSet.java
@@ -24,19 +24,24 @@ import android.provider.MediaStore.Files.FileColumns;
import android.provider.MediaStore.Images;
import android.provider.MediaStore.Images.ImageColumns;
import android.provider.MediaStore.Video;
+import android.util.Log;
import com.android.gallery3d.R;
import com.android.gallery3d.app.GalleryApp;
import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.util.GalleryUtils;
+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 {
+public class LocalAlbumSet extends MediaSet
+ implements FutureListener<ArrayList<MediaSet>> {
public static final Path PATH_ALL = Path.fromString("/local/all");
public static final Path PATH_IMAGE = Path.fromString("/local/image");
public static final Path PATH_VIDEO = Path.fromString("/local/video");
@@ -93,6 +98,8 @@ public class LocalAlbumSet extends MediaSet {
private final ChangeNotifier mNotifierImage;
private final ChangeNotifier mNotifierVideo;
private final String mName;
+ private Future<ArrayList<MediaSet>> mLoadTask;
+ private ArrayList<MediaSet> mLoadBuffer;
public LocalAlbumSet(Path path, GalleryApp application) {
super(path, nextVersionNumber());
@@ -130,7 +137,16 @@ public class LocalAlbumSet extends MediaSet {
return mName;
}
- private BucketEntry[] loadBucketEntries(Cursor cursor) {
+ private BucketEntry[] loadBucketEntries(JobContext jc) {
+ Uri uri = mBaseUri;
+
+ Log.v("DebugLoadingTime", "start quering media provider");
+ Cursor cursor = mApplication.getContentResolver().query(
+ uri, PROJECTION_BUCKET, BUCKET_GROUP_BY, null, BUCKET_ORDER_BY);
+ if (cursor == null) {
+ Log.w(TAG, "cannot open local database: " + uri);
+ return new BucketEntry[0];
+ }
ArrayList<BucketEntry> buffer = new ArrayList<BucketEntry>();
int typeBits = 0;
if ((mType & MEDIA_TYPE_IMAGE) != 0) {
@@ -149,7 +165,9 @@ public class LocalAlbumSet extends MediaSet {
buffer.add(entry);
}
}
+ if (jc.isCancelled()) return null;
}
+ Log.v("DebugLoadingTime", "got " + buffer.size() + " buckets");
} finally {
cursor.close();
}
@@ -164,62 +182,60 @@ public class LocalAlbumSet extends MediaSet {
return -1;
}
- @SuppressWarnings("unchecked")
- protected ArrayList<MediaSet> loadSubMediaSets() {
- // Note: it will be faster if we only select media_type and bucket_id.
- // need to test the performance if that is worth
+ private class AlbumsLoader implements ThreadPool.Job<ArrayList<MediaSet>> {
- Uri uri = mBaseUri;
- GalleryUtils.assertNotInRenderThread();
- Cursor cursor = mApplication.getContentResolver().query(
- uri, PROJECTION_BUCKET, BUCKET_GROUP_BY, null, BUCKET_ORDER_BY);
- if (cursor == null) {
- Log.w(TAG, "cannot open local database: " + uri);
- return new ArrayList<MediaSet>();
- }
- BucketEntry[] entries = loadBucketEntries(cursor);
- 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);
- }
+ @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 = loadBucketEntries(jc);
+
+ 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) {
- albums.add(getLocalAlbum(dataManager,
- mType, mPath, entry.bucketId, entry.bucketName));
- }
- for (int i = 0, n = albums.size(); i < n; ++i) {
- albums.get(i).reload();
+ ArrayList<MediaSet> albums = new ArrayList<MediaSet>();
+ DataManager dataManager = mApplication.getDataManager();
+ for (BucketEntry entry : entries) {
+ MediaSet album = getLocalAlbum(dataManager,
+ mType, mPath, entry.bucketId, entry.bucketName);
+ album.reload();
+ albums.add(album);
+ }
+ return albums;
}
- return albums;
}
private MediaSet getLocalAlbum(
DataManager manager, int type, Path parent, int id, String name) {
- Path path = parent.getChild(id);
- MediaObject object = manager.peekMediaObject(path);
- if (object != null) return (MediaSet) object;
- switch (type) {
- case MEDIA_TYPE_IMAGE:
- return new LocalAlbum(path, mApplication, id, true, name);
- case MEDIA_TYPE_VIDEO:
- return new LocalAlbum(path, mApplication, id, false, name);
- case MEDIA_TYPE_ALL:
- Comparator<MediaItem> comp = DataManager.sDateTakenComparator;
- return new LocalMergeAlbum(path, comp, new MediaSet[] {
- getLocalAlbum(manager, MEDIA_TYPE_IMAGE, PATH_IMAGE, id, name),
- getLocalAlbum(manager, MEDIA_TYPE_VIDEO, PATH_VIDEO, id, name)}, id);
+ synchronized (DataManager.LOCK) {
+ Path path = parent.getChild(id);
+ MediaObject object = manager.peekMediaObject(path);
+ if (object != null) return (MediaSet) object;
+ switch (type) {
+ case MEDIA_TYPE_IMAGE:
+ return new LocalAlbum(path, mApplication, id, true, name);
+ case MEDIA_TYPE_VIDEO:
+ return new LocalAlbum(path, mApplication, id, false, name);
+ case MEDIA_TYPE_ALL:
+ Comparator<MediaItem> comp = DataManager.sDateTakenComparator;
+ return new LocalMergeAlbum(path, comp, new MediaSet[] {
+ getLocalAlbum(manager, MEDIA_TYPE_IMAGE, PATH_IMAGE, id, name),
+ getLocalAlbum(manager, MEDIA_TYPE_VIDEO, PATH_VIDEO, id, name)}, id);
+ }
+ throw new IllegalArgumentException(String.valueOf(type));
}
- throw new IllegalArgumentException(String.valueOf(type));
}
public static String getBucketName(ContentResolver resolver, int bucketId) {
@@ -245,15 +261,31 @@ public class LocalAlbumSet extends MediaSet {
}
@Override
- public long reload() {
+ // synchronized on this function for
+ // 1. Prevent calling reload() concurrently.
+ // 2. Prevent calling onFutureDone() and reload() concurrently
+ public synchronized long reload() {
// "|" is used instead of "||" because we want to clear both flags.
if (mNotifierImage.isDirty() | mNotifierVideo.isDirty()) {
+ if (mLoadTask != null) mLoadTask.cancel();
+ mLoadTask = mApplication.getThreadPool().submit(new AlbumsLoader(), this);
+ }
+ if (mLoadBuffer != null) {
+ mAlbums = mLoadBuffer;
+ mLoadBuffer = null;
mDataVersion = nextVersionNumber();
- mAlbums = loadSubMediaSets();
}
return mDataVersion;
}
+ @Override
+ public synchronized void onFutureDone(Future<ArrayList<MediaSet>> future) {
+ if (mLoadTask != future) return; // ignore, wait for the latest task
+ mLoadBuffer = future.get();
+ if (mLoadBuffer == null) mLoadBuffer = new ArrayList<MediaSet>();
+ notifyContentChanged();
+ }
+
// For debug only. Fake there is a ContentObserver.onChange() event.
void fakeChange() {
mNotifierImage.fakeChange();
diff --git a/src/com/android/gallery3d/data/MtpDeviceSet.java b/src/com/android/gallery3d/data/MtpDeviceSet.java
index 0d0e67ec3..dd79bc1cb 100644
--- a/src/com/android/gallery3d/data/MtpDeviceSet.java
+++ b/src/com/android/gallery3d/data/MtpDeviceSet.java
@@ -22,22 +22,30 @@ import android.util.Log;
import com.android.gallery3d.R;
import com.android.gallery3d.app.GalleryApp;
+import com.android.gallery3d.util.Future;
+import com.android.gallery3d.util.FutureListener;
import com.android.gallery3d.util.MediaSetUtils;
+import com.android.gallery3d.util.ThreadPool.Job;
+import com.android.gallery3d.util.ThreadPool.JobContext;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
// MtpDeviceSet -- MtpDevice -- MtpImage
-public class MtpDeviceSet extends MediaSet {
+public class MtpDeviceSet extends MediaSet
+ implements FutureListener<ArrayList<MediaSet>> {
private static final String TAG = "MtpDeviceSet";
private GalleryApp mApplication;
- private final ArrayList<MediaSet> mDeviceSet = new ArrayList<MediaSet>();
private final ChangeNotifier mNotifier;
private final MtpContext mMtpContext;
private final String mName;
+ private Future<ArrayList<MediaSet>> mLoadTask;
+ private ArrayList<MediaSet> mDeviceSet = new ArrayList<MediaSet>();
+ private ArrayList<MediaSet> mLoadBuffer;
+
public MtpDeviceSet(Path path, GalleryApp application, MtpContext mtpContext) {
super(path, nextVersionNumber());
mApplication = application;
@@ -46,26 +54,33 @@ public class MtpDeviceSet extends MediaSet {
mName = application.getResources().getString(R.string.set_label_mtp_devices);
}
- private void loadDevices() {
- DataManager dataManager = mApplication.getDataManager();
- // Enumerate all devices
- mDeviceSet.clear();
- List<android.mtp.MtpDevice> devices = mMtpContext.getMtpClient().getDeviceList();
- Log.v(TAG, "loadDevices: " + devices + ", size=" + devices.size());
- for (android.mtp.MtpDevice mtpDevice : devices) {
- int deviceId = mtpDevice.getDeviceId();
- Path childPath = mPath.getChild(deviceId);
- MtpDevice device = (MtpDevice) dataManager.peekMediaObject(childPath);
- if (device == null) {
- device = new MtpDevice(childPath, mApplication, deviceId, mMtpContext);
+ private class DevicesLoader implements Job<ArrayList<MediaSet>> {
+ @Override
+ public ArrayList<MediaSet> run(JobContext jc) {
+ DataManager dataManager = mApplication.getDataManager();
+ ArrayList<MediaSet> result = new ArrayList<MediaSet>();
+
+ // Enumerate all devices
+ List<android.mtp.MtpDevice> devices = mMtpContext.getMtpClient().getDeviceList();
+ Log.v(TAG, "loadDevices: " + devices + ", size=" + devices.size());
+ for (android.mtp.MtpDevice mtpDevice : devices) {
+ synchronized (DataManager.LOCK) {
+ int deviceId = mtpDevice.getDeviceId();
+ Path childPath = mPath.getChild(deviceId);
+ MtpDevice device = (MtpDevice) dataManager.peekMediaObject(childPath);
+ if (device == null) {
+ device = new MtpDevice(childPath, mApplication, deviceId, mMtpContext);
+ }
+ Log.d(TAG, "add device " + device);
+ result.add(device);
+ }
}
- Log.d(TAG, "add device " + device);
- mDeviceSet.add(device);
- }
+ Collections.sort(result, MediaSetUtils.NAME_COMPARATOR);
- Collections.sort(mDeviceSet, MediaSetUtils.NAME_COMPARATOR);
- for (int i = 0, n = mDeviceSet.size(); i < n; i++) {
- mDeviceSet.get(i).reload();
+ for (int i = 0, n = result.size(); i < n; ++i) {
+ result.get(i).reload();
+ }
+ return result;
}
}
@@ -99,11 +114,24 @@ public class MtpDeviceSet extends MediaSet {
}
@Override
- public long reload() {
+ public synchronized long reload() {
if (mNotifier.isDirty()) {
+ if (mLoadTask != null) mLoadTask.cancel();
+ mLoadTask = mApplication.getThreadPool().submit(new DevicesLoader(), this);
+ }
+ if (mLoadBuffer != null) {
+ mDeviceSet = mLoadBuffer;
+ mLoadBuffer = null;
mDataVersion = nextVersionNumber();
- loadDevices();
}
return mDataVersion;
}
+
+ @Override
+ public synchronized void onFutureDone(Future<ArrayList<MediaSet>> future) {
+ if (future != mLoadTask) return;
+ mLoadBuffer = future.get();
+ if (mLoadBuffer == null) mLoadBuffer = new ArrayList<MediaSet>();
+ notifyContentChanged();
+ }
}