OSDN Git Service

Fix for blank Gallery widgets on a DB upgrade
authorMangesh Ghiware <mghiware@google.com>
Wed, 24 Apr 2013 00:37:15 +0000 (17:37 -0700)
committerMangesh Ghiware <mghiware@google.com>
Wed, 24 Apr 2013 20:24:43 +0000 (13:24 -0700)
Bug: 8660303
Change-Id: I06910ab0811d5f71ba6849d53ddc03c008fc77ad

src/com/android/gallery3d/gadget/MediaSetSource.java
src/com/android/gallery3d/gadget/WidgetService.java

index caeff2a..458651c 100644 (file)
@@ -22,93 +22,212 @@ import android.os.Binder;
 
 import com.android.gallery3d.common.Utils;
 import com.android.gallery3d.data.ContentListener;
+import com.android.gallery3d.data.DataManager;
 import com.android.gallery3d.data.MediaItem;
 import com.android.gallery3d.data.MediaObject;
 import com.android.gallery3d.data.MediaSet;
+import com.android.gallery3d.data.Path;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 
 public class MediaSetSource implements WidgetSource, ContentListener {
-    private static final int CACHE_SIZE = 32;
-
-    @SuppressWarnings("unused")
     private static final String TAG = "MediaSetSource";
 
-    private MediaSet mSource;
-    private MediaItem mCache[] = new MediaItem[CACHE_SIZE];
-    private int mCacheStart;
-    private int mCacheEnd;
-    private long mSourceVersion = MediaObject.INVALID_DATA_VERSION;
+    private DataManager mDataManager;
+    private Path mAlbumPath;
+
+    private WidgetSource mSource;
 
-    private ContentListener mContentListener;
+    private MediaSet mRootSet;
+    private ContentListener mListener;
+
+    public MediaSetSource(DataManager manager, String albumPath) {
+        MediaSet mediaSet = (MediaSet) manager.getMediaObject(albumPath);
+        if (mediaSet != null) {
+            mSource = new CheckedMediaSetSource(mediaSet);
+            return;
+        }
 
-    public MediaSetSource(MediaSet source) {
-        mSource = Utils.checkNotNull(source);
-        mSource.addContentListener(this);
+        // Initialize source to an empty source until the album path can be resolved
+        mDataManager = Utils.checkNotNull(manager);
+        mAlbumPath = Path.fromString(albumPath);
+        mSource = new EmptySource();
+        monitorRootPath();
     }
 
     @Override
-    public void close() {
-        mSource.removeContentListener(this);
+    public int size() {
+        return mSource.size();
     }
 
-    private void ensureCacheRange(int index) {
-        if (index >= mCacheStart && index < mCacheEnd) return;
-
-        long token = Binder.clearCallingIdentity();
-        try {
-            mCacheStart = index;
-            ArrayList<MediaItem> items = mSource.getMediaItem(mCacheStart, CACHE_SIZE);
-            mCacheEnd = mCacheStart + items.size();
-            items.toArray(mCache);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
+    @Override
+    public Bitmap getImage(int index) {
+        return mSource.getImage(index);
     }
 
     @Override
-    public synchronized Uri getContentUri(int index) {
-        ensureCacheRange(index);
-        if (index < mCacheStart || index >= mCacheEnd) return null;
-        return mCache[index - mCacheStart].getContentUri();
+    public Uri getContentUri(int index) {
+        return mSource.getContentUri(index);
     }
 
     @Override
-    public synchronized Bitmap getImage(int index) {
-        ensureCacheRange(index);
-        if (index < mCacheStart || index >= mCacheEnd) return null;
-        return WidgetUtils.createWidgetBitmap(mCache[index - mCacheStart]);
+    public synchronized void setContentListener(ContentListener listener) {
+        if (mRootSet != null) {
+            mListener = listener;
+        } else {
+            mSource.setContentListener(listener);
+        }
     }
 
     @Override
     public void reload() {
-        long version = mSource.reload();
-        if (mSourceVersion != version) {
-            mSourceVersion = version;
-            mCacheStart = 0;
-            mCacheEnd = 0;
-            Arrays.fill(mCache, null);
-        }
+        mSource.reload();
     }
 
     @Override
-    public void setContentListener(ContentListener listener) {
-        mContentListener = listener;
+    public void close() {
+        mSource.close();
     }
 
     @Override
-    public int size() {
-        long token = Binder.clearCallingIdentity();
-        try {
-            return mSource.getMediaItemCount();
-        } finally {
-            Binder.restoreCallingIdentity(token);
+    public void onContentDirty() {
+        resolveAlbumPath();
+    }
+
+    private void monitorRootPath() {
+        String rootPath = mDataManager.getTopSetPath(DataManager.INCLUDE_ALL);
+        mRootSet = (MediaSet) mDataManager.getMediaObject(rootPath);
+        mRootSet.addContentListener(this);
+    }
+
+    private synchronized void resolveAlbumPath() {
+        if (mDataManager == null) return;
+        MediaSet mediaSet = (MediaSet) mDataManager.getMediaObject(mAlbumPath);
+        if (mediaSet != null) {
+            // Clear the reference instead of removing the listener
+            // to get around a concurrent modification exception.
+            mRootSet = null;
+
+            mSource = new CheckedMediaSetSource(mediaSet);
+            if (mListener != null) {
+                mListener.onContentDirty();
+                mSource.setContentListener(mListener);
+                mListener = null;
+            }
+            mDataManager = null;
+            mAlbumPath = null;
         }
     }
 
-    @Override
-    public void onContentDirty() {
-        if (mContentListener != null) mContentListener.onContentDirty();
+    private static class CheckedMediaSetSource implements WidgetSource, ContentListener {
+        private static final int CACHE_SIZE = 32;
+
+        @SuppressWarnings("unused")
+        private static final String TAG = "CheckedMediaSetSource";
+
+        private MediaSet mSource;
+        private MediaItem mCache[] = new MediaItem[CACHE_SIZE];
+        private int mCacheStart;
+        private int mCacheEnd;
+        private long mSourceVersion = MediaObject.INVALID_DATA_VERSION;
+
+        private ContentListener mContentListener;
+
+        public CheckedMediaSetSource(MediaSet source) {
+            mSource = Utils.checkNotNull(source);
+            mSource.addContentListener(this);
+        }
+
+        @Override
+        public void close() {
+            mSource.removeContentListener(this);
+        }
+
+        private void ensureCacheRange(int index) {
+            if (index >= mCacheStart && index < mCacheEnd) return;
+
+            long token = Binder.clearCallingIdentity();
+            try {
+                mCacheStart = index;
+                ArrayList<MediaItem> items = mSource.getMediaItem(mCacheStart, CACHE_SIZE);
+                mCacheEnd = mCacheStart + items.size();
+                items.toArray(mCache);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public synchronized Uri getContentUri(int index) {
+            ensureCacheRange(index);
+            if (index < mCacheStart || index >= mCacheEnd) return null;
+            return mCache[index - mCacheStart].getContentUri();
+        }
+
+        @Override
+        public synchronized Bitmap getImage(int index) {
+            ensureCacheRange(index);
+            if (index < mCacheStart || index >= mCacheEnd) return null;
+            return WidgetUtils.createWidgetBitmap(mCache[index - mCacheStart]);
+        }
+
+        @Override
+        public void reload() {
+            long version = mSource.reload();
+            if (mSourceVersion != version) {
+                mSourceVersion = version;
+                mCacheStart = 0;
+                mCacheEnd = 0;
+                Arrays.fill(mCache, null);
+            }
+        }
+
+        @Override
+        public void setContentListener(ContentListener listener) {
+            mContentListener = listener;
+        }
+
+        @Override
+        public int size() {
+            long token = Binder.clearCallingIdentity();
+            try {
+                return mSource.getMediaItemCount();
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void onContentDirty() {
+            if (mContentListener != null) mContentListener.onContentDirty();
+        }
+    }
+
+    private static class EmptySource implements WidgetSource {
+
+        @Override
+        public int size() {
+            return 0;
+        }
+
+        @Override
+        public Bitmap getImage(int index) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Uri getContentUri(int index) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void setContentListener(ContentListener listener) {}
+
+        @Override
+        public void reload() {}
+
+        @Override
+        public void close() {}
     }
 }
index 334b15a..94dd164 100644 (file)
@@ -28,9 +28,6 @@ import com.android.gallery3d.R;
 import com.android.gallery3d.app.GalleryApp;
 import com.android.gallery3d.common.ApiHelper;
 import com.android.gallery3d.data.ContentListener;
-import com.android.gallery3d.data.DataManager;
-import com.android.gallery3d.data.MediaSet;
-import com.android.gallery3d.data.Path;
 
 @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
 public class WidgetService extends RemoteViewsService {
@@ -52,33 +49,6 @@ public class WidgetService extends RemoteViewsService {
                 id, type, albumPath);
     }
 
-    private static class EmptySource implements WidgetSource {
-
-        @Override
-        public int size() {
-            return 0;
-        }
-
-        @Override
-        public Bitmap getImage(int index) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public Uri getContentUri(int index) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public void setContentListener(ContentListener listener) {}
-
-        @Override
-        public void reload() {}
-
-        @Override
-        public void close() {}
-    }
-
     private static class PhotoRVFactory implements
             RemoteViewsService.RemoteViewsFactory, ContentListener {
 
@@ -99,12 +69,7 @@ public class WidgetService extends RemoteViewsService {
         @Override
         public void onCreate() {
             if (mType == WidgetDatabaseHelper.TYPE_ALBUM) {
-                Path path = Path.fromString(mAlbumPath);
-                DataManager manager = mApp.getDataManager();
-                MediaSet mediaSet = (MediaSet) manager.getMediaObject(path);
-                mSource = mediaSet == null
-                        ? new EmptySource()
-                        : new MediaSetSource(mediaSet);
+                mSource = new MediaSetSource(mApp.getDataManager(), mAlbumPath);
             } else {
                 mSource = new LocalPhotoSource(mApp.getAndroidContext());
             }