MediaFeed.java revision 71660902f0aa83113bf11a2933e92b08c524fed5
1f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparkspackage com.cooliris.media;
2f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
3f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparksimport java.util.ArrayList;
4f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparksimport java.util.HashMap;
5897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnarajimport java.util.HashSet;
6f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
7897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnarajimport android.content.ContentResolver;
8f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparksimport android.content.Context;
9897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnarajimport android.database.ContentObserver;
101c729acdafe147abda6b3479eafb17607f172780Venkatimport android.util.Log;
11f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparksimport android.view.Gravity;
12f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparksimport android.widget.Toast;
13897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnarajimport android.net.Uri;
14897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnarajimport android.os.Handler;
15f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparksimport android.os.Process;
16f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
17d93f177bf2bc26f4ad64ca2f7725da8b0347a77fVenkatimport com.cooliris.app.App;
1829dcedb79b7eb9e3d65adc5d2ea95c1dd5c01df9Chih-Chung Changimport com.cooliris.app.Res;
19f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparksimport com.cooliris.media.MediaClustering.Cluster;
20f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
21f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparkspublic final class MediaFeed implements Runnable {
221c729acdafe147abda6b3479eafb17607f172780Venkat    private final String TAG = "MediaFeed";
23f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public static final int OPERATION_DELETE = 0;
24f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public static final int OPERATION_ROTATE = 1;
25f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public static final int OPERATION_CROP = 2;
26f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
27f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private static final int NUM_ITEMS_LOOKAHEAD = 60;
28f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
29f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private IndexRange mVisibleRange = new IndexRange();
30f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private IndexRange mBufferedRange = new IndexRange();
31f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private ArrayList<MediaSet> mMediaSets = new ArrayList<MediaSet>();
32f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private Listener mListener;
33f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private DataSource mDataSource;
34f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private boolean mListenerNeedsUpdate = false;
35d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks    private boolean mMediaFeedNeedsToRun = false;
36f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private MediaSet mSingleWrapper = new MediaSet();
37f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private boolean mInClusteringMode = false;
38f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private HashMap<MediaSet, MediaClustering> mClusterSets = new HashMap<MediaSet, MediaClustering>(32);
39f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private int mExpandedMediaSetIndex = Shared.INVALID;
40f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private MediaFilter mMediaFilter;
41f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private MediaSet mMediaFilteredSet;
42f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private Context mContext;
43f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private Thread mDataSourceThread = null;
44f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private Thread mAlbumSourceThread = null;
45f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private boolean mListenerNeedsLayout;
46f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private boolean mWaitingForMediaScanner;
47f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private boolean mSingleImageMode;
48f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private boolean mLoading;
49897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj    private HashMap<String, ContentObserver> mContentObservers = new HashMap<String, ContentObserver>();
5062dd11281ef6e12049dd6798b184157e9583d7d4Venkat    private ArrayList<String[]> mRequestedRefresh = new ArrayList<String[]>();
51f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
52f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public interface Listener {
53f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        public abstract void onFeedAboutToChange(MediaFeed feed);
5462dd11281ef6e12049dd6798b184157e9583d7d4Venkat
55f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        public abstract void onFeedChanged(MediaFeed feed, boolean needsLayout);
56f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
57f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
58f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public MediaFeed(Context context, DataSource dataSource, Listener listener) {
59f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mContext = context;
60f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mListener = listener;
61f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mDataSource = dataSource;
62f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mSingleWrapper.setNumExpectedItems(1);
63f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mLoading = true;
64f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
65d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks
66f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void shutdown() {
67f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mDataSourceThread != null) {
68f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            mDataSource.shutdown();
69f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            mDataSourceThread.interrupt();
70f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            mDataSourceThread = null;
71f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
72f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mAlbumSourceThread != null) {
73f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            mAlbumSourceThread.interrupt();
74f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            mAlbumSourceThread = null;
75f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
76f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        int numSets = mMediaSets.size();
77f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        for (int i = 0; i < numSets; ++i) {
78f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            MediaSet set = mMediaSets.get(i);
79f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            set.clear();
80f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
81f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        synchronized (mMediaSets) {
82f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            mMediaSets.clear();
83f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
84f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        int numClusters = mClusterSets.size();
85f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        for (int i = 0; i < numClusters; ++i) {
86f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            MediaClustering mc = mClusterSets.get(i);
87f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (mc != null) {
88f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                mc.clear();
89f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
90f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
91f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mClusterSets.clear();
92f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mListener = null;
93f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mDataSource = null;
94f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mSingleWrapper = null;
95f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
96f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
97f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void setVisibleRange(int begin, int end) {
98d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        if (begin != mVisibleRange.begin || end != mVisibleRange.end) {
99d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks            mVisibleRange.begin = begin;
100d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks            mVisibleRange.end = end;
101d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks            int numItems = 96;
102d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks            int numItemsBy2 = numItems / 2;
103d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks            int numItemsBy4 = numItems / 4;
104d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks            mBufferedRange.begin = (begin / numItemsBy2) * numItemsBy2 - numItemsBy4;
105d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks            mBufferedRange.end = mBufferedRange.begin + numItems;
106d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks            mMediaFeedNeedsToRun = true;
107d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        }
108f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
109f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
110f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void setFilter(MediaFilter filter) {
111f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mMediaFilter = filter;
112f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mMediaFilteredSet = null;
113f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mListener != null) {
114f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            mListener.onFeedAboutToChange(this);
115f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
116d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        mMediaFeedNeedsToRun = true;
117f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
118f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
119f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void removeFilter() {
120f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mMediaFilter = null;
121f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mMediaFilteredSet = null;
122f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mListener != null) {
123f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            mListener.onFeedAboutToChange(this);
124f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            updateListener(true);
125f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
126d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        mMediaFeedNeedsToRun = true;
127f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
128f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
129f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public ArrayList<MediaSet> getMediaSets() {
130f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return mMediaSets;
131f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
132f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
133d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks    public MediaSet getMediaSet(final long setId) {
134f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (setId != Shared.INVALID) {
135d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks            try {
136d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                int mMediaSetsSize = mMediaSets.size();
137d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                for (int i = 0; i < mMediaSetsSize; i++) {
1381b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj                    final MediaSet set = mMediaSets.get(i);
1391b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj                    if (set.mId == setId) {
1401b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj                        set.mFlagForDelete = false;
1411b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj                        return set;
142d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                    }
143f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
144d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks            } catch (Exception e) {
145d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                return null;
146f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
147f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
148f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return null;
149f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
150f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
151f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public MediaSet getFilteredSet() {
152f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return mMediaFilteredSet;
153f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
154f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
155f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public MediaSet addMediaSet(final long setId, DataSource dataSource) {
156f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        MediaSet mediaSet = new MediaSet(dataSource);
157f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mediaSet.mId = setId;
158f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mMediaSets.add(mediaSet);
159d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        if (mDataSourceThread != null && !mDataSourceThread.isAlive()) {
160d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks            mDataSourceThread.start();
161d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        }
162d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        mMediaFeedNeedsToRun = true;
163f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return mediaSet;
164f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
165f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
166f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public DataSource getDataSource() {
167f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return mDataSource;
168f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
169f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
170f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public MediaClustering getClustering() {
171f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mExpandedMediaSetIndex != Shared.INVALID && mExpandedMediaSetIndex < mMediaSets.size()) {
172f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            return mClusterSets.get(mMediaSets.get(mExpandedMediaSetIndex));
173f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
174f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return null;
175f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
176f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
177f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public ArrayList<Cluster> getClustersForSet(final MediaSet set) {
178f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        ArrayList<Cluster> clusters = null;
179f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mClusterSets != null && mClusterSets.containsKey(set)) {
180f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            MediaClustering mediaClustering = mClusterSets.get(set);
181f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (mediaClustering != null) {
182f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                clusters = mediaClustering.getClusters();
183f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
184f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
185f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return clusters;
186f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
187f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
188f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void addItemToMediaSet(MediaItem item, MediaSet mediaSet) {
189f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        item.mParentMediaSet = mediaSet;
190f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mediaSet.addItem(item);
191d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        synchronized (mClusterSets) {
192f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (item.mClusteringState == MediaItem.NOT_CLUSTERED) {
193f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                MediaClustering clustering = mClusterSets.get(mediaSet);
194f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                if (clustering == null) {
195f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    clustering = new MediaClustering(mediaSet.isPicassaAlbum());
196f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    mClusterSets.put(mediaSet, clustering);
197f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
198f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                clustering.setTimeRange(mediaSet.mMaxTimestamp - mediaSet.mMinTimestamp, mediaSet.getNumExpectedItems());
199f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                clustering.addItemForClustering(item);
200f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                item.mClusteringState = MediaItem.CLUSTERED;
201f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
202f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
203d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        mMediaFeedNeedsToRun = true;
204f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
205f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
206f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void performOperation(final int operation, final ArrayList<MediaBucket> mediaBuckets, final Object data) {
207f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        int numBuckets = mediaBuckets.size();
208f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        final ArrayList<MediaBucket> copyMediaBuckets = new ArrayList<MediaBucket>(numBuckets);
209f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        for (int i = 0; i < numBuckets; ++i) {
210f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            copyMediaBuckets.add(mediaBuckets.get(i));
211f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
212f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (operation == OPERATION_DELETE && mListener != null) {
213f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            mListener.onFeedAboutToChange(this);
214f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
215f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        Thread operationThread = new Thread(new Runnable() {
216f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            public void run() {
217f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                ArrayList<MediaBucket> mediaBuckets = copyMediaBuckets;
218f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                if (operation == OPERATION_DELETE) {
219f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    int numBuckets = mediaBuckets.size();
220f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    for (int i = 0; i < numBuckets; ++i) {
221f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        MediaBucket bucket = mediaBuckets.get(i);
222f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        MediaSet set = bucket.mediaSet;
223f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        ArrayList<MediaItem> items = bucket.mediaItems;
224f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        if (set != null && items == null) {
225f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            // Remove the entire bucket.
226f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            removeMediaSet(set);
227f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        } else if (set != null && items != null) {
228f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            // We need to remove these items from the set.
229f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            int numItems = items.size();
2301bb0c42b2a62f580eea4764d6a4434ffecfbf353Dave Sparks                            // We also need to delete the items from the
2311bb0c42b2a62f580eea4764d6a4434ffecfbf353Dave Sparks                            // cluster.
232f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            MediaClustering clustering = mClusterSets.get(set);
233f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            for (int j = 0; j < numItems; ++j) {
234f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                MediaItem item = items.get(j);
235f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                removeItemFromMediaSet(item, set);
236f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                if (clustering != null) {
237f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    clustering.removeItemFromClustering(item);
238f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                }
239f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            }
240f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            set.updateNumExpectedItems();
241f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            set.generateTitle(true);
242f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        }
243f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    }
244f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    updateListener(true);
245d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                    mMediaFeedNeedsToRun = true;
246f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    if (mDataSource != null) {
247f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        mDataSource.performOperation(OPERATION_DELETE, mediaBuckets, null);
248f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    }
249f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                } else {
250f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    mDataSource.performOperation(operation, mediaBuckets, data);
251f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
252f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
253f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        });
254f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        operationThread.setName("Operation " + operation);
255f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        operationThread.start();
256f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
257f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
258f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void removeMediaSet(MediaSet set) {
2592b04f591f758b7af03c43d90e91b939cbd515506Venkat Krishnaraj        synchronized (mMediaSets) {
2601bb0c42b2a62f580eea4764d6a4434ffecfbf353Dave Sparks            mMediaSets.remove(set);
2612b04f591f758b7af03c43d90e91b939cbd515506Venkat Krishnaraj        }
262d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        mMediaFeedNeedsToRun = true;
263f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
264f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
265f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private void removeItemFromMediaSet(MediaItem item, MediaSet mediaSet) {
266f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mediaSet.removeItem(item);
267d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        synchronized (mClusterSets) {
268f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            MediaClustering clustering = mClusterSets.get(mediaSet);
269f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (clustering != null) {
270f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                clustering.removeItemFromClustering(item);
271f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
272f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
273d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        mMediaFeedNeedsToRun = true;
274f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
275f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
276f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void updateListener(boolean needsLayout) {
277f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mListenerNeedsUpdate = true;
278f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mListenerNeedsLayout = needsLayout;
279f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
280f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
281f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public int getNumSlots() {
282f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        int currentMediaSetIndex = mExpandedMediaSetIndex;
283f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        ArrayList<MediaSet> mediaSets = mMediaSets;
284f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        int mediaSetsSize = mediaSets.size();
285f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
286f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mInClusteringMode == false) {
287f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (currentMediaSetIndex == Shared.INVALID || currentMediaSetIndex >= mediaSetsSize) {
288f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                return mediaSetsSize;
289f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            } else {
290f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                MediaSet setToUse = (mMediaFilteredSet == null) ? mediaSets.get(currentMediaSetIndex) : mMediaFilteredSet;
2915e0474e8e1942c41234eb251f948c2fbb7445b02Venkat Krishnaraj                return setToUse.getNumExpectedItems();
292f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
293f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        } else if (currentMediaSetIndex != Shared.INVALID && currentMediaSetIndex < mediaSetsSize) {
294f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            MediaSet set = mediaSets.get(currentMediaSetIndex);
295f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            MediaClustering clustering = mClusterSets.get(set);
296f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (clustering != null) {
297f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                return clustering.getClustersForDisplay().size();
298f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
299f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
300f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return 0;
301f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
30262dd11281ef6e12049dd6798b184157e9583d7d4Venkat
30388dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat    public ArrayList<Integer> getBreaks() {
30488dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat        if (true)
30588dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat            return null;
30688dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat        int currentMediaSetIndex = mExpandedMediaSetIndex;
30788dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat        ArrayList<MediaSet> mediaSets = mMediaSets;
30888dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat        int mediaSetsSize = mediaSets.size();
30988dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat        if (currentMediaSetIndex == Shared.INVALID || currentMediaSetIndex >= mediaSetsSize)
31088dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat            return null;
31188dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat        MediaSet set = mediaSets.get(currentMediaSetIndex);
31288dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat        MediaClustering clustering = mClusterSets.get(set);
31388dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat        if (clustering != null) {
31488dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat            clustering.compute(null, true);
31588dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat            final ArrayList<Cluster> clusters = clustering.getClustersForDisplay();
31688dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat            int numClusters = clusters.size();
31788dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat            final ArrayList<Integer> retVal = new ArrayList<Integer>(numClusters);
31888dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat            int size = 0;
31988dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat            for (int i = 0; i < numClusters; ++i) {
32088dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat                size += clusters.get(i).getItems().size();
32188dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat                retVal.add(size);
32288dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat            }
32388dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat            return retVal;
32488dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat        } else {
32588dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat            return null;
32688dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat        }
32788dc4ec391fdd373821aa94ae93ca0c231eb98bbVenkat    }
328f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
329f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public MediaSet getSetForSlot(int slotIndex) {
330f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (slotIndex < 0) {
331f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            return null;
332f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
333f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
334f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        ArrayList<MediaSet> mediaSets = mMediaSets;
335f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        int mediaSetsSize = mediaSets.size();
336f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        int currentMediaSetIndex = mExpandedMediaSetIndex;
337f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
338f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mInClusteringMode == false) {
339f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (currentMediaSetIndex == Shared.INVALID || currentMediaSetIndex >= mediaSetsSize) {
340f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                if (slotIndex >= mediaSetsSize) {
341f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    return null;
342f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
343f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                return mMediaSets.get(slotIndex);
344f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
345f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (mSingleWrapper.getNumItems() == 0) {
346f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                mSingleWrapper.addItem(null);
347f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
348f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            MediaSet setToUse = (mMediaFilteredSet == null) ? mMediaSets.get(currentMediaSetIndex) : mMediaFilteredSet;
349f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            ArrayList<MediaItem> items = setToUse.getItems();
350f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (slotIndex >= setToUse.getNumItems()) {
351f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                return null;
352f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
353f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            mSingleWrapper.getItems().set(0, items.get(slotIndex));
354f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            return mSingleWrapper;
355f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        } else if (currentMediaSetIndex != Shared.INVALID && currentMediaSetIndex < mediaSetsSize) {
356f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            MediaSet set = mediaSets.get(currentMediaSetIndex);
357f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            MediaClustering clustering = mClusterSets.get(set);
358f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (clustering != null) {
359f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                ArrayList<MediaClustering.Cluster> clusters = clustering.getClustersForDisplay();
360f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                if (clusters.size() > slotIndex) {
361f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    MediaClustering.Cluster cluster = clusters.get(slotIndex);
362f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    cluster.generateCaption(mContext);
363f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    return cluster;
364f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
365f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
366f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
367f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return null;
368f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
369f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
370f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public boolean getWaitingForMediaScanner() {
371f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return mWaitingForMediaScanner;
372f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
373d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks
374f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public boolean isLoading() {
375f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return mLoading;
376f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
377f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
378f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void start() {
379f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        final MediaFeed feed = this;
38062f6a6a2e299c0706bfd0d4a0bca0ef1b10d3f37Venkat        onResume();
381f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mLoading = true;
382d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        mDataSourceThread = new Thread(this);
383d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        mDataSourceThread.setName("MediaFeed");
384f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mAlbumSourceThread = new Thread(new Runnable() {
385f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            public void run() {
386f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                if (mContext == null)
387f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    return;
388f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
389f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                DataSource dataSource = mDataSource;
3901bb0c42b2a62f580eea4764d6a4434ffecfbf353Dave Sparks                // We must wait while the SD card is mounted or the MediaScanner
3911bb0c42b2a62f580eea4764d6a4434ffecfbf353Dave Sparks                // is running.
392d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                if (dataSource != null) {
3931b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj                    loadMediaSets();
394d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                }
395f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                mWaitingForMediaScanner = false;
396f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                while (ImageManager.isMediaScannerScanning(mContext.getContentResolver())) {
397f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    // MediaScanner is still running, wait
39888ed7e72a2a0bfdbef7f72aea2b2ddfd74961bdbVenkat Krishnaraj                    if (Thread.interrupted())
39988ed7e72a2a0bfdbef7f72aea2b2ddfd74961bdbVenkat Krishnaraj                        return;
400f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    mWaitingForMediaScanner = true;
401f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    try {
402f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        if (mContext == null)
403f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            return;
40429dcedb79b7eb9e3d65adc5d2ea95c1dd5c01df9Chih-Chung Chang                        showToast(mContext.getResources().getString(Res.string.initializing), Toast.LENGTH_LONG);
4051b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj                        if (dataSource != null) {
4061b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj                            loadMediaSets();
4071b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj                        }
4081b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj                        Thread.sleep(10000);
409f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    } catch (InterruptedException e) {
41088ed7e72a2a0bfdbef7f72aea2b2ddfd74961bdbVenkat Krishnaraj                        return;
411f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    }
412f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
413f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                if (mWaitingForMediaScanner) {
41429dcedb79b7eb9e3d65adc5d2ea95c1dd5c01df9Chih-Chung Chang                    showToast(mContext.getResources().getString(Res.string.loading_new), Toast.LENGTH_LONG);
415d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                    mWaitingForMediaScanner = false;
4161b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj                    loadMediaSets();
417f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
418f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                mLoading = false;
419f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
420f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        });
421f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mAlbumSourceThread.setName("MediaSets");
422f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mAlbumSourceThread.start();
423f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
424897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj
4251b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj    private void loadMediaSets() {
4261b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj        if (mDataSource == null)
4271b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj            return;
4281b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj        final ArrayList<MediaSet> sets = mMediaSets;
4291b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj        final int numSets = sets.size();
4301b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj        for (int i = 0; i < numSets; ++i) {
4311b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj            final MediaSet set = sets.get(i);
4321b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj            set.mFlagForDelete = true;
4331b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj        }
43462f6a6a2e299c0706bfd0d4a0bca0ef1b10d3f37Venkat        synchronized (sets) {
43562f6a6a2e299c0706bfd0d4a0bca0ef1b10d3f37Venkat            mDataSource.refresh(MediaFeed.this, mDataSource.getDatabaseUris());
43662f6a6a2e299c0706bfd0d4a0bca0ef1b10d3f37Venkat            mDataSource.loadMediaSets(MediaFeed.this);
43762f6a6a2e299c0706bfd0d4a0bca0ef1b10d3f37Venkat        }
4381b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj        for (int i = 0; i < numSets; ++i) {
4391b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj            final MediaSet set = sets.get(i);
4401b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj            if (set.mFlagForDelete) {
4411b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj                removeMediaSet(set);
4421b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj            }
4431b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj        }
4441b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj        updateListener(false);
4451b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj    }
446f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
447f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private void showToast(final String string, final int duration) {
448f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        showToast(string, duration, false);
449f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
450f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
451f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private void showToast(final String string, final int duration, final boolean centered) {
452d93f177bf2bc26f4ad64ca2f7725da8b0347a77fVenkat        if (mContext != null && !App.get(mContext).isPaused()) {
45362f6a6a2e299c0706bfd0d4a0bca0ef1b10d3f37Venkat            App.get(mContext).getHandler().post(new Runnable() {
454f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                public void run() {
455f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    if (mContext != null) {
456f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        Toast toast = Toast.makeText(mContext, string, duration);
457f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        if (centered) {
458f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            toast.setGravity(Gravity.CENTER, 0, 0);
459f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        }
460f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        toast.show();
461f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    }
462f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
463f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            });
464f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
465f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
466f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
467f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void run() {
468f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        DataSource dataSource = mDataSource;
469d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        int sleepMs = 10;
470f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
471f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (dataSource != null) {
472d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks            while (!Thread.interrupted()) {
47362dd11281ef6e12049dd6798b184157e9583d7d4Venkat                String[] databaseUris = null;
47462dd11281ef6e12049dd6798b184157e9583d7d4Venkat                boolean performRefresh = false;
47562dd11281ef6e12049dd6798b184157e9583d7d4Venkat                synchronized (mRequestedRefresh) {
47662dd11281ef6e12049dd6798b184157e9583d7d4Venkat                    if (mRequestedRefresh.size() > 0) {
47762dd11281ef6e12049dd6798b184157e9583d7d4Venkat                        // We prune this first.
47862dd11281ef6e12049dd6798b184157e9583d7d4Venkat                        int numRequests = mRequestedRefresh.size();
47962dd11281ef6e12049dd6798b184157e9583d7d4Venkat                        for (int i = 0; i < numRequests; ++i) {
48062dd11281ef6e12049dd6798b184157e9583d7d4Venkat                            databaseUris = ArrayUtils.addAll(databaseUris, mRequestedRefresh.get(i));
48162dd11281ef6e12049dd6798b184157e9583d7d4Venkat                        }
48262dd11281ef6e12049dd6798b184157e9583d7d4Venkat                        mRequestedRefresh.clear();
48362dd11281ef6e12049dd6798b184157e9583d7d4Venkat                        performRefresh = true;
48462dd11281ef6e12049dd6798b184157e9583d7d4Venkat                        // We need to eliminate duplicate uris in this array
48562dd11281ef6e12049dd6798b184157e9583d7d4Venkat                        final HashMap<String, String> uris = new HashMap<String, String>();
48662dd11281ef6e12049dd6798b184157e9583d7d4Venkat                        if (databaseUris != null) {
48762dd11281ef6e12049dd6798b184157e9583d7d4Venkat                            int numUris = databaseUris.length;
48862dd11281ef6e12049dd6798b184157e9583d7d4Venkat                            for (int i = 0; i < numUris; ++i) {
48962dd11281ef6e12049dd6798b184157e9583d7d4Venkat                                final String uri = databaseUris[i];
49062dd11281ef6e12049dd6798b184157e9583d7d4Venkat                                if (uri != null)
49162dd11281ef6e12049dd6798b184157e9583d7d4Venkat                                    uris.put(uri, uri);
49262dd11281ef6e12049dd6798b184157e9583d7d4Venkat                            }
49362dd11281ef6e12049dd6798b184157e9583d7d4Venkat                        }
49462dd11281ef6e12049dd6798b184157e9583d7d4Venkat                        databaseUris = new String[0];
49562dd11281ef6e12049dd6798b184157e9583d7d4Venkat                        databaseUris = (String[]) uris.keySet().toArray(databaseUris);
49662dd11281ef6e12049dd6798b184157e9583d7d4Venkat                    }
49762dd11281ef6e12049dd6798b184157e9583d7d4Venkat                }
49862dd11281ef6e12049dd6798b184157e9583d7d4Venkat                if (performRefresh) {
4991c729acdafe147abda6b3479eafb17607f172780Venkat                    if (dataSource != null) {
50062dd11281ef6e12049dd6798b184157e9583d7d4Venkat                        dataSource.refresh(this, databaseUris);
50171660902f0aa83113bf11a2933e92b08c524fed5Venkat                        mMediaFeedNeedsToRun = true;
5021c729acdafe147abda6b3479eafb17607f172780Venkat                    }
5031c729acdafe147abda6b3479eafb17607f172780Venkat                }
5041c729acdafe147abda6b3479eafb17607f172780Venkat                if (mListenerNeedsUpdate && !mMediaFeedNeedsToRun) {
505f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    mListenerNeedsUpdate = false;
506f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    if (mListener != null)
507f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        mListener.onFeedChanged(this, mListenerNeedsLayout);
508f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    try {
509f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        Thread.sleep(sleepMs);
510f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    } catch (InterruptedException e) {
511f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        return;
512f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    }
513f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                } else {
514f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    try {
515f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        Thread.sleep(sleepMs);
516f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    } catch (InterruptedException e) {
517f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        return;
518f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    }
519f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
520d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                sleepMs = 300;
521d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                if (!mMediaFeedNeedsToRun)
522d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                    continue;
523d93f177bf2bc26f4ad64ca2f7725da8b0347a77fVenkat                App app = App.get(mContext);
52462f6a6a2e299c0706bfd0d4a0bca0ef1b10d3f37Venkat                if (app == null || app.isPaused())
52562f6a6a2e299c0706bfd0d4a0bca0ef1b10d3f37Venkat                    continue;
526d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                mMediaFeedNeedsToRun = false;
527f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                ArrayList<MediaSet> mediaSets = mMediaSets;
528f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                synchronized (mediaSets) {
529f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    int expandedSetIndex = mExpandedMediaSetIndex;
530f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    if (expandedSetIndex >= mMediaSets.size()) {
531f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        expandedSetIndex = Shared.INVALID;
532f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    }
533f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    if (expandedSetIndex == Shared.INVALID) {
534f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        // We purge the sets outside this visibleRange.
5352b04f591f758b7af03c43d90e91b939cbd515506Venkat Krishnaraj                        int numSets = mediaSets.size();
536f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        IndexRange visibleRange = mVisibleRange;
537f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        IndexRange bufferedRange = mBufferedRange;
538f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        boolean scanMediaSets = true;
539f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        for (int i = 0; i < numSets; ++i) {
540f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            if (i >= visibleRange.begin && i <= visibleRange.end && scanMediaSets) {
541f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                MediaSet set = mediaSets.get(i);
542f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                int numItemsLoaded = set.mNumItemsLoaded;
543f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                if (numItemsLoaded < set.getNumExpectedItems() && numItemsLoaded < 8) {
54462f6a6a2e299c0706bfd0d4a0bca0ef1b10d3f37Venkat                                    synchronized (set) {
54562f6a6a2e299c0706bfd0d4a0bca0ef1b10d3f37Venkat                                        dataSource.loadItemsForSet(this, set, numItemsLoaded, 8);
54662f6a6a2e299c0706bfd0d4a0bca0ef1b10d3f37Venkat                                    }
547f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    if (set.getNumExpectedItems() == 0) {
548f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                        mediaSets.remove(set);
549f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                        break;
550f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    }
551f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    if (mListener != null) {
5521c729acdafe147abda6b3479eafb17607f172780Venkat                                        mListenerNeedsUpdate = false;
5531c729acdafe147abda6b3479eafb17607f172780Venkat                                        mListener.onFeedChanged(this, mListenerNeedsLayout);
5541c729acdafe147abda6b3479eafb17607f172780Venkat                                        mListenerNeedsLayout = false;
555f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    }
556f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    sleepMs = 100;
557f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    scanMediaSets = false;
558f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                }
559d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                                if (!set.setContainsValidItems()) {
560d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                                    mediaSets.remove(set);
561d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                                    if (mListener != null) {
5621c729acdafe147abda6b3479eafb17607f172780Venkat                                        mListenerNeedsUpdate = false;
5631c729acdafe147abda6b3479eafb17607f172780Venkat                                        mListener.onFeedChanged(this, mListenerNeedsLayout);
5641c729acdafe147abda6b3479eafb17607f172780Venkat                                        mListenerNeedsLayout = false;
565d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                                    }
566d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                                    break;
567d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                                }
568f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            }
569f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        }
5702b04f591f758b7af03c43d90e91b939cbd515506Venkat Krishnaraj                        numSets = mediaSets.size();
571f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        for (int i = 0; i < numSets; ++i) {
572f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            MediaSet set = mediaSets.get(i);
573f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            if (i >= bufferedRange.begin && i <= bufferedRange.end) {
574f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                if (scanMediaSets) {
575f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    int numItemsLoaded = set.mNumItemsLoaded;
576f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    if (numItemsLoaded < set.getNumExpectedItems() && numItemsLoaded < 8) {
57762f6a6a2e299c0706bfd0d4a0bca0ef1b10d3f37Venkat                                        synchronized (set) {
57862f6a6a2e299c0706bfd0d4a0bca0ef1b10d3f37Venkat                                            dataSource.loadItemsForSet(this, set, numItemsLoaded, 8);
57962f6a6a2e299c0706bfd0d4a0bca0ef1b10d3f37Venkat                                        }
580f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                        if (set.getNumExpectedItems() == 0) {
581f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                            mediaSets.remove(set);
582f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                            break;
583f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                        }
584f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                        if (mListener != null) {
5851c729acdafe147abda6b3479eafb17607f172780Venkat                                            mListenerNeedsUpdate = false;
5861c729acdafe147abda6b3479eafb17607f172780Venkat                                            mListener.onFeedChanged(this, mListenerNeedsLayout);
5871c729acdafe147abda6b3479eafb17607f172780Venkat                                            mListenerNeedsLayout = false;
588f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                        }
589f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                        sleepMs = 100;
590f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                        scanMediaSets = false;
591f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    }
592f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                }
593897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                            } else if (!mListenerNeedsUpdate && (i < bufferedRange.begin || i > bufferedRange.end)) {
594f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                // Purge this set to its initial status.
595f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                MediaClustering clustering = mClusterSets.get(set);
596f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                if (clustering != null) {
597f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    clustering.clear();
598f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    mClusterSets.remove(set);
599f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                }
600f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                if (set.getNumItems() != 0)
601f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    set.clear();
602f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            }
603f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        }
604f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    }
605f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    if (expandedSetIndex != Shared.INVALID) {
606f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        int numSets = mMediaSets.size();
607f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        for (int i = 0; i < numSets; ++i) {
608f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            // Purge other sets.
609f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            if (i != expandedSetIndex) {
610f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                MediaSet set = mediaSets.get(i);
611f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                MediaClustering clustering = mClusterSets.get(set);
612f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                if (clustering != null) {
613f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    clustering.clear();
614f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    mClusterSets.remove(set);
615f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                }
616897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                                if (set.mNumItemsLoaded != 0)
617f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    set.clear();
618f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            }
619f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        }
620f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        // Make sure all the items are loaded for the album.
621f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        int numItemsLoaded = mediaSets.get(expandedSetIndex).mNumItemsLoaded;
622f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        int requestedItems = mVisibleRange.end;
623f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        // requestedItems count changes in clustering mode.
624f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        if (mInClusteringMode && mClusterSets != null) {
625f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            requestedItems = 0;
626f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            MediaClustering clustering = mClusterSets.get(mediaSets.get(expandedSetIndex));
627db87908d640e17ef0946824be158d86c6e2d6836Dave Sparks                            if (clustering != null) {
628db87908d640e17ef0946824be158d86c6e2d6836Dave Sparks                                ArrayList<Cluster> clusters = clustering.getClustersForDisplay();
629db87908d640e17ef0946824be158d86c6e2d6836Dave Sparks                                int numClusters = clusters.size();
630db87908d640e17ef0946824be158d86c6e2d6836Dave Sparks                                for (int i = 0; i < numClusters; i++) {
631db87908d640e17ef0946824be158d86c6e2d6836Dave Sparks                                    requestedItems += clusters.get(i).getNumExpectedItems();
632db87908d640e17ef0946824be158d86c6e2d6836Dave Sparks                                }
633f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            }
634f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        }
635f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        MediaSet set = mediaSets.get(expandedSetIndex);
636f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        if (numItemsLoaded < set.getNumExpectedItems()) {
637897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                            // We perform calculations for a window that gets
638897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                            // anchored to a multiple of NUM_ITEMS_LOOKAHEAD.
639897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                            // The start of the window is 0, x, 2x, 3x ... etc
640897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                            // where x = NUM_ITEMS_LOOKAHEAD.
64162f6a6a2e299c0706bfd0d4a0bca0ef1b10d3f37Venkat                            synchronized (set) {
64262f6a6a2e299c0706bfd0d4a0bca0ef1b10d3f37Venkat                                dataSource.loadItemsForSet(this, set, numItemsLoaded, (requestedItems / NUM_ITEMS_LOOKAHEAD)
64362f6a6a2e299c0706bfd0d4a0bca0ef1b10d3f37Venkat                                        * NUM_ITEMS_LOOKAHEAD + NUM_ITEMS_LOOKAHEAD);
64462f6a6a2e299c0706bfd0d4a0bca0ef1b10d3f37Venkat                            }
645f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            if (set.getNumExpectedItems() == 0) {
646f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                mediaSets.remove(set);
6471c729acdafe147abda6b3479eafb17607f172780Venkat                                mListenerNeedsUpdate = false;
6481c729acdafe147abda6b3479eafb17607f172780Venkat                                mListener.onFeedChanged(this, mListenerNeedsLayout);
6491c729acdafe147abda6b3479eafb17607f172780Venkat                                mListenerNeedsLayout = false;
650f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            }
651f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            if (numItemsLoaded != set.mNumItemsLoaded && mListener != null) {
6521c729acdafe147abda6b3479eafb17607f172780Venkat                                mListenerNeedsUpdate = false;
6531c729acdafe147abda6b3479eafb17607f172780Venkat                                mListener.onFeedChanged(this, mListenerNeedsLayout);
6541c729acdafe147abda6b3479eafb17607f172780Venkat                                mListenerNeedsLayout = false;
655f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            }
656f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        }
657f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    }
658f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    MediaFilter filter = mMediaFilter;
659f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    if (filter != null && mMediaFilteredSet == null) {
660f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        if (expandedSetIndex != Shared.INVALID) {
661f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            MediaSet set = mediaSets.get(expandedSetIndex);
662f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            ArrayList<MediaItem> items = set.getItems();
663f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            int numItems = set.getNumItems();
664f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            MediaSet filteredSet = new MediaSet();
665f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            filteredSet.setNumExpectedItems(numItems);
666f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            mMediaFilteredSet = filteredSet;
667f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            for (int i = 0; i < numItems; ++i) {
668f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                MediaItem item = items.get(i);
669f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                if (filter.pass(item)) {
670f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    filteredSet.addItem(item);
671f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                }
672f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            }
673f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            filteredSet.updateNumExpectedItems();
674f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            filteredSet.generateTitle(true);
675f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        }
676f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        updateListener(true);
677f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    }
678f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
679f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
680f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
681f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
682f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
683f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void expandMediaSet(int mediaSetIndex) {
684f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        // We need to check if this slot can be focused or not.
685f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mListener != null) {
686f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            mListener.onFeedAboutToChange(this);
687f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
688f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mExpandedMediaSetIndex > 0 && mediaSetIndex == Shared.INVALID) {
689f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            // We are collapsing a previously expanded media set
6901bb0c42b2a62f580eea4764d6a4434ffecfbf353Dave Sparks            if (mediaSetIndex < mMediaSets.size() && mExpandedMediaSetIndex >= 0 && mExpandedMediaSetIndex < mMediaSets.size()) {
691f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                MediaSet set = mMediaSets.get(mExpandedMediaSetIndex);
692f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                if (set.getNumItems() == 0) {
693f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    set.clear();
694f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
695f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
696f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
697f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mExpandedMediaSetIndex = mediaSetIndex;
698f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mediaSetIndex < mMediaSets.size() && mediaSetIndex >= 0) {
699f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            // Notify Picasa that the user entered the album.
700f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            // MediaSet set = mMediaSets.get(mediaSetIndex);
7011bb0c42b2a62f580eea4764d6a4434ffecfbf353Dave Sparks            // PicasaService.requestSync(mContext,
7021bb0c42b2a62f580eea4764d6a4434ffecfbf353Dave Sparks            // PicasaService.TYPE_ALBUM_PHOTOS, set.mPicasaAlbumId);
703f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
704f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        updateListener(true);
705d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        mMediaFeedNeedsToRun = true;
706f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
707f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
708f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public boolean canExpandSet(int slotIndex) {
709f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        int mediaSetIndex = slotIndex;
710f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mediaSetIndex < mMediaSets.size() && mediaSetIndex >= 0) {
711f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            MediaSet set = mMediaSets.get(mediaSetIndex);
712f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (set.getNumItems() > 0) {
713f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                MediaItem item = set.getItems().get(0);
714f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                if (item.mId == Shared.INVALID) {
715f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    return false;
716f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
717f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                return true;
718f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
719f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
720f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return false;
721f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
722f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
723f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public boolean hasExpandedMediaSet() {
724f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return (mExpandedMediaSetIndex != Shared.INVALID);
725f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
726f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
727f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public boolean restorePreviousClusteringState() {
728f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        boolean retVal = disableClusteringIfNecessary();
729f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (retVal) {
730f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (mListener != null) {
731f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                mListener.onFeedAboutToChange(this);
732f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
733f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            updateListener(true);
734d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks            mMediaFeedNeedsToRun = true;
735f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
736f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return retVal;
737f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
738f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
739f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private boolean disableClusteringIfNecessary() {
740f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mInClusteringMode) {
741f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            // Disable clustering.
742f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            mInClusteringMode = false;
743d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks            mMediaFeedNeedsToRun = true;
744f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            return true;
745f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
746f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return false;
747f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
748f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
749f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public boolean isClustered() {
750f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return mInClusteringMode;
751f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
752f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
753f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public MediaSet getCurrentSet() {
754f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mExpandedMediaSetIndex != Shared.INVALID && mExpandedMediaSetIndex < mMediaSets.size()) {
755f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            return mMediaSets.get(mExpandedMediaSetIndex);
756f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
757f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return null;
758f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
759f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
760f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void performClustering() {
761f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mListener != null) {
762f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            mListener.onFeedAboutToChange(this);
763f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
764f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        MediaSet setToUse = null;
7652a6f302015b435941369d94f04f3018972558c46Venkat Krishnaraj        if (mExpandedMediaSetIndex != Shared.INVALID && mExpandedMediaSetIndex < mMediaSets.size()) {
766f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            setToUse = mMediaSets.get(mExpandedMediaSetIndex);
767f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
768f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (setToUse != null) {
769f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            MediaClustering clustering = null;
770d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks            synchronized (mClusterSets) {
771f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                // Make sure the computation is completed to the end.
772f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                clustering = mClusterSets.get(setToUse);
773f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                if (clustering != null) {
774f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    clustering.compute(null, true);
775f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                } else {
776f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    return;
777f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
778f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
779f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            mInClusteringMode = true;
780f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            updateListener(true);
781f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
782f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
783f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
784f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void moveSetToFront(MediaSet mediaSet) {
785f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        ArrayList<MediaSet> mediaSets = mMediaSets;
786f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        int numSets = mediaSets.size();
787f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (numSets == 0) {
788f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            mediaSets.add(mediaSet);
789f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            return;
790f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
791f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        MediaSet setToFind = mediaSets.get(0);
792f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (setToFind == mediaSet) {
793f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            return;
794f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
795f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mediaSets.set(0, mediaSet);
796f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        int indexToSwapTill = -1;
797f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        for (int i = 1; i < numSets; ++i) {
798f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            MediaSet set = mediaSets.get(i);
799f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (set == mediaSet) {
800f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                mediaSets.set(i, setToFind);
801f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                indexToSwapTill = i;
802f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                break;
803f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
804f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
805f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (indexToSwapTill != Shared.INVALID) {
806f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            for (int i = indexToSwapTill; i > 1; --i) {
807f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                MediaSet setEnd = mediaSets.get(i);
808f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                MediaSet setPrev = mediaSets.get(i - 1);
809f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                mediaSets.set(i, setPrev);
810f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                mediaSets.set(i - 1, setEnd);
811f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
812f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
813d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        mMediaFeedNeedsToRun = true;
814f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
815f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
816f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public MediaSet replaceMediaSet(long setId, DataSource dataSource) {
8171c729acdafe147abda6b3479eafb17607f172780Venkat        Log.i(TAG, "Replacing media set " + setId);
8181b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj        final MediaSet set = getMediaSet(setId);
8191b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj        set.refresh();
8201b329b810c628b43c86a574ec6d4ad4478f02d3cVenkat Krishnaraj        return set;
821f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
822d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks
823f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void setSingleImageMode(boolean singleImageMode) {
824f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mSingleImageMode = singleImageMode;
825f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
826f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
827f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public boolean isSingleImageMode() {
828f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return mSingleImageMode;
829f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
830f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
831f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public MediaSet getExpandedMediaSet() {
832f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mExpandedMediaSetIndex == Shared.INVALID)
833f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            return null;
834f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mExpandedMediaSetIndex >= mMediaSets.size())
835f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            return null;
836f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return mMediaSets.get(mExpandedMediaSetIndex);
837f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
8385e0474e8e1942c41234eb251f948c2fbb7445b02Venkat Krishnaraj
8395e0474e8e1942c41234eb251f948c2fbb7445b02Venkat Krishnaraj    public void refresh() {
84062dd11281ef6e12049dd6798b184157e9583d7d4Venkat        if (mDataSource != null) {
84162dd11281ef6e12049dd6798b184157e9583d7d4Venkat            synchronized (mRequestedRefresh) {
84262dd11281ef6e12049dd6798b184157e9583d7d4Venkat                mRequestedRefresh.add(mDataSource.getDatabaseUris());
84362dd11281ef6e12049dd6798b184157e9583d7d4Venkat            }
84462dd11281ef6e12049dd6798b184157e9583d7d4Venkat        }
845897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj    }
846897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj
847897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj    private void refresh(final String[] databaseUris) {
84862f6a6a2e299c0706bfd0d4a0bca0ef1b10d3f37Venkat        synchronized (mMediaSets) {
84962f6a6a2e299c0706bfd0d4a0bca0ef1b10d3f37Venkat            if (mDataSource != null) {
85062dd11281ef6e12049dd6798b184157e9583d7d4Venkat                synchronized (mRequestedRefresh) {
85162dd11281ef6e12049dd6798b184157e9583d7d4Venkat                    mRequestedRefresh.add(databaseUris);
85262dd11281ef6e12049dd6798b184157e9583d7d4Venkat                }
85362f6a6a2e299c0706bfd0d4a0bca0ef1b10d3f37Venkat            }
8545e0474e8e1942c41234eb251f948c2fbb7445b02Venkat Krishnaraj        }
8555e0474e8e1942c41234eb251f948c2fbb7445b02Venkat Krishnaraj    }
856897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj
857897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj    public void onPause() {
858897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj        final HashMap<String, ContentObserver> observers = mContentObservers;
859897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj        String[] uris = new String[observers.size()];
860897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj        uris = observers.keySet().toArray(uris);
861897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj        final int numUris = uris.length;
862897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj        final ContentResolver cr = mContext.getContentResolver();
863897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj        for (int i = 0; i < numUris; ++i) {
864897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj            final String uri = uris[i];
865897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj            if (uri != null) {
866897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                final ContentObserver observer = observers.get(uri);
867897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                cr.unregisterContentObserver(observer);
868897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                observers.remove(uri);
869897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj            }
870897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj        }
871897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj        observers.clear();
872897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj    }
873897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj
874897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj    public void onResume() {
875897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj        // We setup the listeners for this datasource
876897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj        final String[] uris = mDataSource.getDatabaseUris();
877897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj        final HashMap<String, ContentObserver> observers = mContentObservers;
878897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj        if (mContext instanceof Gallery) {
879897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj            final Gallery gallery = (Gallery) mContext;
880897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj            final ContentResolver cr = mContext.getContentResolver();
881897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj            if (uris != null) {
882897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                final int numUris = uris.length;
883897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                for (int i = 0; i < numUris; ++i) {
884897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                    final String uri = uris[i];
885897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                    final ContentObserver presentObserver = observers.get(uri);
886897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                    if (presentObserver == null) {
887d93f177bf2bc26f4ad64ca2f7725da8b0347a77fVenkat                        final Handler handler = App.get(mContext).getHandler();
888897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                        final ContentObserver observer = new ContentObserver(handler) {
889897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                            public void onChange(boolean selfChange) {
890897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                                if (!mWaitingForMediaScanner) {
891897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                                    MediaFeed.this.refresh(new String[] { uri });
892897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                                }
893897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                            }
894897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                        };
89562dd11281ef6e12049dd6798b184157e9583d7d4Venkat                        cr.registerContentObserver(Uri.parse(uri), true, observer);
896897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                        observers.put(uri, observer);
897897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                    }
898897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj                }
899897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj            }
900897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj        }
901897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj        refresh();
902897ad622181117e8acbdeae2ff0afece68f1332cVenkat Krishnaraj    }
903f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks}
904