diff options
Diffstat (limited to 'src/com/android/gallery3d/app/AlbumSetDataLoader.java')
-rw-r--r-- | src/com/android/gallery3d/app/AlbumSetDataLoader.java | 393 |
1 files changed, 0 insertions, 393 deletions
diff --git a/src/com/android/gallery3d/app/AlbumSetDataLoader.java b/src/com/android/gallery3d/app/AlbumSetDataLoader.java deleted file mode 100644 index cf380f812..000000000 --- a/src/com/android/gallery3d/app/AlbumSetDataLoader.java +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.os.Handler; -import android.os.Message; -import android.os.Process; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.ContentListener; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.ui.SynchronizedHandler; - -import java.util.Arrays; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.FutureTask; - -public class AlbumSetDataLoader { - @SuppressWarnings("unused") - private static final String TAG = "AlbumSetDataAdapter"; - - private static final int INDEX_NONE = -1; - - private static final int MIN_LOAD_COUNT = 4; - - private static final int MSG_LOAD_START = 1; - private static final int MSG_LOAD_FINISH = 2; - private static final int MSG_RUN_OBJECT = 3; - - public static interface DataListener { - public void onContentChanged(int index); - public void onSizeChanged(int size); - } - - private final MediaSet[] mData; - private final MediaItem[] mCoverItem; - private final int[] mTotalCount; - private final long[] mItemVersion; - private final long[] mSetVersion; - - private int mActiveStart = 0; - private int mActiveEnd = 0; - - private int mContentStart = 0; - private int mContentEnd = 0; - - private final MediaSet mSource; - private long mSourceVersion = MediaObject.INVALID_DATA_VERSION; - private int mSize; - - private DataListener mDataListener; - private LoadingListener mLoadingListener; - private ReloadTask mReloadTask; - - private final Handler mMainHandler; - - private final MySourceListener mSourceListener = new MySourceListener(); - - public AlbumSetDataLoader(AbstractGalleryActivity activity, MediaSet albumSet, int cacheSize) { - mSource = Utils.checkNotNull(albumSet); - mCoverItem = new MediaItem[cacheSize]; - mData = new MediaSet[cacheSize]; - mTotalCount = new int[cacheSize]; - mItemVersion = new long[cacheSize]; - mSetVersion = new long[cacheSize]; - Arrays.fill(mItemVersion, MediaObject.INVALID_DATA_VERSION); - Arrays.fill(mSetVersion, MediaObject.INVALID_DATA_VERSION); - - mMainHandler = new SynchronizedHandler(activity.getGLRoot()) { - @Override - public void handleMessage(Message message) { - switch (message.what) { - case MSG_RUN_OBJECT: - ((Runnable) message.obj).run(); - return; - case MSG_LOAD_START: - if (mLoadingListener != null) mLoadingListener.onLoadingStarted(); - return; - case MSG_LOAD_FINISH: - if (mLoadingListener != null) mLoadingListener.onLoadingFinished(false); - return; - } - } - }; - } - - public void pause() { - mReloadTask.terminate(); - mReloadTask = null; - mSource.removeContentListener(mSourceListener); - } - - public void resume() { - mSource.addContentListener(mSourceListener); - mReloadTask = new ReloadTask(); - mReloadTask.start(); - } - - private void assertIsActive(int index) { - if (index < mActiveStart && index >= mActiveEnd) { - throw new IllegalArgumentException(String.format( - "%s not in (%s, %s)", index, mActiveStart, mActiveEnd)); - } - } - - public MediaSet getMediaSet(int index) { - assertIsActive(index); - return mData[index % mData.length]; - } - - public MediaItem getCoverItem(int index) { - assertIsActive(index); - return mCoverItem[index % mCoverItem.length]; - } - - public int getTotalCount(int index) { - assertIsActive(index); - return mTotalCount[index % mTotalCount.length]; - } - - public int getActiveStart() { - return mActiveStart; - } - - public boolean isActive(int index) { - return index >= mActiveStart && index < mActiveEnd; - } - - public int size() { - return mSize; - } - - // Returns the index of the MediaSet with the given path or - // -1 if the path is not cached - public int findSet(Path id) { - int length = mData.length; - for (int i = mContentStart; i < mContentEnd; i++) { - MediaSet set = mData[i % length]; - if (set != null && id == set.getPath()) { - return i; - } - } - return -1; - } - - private void clearSlot(int slotIndex) { - mData[slotIndex] = null; - mCoverItem[slotIndex] = null; - mTotalCount[slotIndex] = 0; - mItemVersion[slotIndex] = MediaObject.INVALID_DATA_VERSION; - mSetVersion[slotIndex] = MediaObject.INVALID_DATA_VERSION; - } - - private void setContentWindow(int contentStart, int contentEnd) { - if (contentStart == mContentStart && contentEnd == mContentEnd) return; - int length = mCoverItem.length; - - int start = this.mContentStart; - int end = this.mContentEnd; - - mContentStart = contentStart; - mContentEnd = contentEnd; - - if (contentStart >= end || start >= contentEnd) { - for (int i = start, n = end; i < n; ++i) { - clearSlot(i % length); - } - } else { - for (int i = start; i < contentStart; ++i) { - clearSlot(i % length); - } - for (int i = contentEnd, n = end; i < n; ++i) { - clearSlot(i % length); - } - } - mReloadTask.notifyDirty(); - } - - public void setActiveWindow(int start, int end) { - if (start == mActiveStart && end == mActiveEnd) return; - - Utils.assertTrue(start <= end - && end - start <= mCoverItem.length && end <= mSize); - - mActiveStart = start; - mActiveEnd = end; - - int length = mCoverItem.length; - // If no data is visible, keep the cache content - if (start == end) return; - - int contentStart = Utils.clamp((start + end) / 2 - length / 2, - 0, Math.max(0, mSize - length)); - int contentEnd = Math.min(contentStart + length, mSize); - if (mContentStart > start || mContentEnd < end - || Math.abs(contentStart - mContentStart) > MIN_LOAD_COUNT) { - setContentWindow(contentStart, contentEnd); - } - } - - private class MySourceListener implements ContentListener { - @Override - public void onContentDirty() { - mReloadTask.notifyDirty(); - } - } - - public void setModelListener(DataListener listener) { - mDataListener = listener; - } - - public void setLoadingListener(LoadingListener listener) { - mLoadingListener = listener; - } - - private static class UpdateInfo { - public long version; - public int index; - - public int size; - public MediaSet item; - public MediaItem cover; - public int totalCount; - } - - private class GetUpdateInfo implements Callable<UpdateInfo> { - - private final long mVersion; - - public GetUpdateInfo(long version) { - mVersion = version; - } - - private int getInvalidIndex(long version) { - long setVersion[] = mSetVersion; - int length = setVersion.length; - for (int i = mContentStart, n = mContentEnd; i < n; ++i) { - int index = i % length; - if (setVersion[i % length] != version) return i; - } - return INDEX_NONE; - } - - @Override - public UpdateInfo call() throws Exception { - int index = getInvalidIndex(mVersion); - if (index == INDEX_NONE && mSourceVersion == mVersion) return null; - UpdateInfo info = new UpdateInfo(); - info.version = mSourceVersion; - info.index = index; - info.size = mSize; - return info; - } - } - - private class UpdateContent implements Callable<Void> { - private final UpdateInfo mUpdateInfo; - - public UpdateContent(UpdateInfo info) { - mUpdateInfo = info; - } - - @Override - public Void call() { - // Avoid notifying listeners of status change after pause - // Otherwise gallery will be in inconsistent state after resume. - if (mReloadTask == null) return null; - UpdateInfo info = mUpdateInfo; - mSourceVersion = info.version; - if (mSize != info.size) { - mSize = info.size; - if (mDataListener != null) mDataListener.onSizeChanged(mSize); - if (mContentEnd > mSize) mContentEnd = mSize; - if (mActiveEnd > mSize) mActiveEnd = mSize; - } - // Note: info.index could be INDEX_NONE, i.e., -1 - if (info.index >= mContentStart && info.index < mContentEnd) { - int pos = info.index % mCoverItem.length; - mSetVersion[pos] = info.version; - long itemVersion = info.item.getDataVersion(); - if (mItemVersion[pos] == itemVersion) return null; - mItemVersion[pos] = itemVersion; - mData[pos] = info.item; - mCoverItem[pos] = info.cover; - mTotalCount[pos] = info.totalCount; - if (mDataListener != null - && info.index >= mActiveStart && info.index < mActiveEnd) { - mDataListener.onContentChanged(info.index); - } - } - return null; - } - } - - private <T> T executeAndWait(Callable<T> callable) { - FutureTask<T> task = new FutureTask<T>(callable); - mMainHandler.sendMessage( - mMainHandler.obtainMessage(MSG_RUN_OBJECT, task)); - try { - return task.get(); - } catch (InterruptedException e) { - return null; - } catch (ExecutionException e) { - throw new RuntimeException(e); - } - } - - // TODO: load active range first - private class ReloadTask extends Thread { - private volatile boolean mActive = true; - private volatile boolean mDirty = true; - private volatile boolean mIsLoading = false; - - private void updateLoading(boolean loading) { - if (mIsLoading == loading) return; - mIsLoading = loading; - mMainHandler.sendEmptyMessage(loading ? MSG_LOAD_START : MSG_LOAD_FINISH); - } - - @Override - public void run() { - Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); - - boolean updateComplete = false; - while (mActive) { - synchronized (this) { - if (mActive && !mDirty && updateComplete) { - if (!mSource.isLoading()) updateLoading(false); - Utils.waitWithoutInterrupt(this); - continue; - } - } - mDirty = false; - updateLoading(true); - - long version = mSource.reload(); - UpdateInfo info = executeAndWait(new GetUpdateInfo(version)); - updateComplete = info == null; - if (updateComplete) continue; - if (info.version != version) { - info.version = version; - info.size = mSource.getSubMediaSetCount(); - - // If the size becomes smaller after reload(), we may - // receive from GetUpdateInfo an index which is too - // big. Because the main thread is not aware of the size - // change until we call UpdateContent. - if (info.index >= info.size) { - info.index = INDEX_NONE; - } - } - if (info.index != INDEX_NONE) { - info.item = mSource.getSubMediaSet(info.index); - if (info.item == null) continue; - info.cover = info.item.getCoverMediaItem(); - info.totalCount = info.item.getTotalMediaItemCount(); - } - executeAndWait(new UpdateContent(info)); - } - updateLoading(false); - } - - public synchronized void notifyDirty() { - mDirty = true; - notifyAll(); - } - - public synchronized void terminate() { - mActive = false; - notifyAll(); - } - } -} - - |