AlbumSetSlidingWindow.java revision d8fb81f601830385a2343d08ad5dd171e4c7bfe0
1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/*
2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2010 The Android Open Source Project
3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License");
5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License.
6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at
7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *      http://www.apache.org/licenses/LICENSE-2.0
9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software
11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS,
12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and
14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License.
15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */
16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.ui;
18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
19dbf4ba12afba115888493caa34937643257e2bb1Ray Chenimport android.graphics.Bitmap;
20dbf4ba12afba115888493caa34937643257e2bb1Ray Chenimport android.os.Message;
21dbf4ba12afba115888493caa34937643257e2bb1Ray Chen
22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.R;
23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.app.GalleryActivity;
24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.common.Utils;
25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaItem;
261a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Linimport com.android.gallery3d.data.MediaObject;
27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaSet;
28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.Path;
29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.util.Future;
30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.util.FutureListener;
31bc2154199aee16762e3758ad0cfed685323d9a9fChih-Chung Changimport com.android.gallery3d.util.GalleryUtils;
32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.util.MediaSetUtils;
33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.util.ThreadPool;
34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class AlbumSetSlidingWindow implements AlbumSetView.ModelListener {
361a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private static final String TAG = "AlbumSetSlidingWindow";
371a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private static final int MSG_UPDATE_ALBUM_ENTRY = 1;
38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public static interface Listener {
40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public void onSizeChanged(int size);
417260f6f74d465520e4497b23fe56f98abb0c15a2Owen Lin        public void onContentChanged();
42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private final AlbumSetView.Model mSource;
45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private int mSize;
46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private int mContentStart = 0;
48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private int mContentEnd = 0;
49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private int mActiveStart = 0;
51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private int mActiveEnd = 0;
52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private Listener mListener;
54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
551a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private final AlbumSetEntry mData[];
56dbf4ba12afba115888493caa34937643257e2bb1Ray Chen    private final SynchronizedHandler mHandler;
57dbf4ba12afba115888493caa34937643257e2bb1Ray Chen    private final ThreadPool mThreadPool;
581a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private final AlbumLabelMaker mLabelMaker;
591a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private final String mLoadingText;
60d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin    private final TextureUploader mTextureUploader;
61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private int mActiveRequestCount = 0;
63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private boolean mIsActive = false;
641a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private BitmapTexture mLoadingLabel;
651a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
661a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private int mSlotWidth;
67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
681a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public static class AlbumSetEntry {
691a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public MediaSet album;
701a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public MediaItem coverItem;
711a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public Texture content;
721a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public Texture label;
73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public Path setPath;
74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public int sourceType;
75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public int cacheFlag;
76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public int cacheStatus;
771a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public int rotation;
781a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public int mediaType;
791a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public boolean isPanorama;
801a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public boolean isWaitLoadingDisplayed;
811a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public long setDataVersion;
821a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public long coverDataVersion;
831a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        private BitmapLoader labelLoader;
841a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        private BitmapLoader coverLoader;
85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
879201679ed1c485767f2e334aa618bd733024af03Chih-Chung Chang    public AlbumSetSlidingWindow(GalleryActivity activity,
889201679ed1c485767f2e334aa618bd733024af03Chih-Chung Chang            AlbumSetView.LabelSpec labelSpec, SelectionDrawer drawer,
89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            AlbumSetView.Model source, int cacheSize) {
90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        source.setModelListener(this);
91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mSource = source;
921a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        mData = new AlbumSetEntry[cacheSize];
93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mSize = source.size();
941a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        mThreadPool = activity.getThreadPool();
95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
961a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        mLabelMaker = new AlbumLabelMaker(activity.getAndroidContext(), labelSpec);
971a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        mLoadingText = activity.getAndroidContext().getString(R.string.loading);
98d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        mTextureUploader = new TextureUploader(activity.getGLRoot());
99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mHandler = new SynchronizedHandler(activity.getGLRoot()) {
101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            @Override
102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            public void handleMessage(Message message) {
1031a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                Utils.assertTrue(message.what == MSG_UPDATE_ALBUM_ENTRY);
1041a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                ((EntryUpdater) message.obj).updateEntry();
105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        };
107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void setListener(Listener listener) {
110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mListener = listener;
111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
1131a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public AlbumSetEntry get(int slotIndex) {
114cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang        if (!isActiveSlot(slotIndex)) {
115cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang            Utils.fail("invalid slot: %s outsides (%s, %s)",
116cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang                    slotIndex, mActiveStart, mActiveEnd);
117cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang        }
118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return mData[slotIndex % mData.length];
119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public int size() {
122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return mSize;
123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
124f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
125f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public boolean isActiveSlot(int slotIndex) {
126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return slotIndex >= mActiveStart && slotIndex < mActiveEnd;
127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void setContentWindow(int contentStart, int contentEnd) {
130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (contentStart == mContentStart && contentEnd == mContentEnd) return;
131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (contentStart >= mContentEnd || mContentStart >= contentEnd) {
133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                freeSlotContent(i);
135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mSource.setActiveWindow(contentStart, contentEnd);
137f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            for (int i = contentStart; i < contentEnd; ++i) {
138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                prepareSlotContent(i);
139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } else {
141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            for (int i = mContentStart; i < contentStart; ++i) {
142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                freeSlotContent(i);
143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            for (int i = contentEnd, n = mContentEnd; i < n; ++i) {
145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                freeSlotContent(i);
146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mSource.setActiveWindow(contentStart, contentEnd);
148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            for (int i = contentStart, n = mContentStart; i < n; ++i) {
149f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                prepareSlotContent(i);
150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            for (int i = mContentEnd; i < contentEnd; ++i) {
152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                prepareSlotContent(i);
153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
154f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mContentStart = contentStart;
157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mContentEnd = contentEnd;
158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void setActiveWindow(int start, int end) {
161cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang        if (!(start <= end && end - start <= mData.length && end <= mSize)) {
162cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang            Utils.fail("start = %s, end = %s, length = %s, size = %s",
163cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang                    start, end, mData.length, mSize);
164cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang        }
165f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
1661a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        AlbumSetEntry data[] = mData;
167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mActiveStart = start;
168f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mActiveEnd = end;
169f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        int contentStart = Utils.clamp((start + end) / 2 - data.length / 2,
170f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                0, Math.max(0, mSize - data.length));
171f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        int contentEnd = Math.min(contentStart + data.length, mSize);
172f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        setContentWindow(contentStart, contentEnd);
173d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin
174d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        if (mIsActive) {
175d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            updateTextureUploadQueue();
176d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            updateAllImageRequests();
177d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        }
178f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
179f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
180f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    // We would like to request non active slots in the following order:
181f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    // Order:    8 6 4 2                   1 3 5 7
182f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    //         |---------|---------------|---------|
183f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    //                   |<-  active  ->|
184f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    //         |<-------- cached range ----------->|
185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void requestNonactiveImages() {
186f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        int range = Math.max(
187f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mContentEnd - mActiveEnd, mActiveStart - mContentStart);
188f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        for (int i = 0 ;i < range; ++i) {
189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            requestImagesInSlot(mActiveEnd + i);
190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            requestImagesInSlot(mActiveStart - 1 - i);
191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
193f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
194f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void cancelNonactiveImages() {
195f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        int range = Math.max(
196f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mContentEnd - mActiveEnd, mActiveStart - mContentStart);
197f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        for (int i = 0 ;i < range; ++i) {
198f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            cancelImagesInSlot(mActiveEnd + i);
199f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            cancelImagesInSlot(mActiveStart - 1 - i);
200f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
201f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
202f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
203f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void requestImagesInSlot(int slotIndex) {
204f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (slotIndex < mContentStart || slotIndex >= mContentEnd) return;
2051a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        AlbumSetEntry entry = mData[slotIndex % mData.length];
2061a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (entry.coverLoader != null) entry.coverLoader.startLoad();
2071a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (entry.labelLoader != null) entry.labelLoader.startLoad();
208f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
209f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
210f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void cancelImagesInSlot(int slotIndex) {
211f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (slotIndex < mContentStart || slotIndex >= mContentEnd) return;
2121a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        AlbumSetEntry entry = mData[slotIndex % mData.length];
2131a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (entry.coverLoader != null) entry.coverLoader.cancelLoad();
2141a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (entry.labelLoader != null) entry.labelLoader.cancelLoad();
2151a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    }
2161a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
2171a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private static long getDataVersion(MediaObject object) {
2181a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        return object == null
2191a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                ? MediaSet.INVALID_DATA_VERSION
2201a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                : object.getDataVersion();
221f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
222f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
223f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void freeSlotContent(int slotIndex) {
2241a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        AlbumSetEntry entry = mData[slotIndex % mData.length];
2251a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (entry.coverLoader != null) entry.coverLoader.recycle();
2261a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (entry.labelLoader != null) entry.labelLoader.recycle();
2271a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        mData[slotIndex % mData.length] = null;
228f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
229f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
2301a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private void updateAlbumSetEntry(AlbumSetEntry entry,
2311a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            int slotIndex, MediaSet album, MediaItem cover) {
2321a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        entry.album = album;
2331a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        entry.setDataVersion = getDataVersion(album);
2341a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        entry.sourceType = identifySourceType(album);
2351a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        entry.cacheFlag = identifyCacheFlag(album);
2361a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        entry.cacheStatus = identifyCacheStatus(album);
2371a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        entry.setPath = (album == null) ? null : album.getPath();
2381a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
2391a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (entry.labelLoader != null) {
2401a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            entry.labelLoader.recycle();
2411a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            entry.labelLoader = null;
2421a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            entry.label = null;
2431a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        }
2441a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (album != null) {
245d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            entry.labelLoader =
246d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin                    new AlbumLabelLoader(slotIndex, album, entry.sourceType);
2471a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        }
2481a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
2491a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        entry.coverItem = cover;
2501a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (getDataVersion(cover) != entry.coverDataVersion) {
2511a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            entry.coverDataVersion = getDataVersion(cover);
2521a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            entry.isPanorama = GalleryUtils.isPanorama(cover);
2531a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            entry.rotation = (cover == null) ? 0 : cover.getRotation();
2541a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            entry.mediaType = (cover == null) ? 0 : cover.getMediaType();
2551a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            if (entry.coverLoader != null) {
2561a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                entry.coverLoader.recycle();
2571a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                entry.coverLoader = null;
2581a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                entry.content = null;
2591a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            }
2601a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            if (cover != null) {
2611a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                entry.coverLoader = new AlbumCoverLoader(slotIndex, cover);
2621a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            }
2631a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        }
264f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
265f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
266f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void prepareSlotContent(int slotIndex) {
267f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        MediaSet set = mSource.getMediaSet(slotIndex);
2681a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        MediaItem coverItem = mSource.getCoverItem(slotIndex);
2691a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        AlbumSetEntry entry = new AlbumSetEntry();
2701a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        updateAlbumSetEntry(entry, slotIndex, set, coverItem);
2711a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        mData[slotIndex % mData.length] = entry;
272f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
273f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
2741a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private static boolean startLoadBitmap(BitmapLoader loader) {
2751a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (loader == null) return false;
2761a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        loader.startLoad();
2771a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        return loader.isRequestInProgress();
278f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
279f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
280d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin    private void queueTextureForUpload(boolean isActive, Texture texture) {
281d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        if ((texture == null) || !(texture instanceof BitmapTexture)) return;
282d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        if (isActive) {
283d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            mTextureUploader.addFgTexture((BitmapTexture) texture);
284d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        } else {
285d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            mTextureUploader.addBgTexture((BitmapTexture) texture);
286f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
287d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin    }
2881a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
289d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin    private void updateTextureUploadQueue() {
290d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        if (!mIsActive) return;
291d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        mTextureUploader.clear();
292d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
293d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            AlbumSetEntry entry = mData[i % mData.length];
294d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            boolean isActive = isActiveSlot(i);
295d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            queueTextureForUpload(isActive, entry.label);
296d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            queueTextureForUpload(isActive, entry.content);
297f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
298f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
299f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
300f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void updateAllImageRequests() {
301f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mActiveRequestCount = 0;
302f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) {
3031a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            AlbumSetEntry entry = mData[i % mData.length];
3041a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            if (startLoadBitmap(entry.coverLoader)) ++mActiveRequestCount;
3051a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            if (startLoadBitmap(entry.labelLoader)) ++mActiveRequestCount;
306f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
307f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mActiveRequestCount == 0) {
308f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            requestNonactiveImages();
309f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } else {
310f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            cancelNonactiveImages();
311f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
312f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
313f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
3141a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    @Override
3151a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public void onSizeChanged(int size) {
3161a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (mIsActive && mSize != size) {
3171a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mSize = size;
3181a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            if (mListener != null) mListener.onSizeChanged(mSize);
319f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
3201a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    }
321f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
3221a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    @Override
3231a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public void onWindowContentChanged(int index) {
3241a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (!mIsActive) {
3251a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            // paused, ignore slot changed event
3261a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            return;
3274bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin        }
328d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin
329d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        // If the updated content is not cached, ignore it
330d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        if (index < mContentStart || index >= mContentEnd) {
331d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            Log.w(TAG, String.format(
332d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin                    "invalid update: %s is outside (%s, %s)",
333d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin                    index, mContentStart, mContentEnd) );
334d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            return;
335d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        }
336d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin
337d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        AlbumSetEntry entry = mData[index % mData.length];
338d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        MediaSet set = mSource.getMediaSet(index);
339d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        MediaItem coverItem = mSource.getCoverItem(index);
340d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        updateAlbumSetEntry(entry, index, set, coverItem);
341d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        updateAllImageRequests();
342d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        updateTextureUploadQueue();
343d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        if (mListener != null && isActiveSlot(index)) {
344d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            mListener.onContentChanged();
345d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        }
3461a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    }
3474bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin
3481a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public BitmapTexture getLoadingTexture() {
3491a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (mLoadingLabel == null) {
3501a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            Bitmap bitmap = mLabelMaker.requestLabel(mLoadingText, null,
351d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin                    SelectionDrawer.DATASOURCE_TYPE_NOT_CATEGORIZED)
3521a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                    .run(ThreadPool.JOB_CONTEXT_STUB);
3531a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mLoadingLabel = new BitmapTexture(bitmap);
3541a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mLoadingLabel.setOpaque(false);
355f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
3561a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        return mLoadingLabel;
3571a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    }
358f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
3591a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public void pause() {
3601a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        mIsActive = false;
3611a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
3621a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            freeSlotContent(i);
3639201679ed1c485767f2e334aa618bd733024af03Chih-Chung Chang        }
364d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        mLabelMaker.clearRecycledLabels();
3651a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    }
366f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
3671a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public void resume() {
3681a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        mIsActive = true;
3691a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
3701a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            prepareSlotContent(i);
3711a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        }
3721a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        updateAllImageRequests();
3731a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    }
374f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
3751a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private static interface EntryUpdater {
3761a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public void updateEntry();
3771a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    }
378da071d27a1435cce080b5c609d0d833555e5a175Chih-Chung Chang
3791a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private class AlbumCoverLoader extends BitmapLoader implements EntryUpdater {
3801a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        private MediaItem mMediaItem;
3811a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        private final int mSlotIndex;
3826c1f01e21406a05dc7d3258001aa901bd8628a79Chih-Chung Chang
3831a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public AlbumCoverLoader(int slotIndex, MediaItem item) {
3841a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mSlotIndex = slotIndex;
3851a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mMediaItem = item;
386f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
387f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
388f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
3891a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        protected void recycleBitmap(Bitmap bitmap) {
390d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            MediaItem.getMicroThumbPool().recycle(bitmap);
391f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
392f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
393f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
3941a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l) {
3951a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            return mThreadPool.submit(mMediaItem.requestImage(
3961a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                    MediaItem.TYPE_MICROTHUMBNAIL), l);
397f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
398f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
399f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
4001a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        protected void onLoadComplete(Bitmap bitmap) {
4011a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mHandler.obtainMessage(MSG_UPDATE_ALBUM_ENTRY, this).sendToTarget();
402f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
403f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
404f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
4051a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public void updateEntry() {
4061a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            Bitmap bitmap = getBitmap();
407d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            if (bitmap == null) return; // error or recycled
4081a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
4091a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            AlbumSetEntry entry = mData[mSlotIndex % mData.length];
410d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            BitmapTexture texture = new BitmapTexture(bitmap);
411d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            entry.content = texture;
4121a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
4131a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            if (isActiveSlot(mSlotIndex)) {
414d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin                mTextureUploader.addFgTexture(texture);
4151a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                --mActiveRequestCount;
4161a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                if (mActiveRequestCount == 0) requestNonactiveImages();
4171a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                if (mListener != null) mListener.onContentChanged();
418d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            } else {
419d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin                mTextureUploader.addBgTexture(texture);
4201a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            }
421f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
422f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
423f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
424f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static int identifySourceType(MediaSet set) {
425f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (set == null) {
426f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return SelectionDrawer.DATASOURCE_TYPE_NOT_CATEGORIZED;
427f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
428f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
429f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        Path path = set.getPath();
430f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (MediaSetUtils.isCameraSource(path)) {
431f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return SelectionDrawer.DATASOURCE_TYPE_CAMERA;
432f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
433f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
434f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        int type = SelectionDrawer.DATASOURCE_TYPE_NOT_CATEGORIZED;
435f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        String prefix = path.getPrefix();
436f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
437f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (prefix.equals("picasa")) {
438f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            type = SelectionDrawer.DATASOURCE_TYPE_PICASA;
439f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } else if (prefix.equals("local") || prefix.equals("merge")) {
440f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            type = SelectionDrawer.DATASOURCE_TYPE_LOCAL;
441f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } else if (prefix.equals("mtp")) {
442f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            type = SelectionDrawer.DATASOURCE_TYPE_MTP;
443f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
444f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
445f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return type;
446f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
447f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
448f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static int identifyCacheFlag(MediaSet set) {
449f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (set == null || (set.getSupportedOperations()
450f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                & MediaSet.SUPPORT_CACHE) == 0) {
451f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return MediaSet.CACHE_FLAG_NO;
452f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
453f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
454f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return set.getCacheFlag();
455f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
456f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
457f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static int identifyCacheStatus(MediaSet set) {
458f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (set == null || (set.getSupportedOperations()
459f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                & MediaSet.SUPPORT_CACHE) == 0) {
460f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return MediaSet.CACHE_STATUS_NOT_CACHED;
461f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
462f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
463f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return set.getCacheStatus();
464f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
465f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
4661a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private class AlbumLabelLoader extends BitmapLoader implements EntryUpdater {
4671a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        private final MediaSet mMediaSet;
468f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private final int mSlotIndex;
4691a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        private final int mSourceType;
470f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
471d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        public AlbumLabelLoader(
472d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin                int slotIndex, MediaSet mediaSet, int sourceType) {
473f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mSlotIndex = slotIndex;
4741a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mMediaSet = mediaSet;
4751a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mSourceType = sourceType;
476f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
477f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
4781a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        @Override
4791a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l) {
4801a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            return mThreadPool.submit(mLabelMaker.requestLabel(
481d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin                    mMediaSet, mSourceType), l);
482f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
483f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
484f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
4851a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        protected void recycleBitmap(Bitmap bitmap) {
486d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            mLabelMaker.reycleLabel(bitmap);
487f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
488f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
489f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
4901a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        protected void onLoadComplete(Bitmap bitmap) {
4911a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mHandler.obtainMessage(MSG_UPDATE_ALBUM_ENTRY, this).sendToTarget();
492f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
493f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
4941a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        @Override
4951a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public void updateEntry() {
4961a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            Bitmap bitmap = getBitmap();
497d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            if (bitmap == null) return; // Error or recycled
498f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
4991a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            AlbumSetEntry entry = mData[mSlotIndex % mData.length];
500d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            BitmapTexture texture = new BitmapTexture(bitmap);
501d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            texture.setOpaque(false);
502d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            entry.label = texture;
5031a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
5041a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            if (isActiveSlot(mSlotIndex)) {
505d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin                mTextureUploader.addFgTexture(texture);
5061a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                --mActiveRequestCount;
5071a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                if (mActiveRequestCount == 0) requestNonactiveImages();
5081a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                if (mListener != null) mListener.onContentChanged();
509d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            } else {
510d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin                mTextureUploader.addBgTexture(texture);
5111a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            }
512f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
513f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
514f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
5151a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public void onSlotSizeChanged(int width, int height) {
5161a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (mSlotWidth == width) return;
517d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin
5181a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        mSlotWidth = width;
5191a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        mLoadingLabel = null;
520d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        mLabelMaker.setLabelWidth(mSlotWidth);
521d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin
522d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        if (!mIsActive) return;
5231a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
524f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
5251a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            AlbumSetEntry entry = mData[i % mData.length];
5261a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            if (entry.labelLoader != null) {
5271a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                entry.labelLoader.recycle();
5281a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                entry.labelLoader = null;
5291a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                entry.label = null;
5301a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            }
5311a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            entry.labelLoader = (entry.album == null)
5321a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                    ? null
533d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin                    : new AlbumLabelLoader(i, entry.album, entry.sourceType);
534f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
535f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        updateAllImageRequests();
536d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        updateTextureUploadQueue();
537f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
538f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin}
539