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.app; 18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 192b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport android.graphics.Bitmap; 202b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport android.graphics.BitmapRegionDecoder; 212b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport android.os.Handler; 222b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport android.os.Message; 232b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Lin 2422493b29c32142f2588c623f5c78e9167352dddcOwen Linimport com.android.gallery3d.common.BitmapUtils; 25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.common.Utils; 26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.ContentListener; 27f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Changimport com.android.gallery3d.data.LocalMediaItem; 28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaItem; 29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaObject; 30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaSet; 31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.Path; 32a4eae1abb4f2547dfbda84301ee764ce35464881John Reckimport com.android.gallery3d.glrenderer.TiledTexture; 33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.ui.PhotoView; 3415b351a22d02e89d882fc9fe32b3f4c512080e0aChih-Chung Changimport com.android.gallery3d.ui.ScreenNail; 35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.ui.SynchronizedHandler; 36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.ui.TileImageViewAdapter; 37030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Linimport com.android.gallery3d.ui.TiledScreenNail; 38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.util.Future; 39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.util.FutureListener; 40f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Changimport com.android.gallery3d.util.MediaSetUtils; 41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.util.ThreadPool; 4222493b29c32142f2588c623f5c78e9167352dddcOwen Linimport com.android.gallery3d.util.ThreadPool.Job; 4322493b29c32142f2588c623f5c78e9167352dddcOwen Linimport com.android.gallery3d.util.ThreadPool.JobContext; 44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.ArrayList; 46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.Arrays; 47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.HashMap; 48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.HashSet; 49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.concurrent.Callable; 50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.concurrent.ExecutionException; 51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.concurrent.FutureTask; 52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class PhotoDataAdapter implements PhotoPage.Model { 54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @SuppressWarnings("unused") 55f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TAG = "PhotoDataAdapter"; 56f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int MSG_LOAD_START = 1; 58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int MSG_LOAD_FINISH = 2; 59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int MSG_RUN_OBJECT = 3; 60b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang private static final int MSG_UPDATE_IMAGE_REQUESTS = 4; 61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 62a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin private static final int MIN_LOAD_COUNT = 16; 63a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin private static final int DATA_CACHE_SIZE = 256; 64b7ec5534c7b539be2397c27cfa5e8b992974c12dChih-Chung Chang private static final int SCREEN_NAIL_MAX = PhotoView.SCREEN_NAIL_MAX; 65b7ec5534c7b539be2397c27cfa5e8b992974c12dChih-Chung Chang private static final int IMAGE_CACHE_SIZE = 2 * SCREEN_NAIL_MAX + 1; 66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int BIT_SCREEN_NAIL = 1; 68f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int BIT_FULL_IMAGE = 2; 69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // sImageFetchSeq is the fetching sequence for images. 71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // We want to fetch the current screennail first (offset = 0), the next 72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // screennail (offset = +1), then the previous screennail (offset = -1) etc. 73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // After all the screennail are fetched, we fetch the full images (only some 74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // of them because of we don't want to use too much memory). 75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static ImageFetch[] sImageFetchSeq; 76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 77f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static class ImageFetch { 78f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int indexOffset; 79f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int imageBit; 80f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public ImageFetch(int offset, int bit) { 81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin indexOffset = offset; 82f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin imageBit = bit; 83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin static { 87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int k = 0; 88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin sImageFetchSeq = new ImageFetch[1 + (IMAGE_CACHE_SIZE - 1) * 2 + 3]; 89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin sImageFetchSeq[k++] = new ImageFetch(0, BIT_SCREEN_NAIL); 90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = 1; i < IMAGE_CACHE_SIZE; ++i) { 92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin sImageFetchSeq[k++] = new ImageFetch(i, BIT_SCREEN_NAIL); 93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin sImageFetchSeq[k++] = new ImageFetch(-i, BIT_SCREEN_NAIL); 94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin sImageFetchSeq[k++] = new ImageFetch(0, BIT_FULL_IMAGE); 97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin sImageFetchSeq[k++] = new ImageFetch(1, BIT_FULL_IMAGE); 98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin sImageFetchSeq[k++] = new ImageFetch(-1, BIT_FULL_IMAGE); 99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private final TileImageViewAdapter mTileProvider = new TileImageViewAdapter(); 102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // PhotoDataAdapter caches MediaItems (data) and ImageEntries (image). 104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // 105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // The MediaItems are stored in the mData array, which has DATA_CACHE_SIZE 106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // entries. The valid index range are [mContentStart, mContentEnd). We keep 107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // mContentEnd - mContentStart <= DATA_CACHE_SIZE, so we can use 108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // (i % DATA_CACHE_SIZE) as index to the array. 109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // 110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // The valid MediaItem window size (mContentEnd - mContentStart) may be 111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // smaller than DATA_CACHE_SIZE because we only update the window and reload 112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // the MediaItems when there are significant changes to the window position 113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // (>= MIN_LOAD_COUNT). 114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private final MediaItem mData[] = new MediaItem[DATA_CACHE_SIZE]; 115f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int mContentStart = 0; 116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int mContentEnd = 0; 117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 118f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // The ImageCache is a Path-to-ImageEntry map. It only holds the 119f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // ImageEntries in the range of [mActiveStart, mActiveEnd). We also keep 120f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // mActiveEnd - mActiveStart <= IMAGE_CACHE_SIZE. Besides, the 121f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // [mActiveStart, mActiveEnd) range must be contained within 122f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // the [mContentStart, mContentEnd) range. 123f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang private HashMap<Path, ImageEntry> mImageCache = 124f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang new HashMap<Path, ImageEntry>(); 125f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int mActiveStart = 0; 126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int mActiveEnd = 0; 127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // mCurrentIndex is the "center" image the user is viewing. The change of 129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // mCurrentIndex triggers the data loading and image loading. 130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int mCurrentIndex; 131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 132214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang // mChanges keeps the version number (of MediaItem) about the images. If any 133214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang // of the version number changes, we notify the view. This is used after a 134214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang // database reload or mCurrentIndex changes. 135b7ec5534c7b539be2397c27cfa5e8b992974c12dChih-Chung Chang private final long mChanges[] = new long[IMAGE_CACHE_SIZE]; 136214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang // mPaths keeps the corresponding Path (of MediaItem) for the images. This 137214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang // is used to determine the item movement. 138214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang private final Path mPaths[] = new Path[IMAGE_CACHE_SIZE]; 139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private final Handler mMainHandler; 141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private final ThreadPool mThreadPool; 142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private final PhotoView mPhotoView; 144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private final MediaSet mSource; 145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private ReloadTask mReloadTask; 146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private long mSourceVersion = MediaObject.INVALID_DATA_VERSION; 148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int mSize = 0; 149f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private Path mItemPath; 150bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang private int mCameraIndex; 15143a80fd806247cb50e81bacda3ad21d210e9ae88Angus Kong private boolean mIsPanorama; 152dbb6acc204ba6f095eb0e49e1298e9ceda2c3096Wu-cheng Li private boolean mIsStaticCamera; 153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private boolean mIsActive; 154b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang private boolean mNeedFullImage; 1556b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang private int mFocusHintDirection = FOCUS_HINT_NEXT; 1566b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang private Path mFocusHintPath = null; 157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public interface DataListener extends LoadingListener { 159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void onPhotoChanged(int index, Path item); 160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private DataListener mDataListener; 163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private final SourceListener mSourceListener = new SourceListener(); 165a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin private final TiledTexture.Uploader mUploader; 166f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // The path of the current viewing item will be stored in mItemPath. 168f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // If mItemPath is not null, mCurrentIndex is only a hint for where we 169f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // can find the item. If mItemPath is null, then we use the mCurrentIndex to 170214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang // find the image being viewed. cameraIndex is the index of the camera 171214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang // preview. If cameraIndex < 0, there is no camera preview. 172b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin public PhotoDataAdapter(AbstractGalleryActivity activity, PhotoView view, 17343a80fd806247cb50e81bacda3ad21d210e9ae88Angus Kong MediaSet mediaSet, Path itemPath, int indexHint, int cameraIndex, 174dbb6acc204ba6f095eb0e49e1298e9ceda2c3096Wu-cheng Li boolean isPanorama, boolean isStaticCamera) { 175f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mSource = Utils.checkNotNull(mediaSet); 176f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mPhotoView = Utils.checkNotNull(view); 177f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mItemPath = Utils.checkNotNull(itemPath); 178f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mCurrentIndex = indexHint; 179bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang mCameraIndex = cameraIndex; 18043a80fd806247cb50e81bacda3ad21d210e9ae88Angus Kong mIsPanorama = isPanorama; 181dbb6acc204ba6f095eb0e49e1298e9ceda2c3096Wu-cheng Li mIsStaticCamera = isStaticCamera; 182f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mThreadPool = activity.getThreadPool(); 183b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang mNeedFullImage = true; 184f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Arrays.fill(mChanges, MediaObject.INVALID_DATA_VERSION); 186f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 187a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin mUploader = new TiledTexture.Uploader(activity.getGLRoot()); 188a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin 189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mMainHandler = new SynchronizedHandler(activity.getGLRoot()) { 190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @SuppressWarnings("unchecked") 191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void handleMessage(Message message) { 193f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin switch (message.what) { 194f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case MSG_RUN_OBJECT: 195f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ((Runnable) message.obj).run(); 196f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return; 197f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case MSG_LOAD_START: { 198f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (mDataListener != null) { 199f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang mDataListener.onLoadingStarted(); 200f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang } 201f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return; 202f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 203f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case MSG_LOAD_FINISH: { 204f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (mDataListener != null) { 20505da3f520eacb9219964b6ed57ef37846d889fd7Hung-ying Tyan mDataListener.onLoadingFinished(false); 206f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang } 207f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return; 208f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 209b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang case MSG_UPDATE_IMAGE_REQUESTS: { 210b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang updateImageRequests(); 211b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang return; 212b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang } 213f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin default: throw new AssertionError(); 214f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 215f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 216f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin }; 217f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 218f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin updateSlidingWindow(); 219f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 220f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 221214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang private MediaItem getItemInternal(int index) { 222214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang if (index < 0 || index >= mSize) return null; 223f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (index >= mContentStart && index < mContentEnd) { 224214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang return mData[index % DATA_CACHE_SIZE]; 225f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 226214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang return null; 227214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang } 228214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang 229214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang private long getVersion(int index) { 230214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang MediaItem item = getItemInternal(index); 231214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang if (item == null) return MediaObject.INVALID_DATA_VERSION; 232214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang return item.getDataVersion(); 233214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang } 234214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang 235214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang private Path getPath(int index) { 236214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang MediaItem item = getItemInternal(index); 237214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang if (item == null) return null; 238214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang return item.getPath(); 239f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 240f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 241b7ec5534c7b539be2397c27cfa5e8b992974c12dChih-Chung Chang private void fireDataChange() { 242214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang // First check if data actually changed. 243214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang boolean changed = false; 244b7ec5534c7b539be2397c27cfa5e8b992974c12dChih-Chung Chang for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; ++i) { 245214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang long newVersion = getVersion(mCurrentIndex + i); 246214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang if (mChanges[i + SCREEN_NAIL_MAX] != newVersion) { 247214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang mChanges[i + SCREEN_NAIL_MAX] = newVersion; 248214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang changed = true; 249214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang } 250f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 251214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang 252214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang if (!changed) return; 253214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang 254214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang // Now calculate the fromIndex array. fromIndex represents the item 255214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang // movement. It records the index where the picture come from. The 256214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang // special value Integer.MAX_VALUE means it's a new picture. 257214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang final int N = IMAGE_CACHE_SIZE; 258214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang int fromIndex[] = new int[N]; 259214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang 260214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang // Remember the old path array. 261214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang Path oldPaths[] = new Path[N]; 262214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang System.arraycopy(mPaths, 0, oldPaths, 0, N); 263214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang 264214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang // Update the mPaths array. 265214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang for (int i = 0; i < N; ++i) { 266214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang mPaths[i] = getPath(mCurrentIndex + i - SCREEN_NAIL_MAX); 267214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang } 268214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang 269214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang // Calculate the fromIndex array. 270214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang for (int i = 0; i < N; i++) { 271214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang Path p = mPaths[i]; 272214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang if (p == null) { 273214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang fromIndex[i] = Integer.MAX_VALUE; 274214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang continue; 275214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang } 276214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang 277214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang // Try to find the same path in the old array 278214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang int j; 279214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang for (j = 0; j < N; j++) { 280214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang if (oldPaths[j] == p) { 281214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang break; 282214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang } 283214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang } 284214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang fromIndex[i] = (j < N) ? j - SCREEN_NAIL_MAX : Integer.MAX_VALUE; 285214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang } 286214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang 287214993dc4abf87c386123af50e3c34184ba11cb6Chih-Chung Chang mPhotoView.notifyDataChange(fromIndex, -mCurrentIndex, 288c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang mSize - 1 - mCurrentIndex); 289f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 290f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 291f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void setDataListener(DataListener listener) { 292f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mDataListener = listener; 293f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 294f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 295f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang private void updateScreenNail(Path path, Future<ScreenNail> future) { 296f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang ImageEntry entry = mImageCache.get(path); 29715b351a22d02e89d882fc9fe32b3f4c512080e0aChih-Chung Chang ScreenNail screenNail = future.get(); 29815b351a22d02e89d882fc9fe32b3f4c512080e0aChih-Chung Chang 299e7327d0566b182c522ca6dfa8e04c649d8f631a0Owen Lin if (entry == null || entry.screenNailTask != future) { 300b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang if (screenNail != null) screenNail.recycle(); 301f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return; 302f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 303e7327d0566b182c522ca6dfa8e04c649d8f631a0Owen Lin 304f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin entry.screenNailTask = null; 305f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang 306f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // Combine the ScreenNails if we already have a BitmapScreenNail 307030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin if (entry.screenNail instanceof TiledScreenNail) { 308030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin TiledScreenNail original = (TiledScreenNail) entry.screenNail; 309f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang screenNail = original.combine(screenNail); 310f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang } 311f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 31215b351a22d02e89d882fc9fe32b3f4c512080e0aChih-Chung Chang if (screenNail == null) { 313f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin entry.failToLoad = true; 314f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang } else { 315f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang entry.failToLoad = false; 316f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang entry.screenNail = screenNail; 317a7b78e224b1808895ea2c3d42ae385526dea12aaYuli Huang } 31815b351a22d02e89d882fc9fe32b3f4c512080e0aChih-Chung Chang 319b7ec5534c7b539be2397c27cfa5e8b992974c12dChih-Chung Chang for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; ++i) { 320f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (path == getPath(mCurrentIndex + i)) { 321a7b78e224b1808895ea2c3d42ae385526dea12aaYuli Huang if (i == 0) updateTileProvider(entry); 322b7ec5534c7b539be2397c27cfa5e8b992974c12dChih-Chung Chang mPhotoView.notifyImageChange(i); 323b7ec5534c7b539be2397c27cfa5e8b992974c12dChih-Chung Chang break; 324f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 325f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 326f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin updateImageRequests(); 327a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin updateScreenNailUploadQueue(); 328f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 329f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 330f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang private void updateFullImage(Path path, Future<BitmapRegionDecoder> future) { 331f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang ImageEntry entry = mImageCache.get(path); 332e7327d0566b182c522ca6dfa8e04c649d8f631a0Owen Lin if (entry == null || entry.fullImageTask != future) { 333f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin BitmapRegionDecoder fullImage = future.get(); 334f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (fullImage != null) fullImage.recycle(); 335f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return; 336f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 337e7327d0566b182c522ca6dfa8e04c649d8f631a0Owen Lin 338f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin entry.fullImageTask = null; 339f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin entry.fullImage = future.get(); 340f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (entry.fullImage != null) { 341f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (path == getPath(mCurrentIndex)) { 342f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin updateTileProvider(entry); 343b7ec5534c7b539be2397c27cfa5e8b992974c12dChih-Chung Chang mPhotoView.notifyImageChange(0); 344f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 345f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 346f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin updateImageRequests(); 347f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 348f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 3497817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 350f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void resume() { 351f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mIsActive = true; 352a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin TiledTexture.prepareResources(); 353a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin 354f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mSource.addContentListener(mSourceListener); 355f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin updateImageCache(); 356f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin updateImageRequests(); 357f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 358f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mReloadTask = new ReloadTask(); 359f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mReloadTask.start(); 360f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 361b7ec5534c7b539be2397c27cfa5e8b992974c12dChih-Chung Chang fireDataChange(); 362f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 363f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 3647817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 365f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void pause() { 366f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mIsActive = false; 367f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 368f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mReloadTask.terminate(); 369f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mReloadTask = null; 370f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 371f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mSource.removeContentListener(mSourceListener); 372f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 373f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (ImageEntry entry : mImageCache.values()) { 374f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (entry.fullImageTask != null) entry.fullImageTask.cancel(); 375f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (entry.screenNailTask != null) entry.screenNailTask.cancel(); 376b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang if (entry.screenNail != null) entry.screenNail.recycle(); 377f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 378f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mImageCache.clear(); 379f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mTileProvider.clear(); 380a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin 381a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin mUploader.clear(); 382a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin TiledTexture.freeResources(); 383f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 384f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 385c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang private MediaItem getItem(int index) { 386c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang if (index < 0 || index >= mSize || !mIsActive) return null; 387c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang Utils.assertTrue(index >= mActiveStart && index < mActiveEnd); 388c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang 389c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang if (index >= mContentStart && index < mContentEnd) { 390c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang return mData[index % DATA_CACHE_SIZE]; 391c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang } 392c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang return null; 393f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 394f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 395f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void updateCurrentIndex(int index) { 396bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang if (mCurrentIndex == index) return; 397f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mCurrentIndex = index; 398f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin updateSlidingWindow(); 399f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 400f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin MediaItem item = mData[index % DATA_CACHE_SIZE]; 401f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mItemPath = item == null ? null : item.getPath(); 402f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 403f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin updateImageCache(); 404f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin updateImageRequests(); 405f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin updateTileProvider(); 406f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 407f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mDataListener != null) { 408f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mDataListener.onPhotoChanged(index, mItemPath); 409f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 410b7ec5534c7b539be2397c27cfa5e8b992974c12dChih-Chung Chang 411b7ec5534c7b539be2397c27cfa5e8b992974c12dChih-Chung Chang fireDataChange(); 412f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 413f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 414a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin private void uploadScreenNail(int offset) { 415a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin int index = mCurrentIndex + offset; 416a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin if (index < mActiveStart || index >= mActiveEnd) return; 417a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin 418a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin MediaItem item = getItem(index); 419a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin if (item == null) return; 420a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin 421a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin ImageEntry e = mImageCache.get(item.getPath()); 422a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin if (e == null) return; 423a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin 424a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin ScreenNail s = e.screenNail; 425030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin if (s instanceof TiledScreenNail) { 426030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin TiledTexture t = ((TiledScreenNail) s).getTexture(); 427a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin if (t != null && !t.isReady()) mUploader.addTexture(t); 428a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin } 429a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin } 430a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin 431a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin private void updateScreenNailUploadQueue() { 432a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin mUploader.clear(); 433a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin uploadScreenNail(0); 434a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin for (int i = 1; i < IMAGE_CACHE_SIZE; ++i) { 435a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin uploadScreenNail(i); 436a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin uploadScreenNail(-i); 437a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin } 438a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin } 439a8f3473271cb4bfc5b47f520402bad7cddb5d3e8Owen Lin 440c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang @Override 441bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang public void moveTo(int index) { 442bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang updateCurrentIndex(index); 443160e6d776daab93610b3d12413ad9ff2dd867d8bChih-Chung Chang } 444160e6d776daab93610b3d12413ad9ff2dd867d8bChih-Chung Chang 445160e6d776daab93610b3d12413ad9ff2dd867d8bChih-Chung Chang @Override 446c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang public ScreenNail getScreenNail(int offset) { 447f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang int index = mCurrentIndex + offset; 448f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (index < 0 || index >= mSize || !mIsActive) return null; 449f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang Utils.assertTrue(index >= mActiveStart && index < mActiveEnd); 450f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang 451f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang MediaItem item = getItem(index); 452f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (item == null) return null; 453f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang 454f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang ImageEntry entry = mImageCache.get(item.getPath()); 455f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (entry == null) return null; 456f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang 4576b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang // Create a default ScreenNail if the real one is not available yet, 4586b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang // except for camera that a black screen is better than a gray tile. 4596b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang if (entry.screenNail == null && !isCamera(offset)) { 46049affdc4e274098a34e4eb2dbe4a89a750f1ba7fOwen Lin entry.screenNail = newPlaceholderScreenNail(item); 461f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (offset == 0) updateTileProvider(entry); 462f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang } 463f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang 464f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang return entry.screenNail; 465c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang } 466c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang 467c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang @Override 468c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang public void getImageSize(int offset, PhotoView.Size size) { 469c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang MediaItem item = getItem(mCurrentIndex + offset); 470c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang if (item == null) { 471c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang size.width = 0; 472c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang size.height = 0; 473c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang } else { 474c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang size.width = item.getWidth(); 475c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang size.height = item.getHeight(); 476c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang } 477c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang } 478c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang 479c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang @Override 480c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang public int getImageRotation(int offset) { 481c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang MediaItem item = getItem(mCurrentIndex + offset); 482c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang return (item == null) ? 0 : item.getFullImageRotation(); 483c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang } 484c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang 485c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang @Override 486c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang public void setNeedFullImage(boolean enabled) { 487c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang mNeedFullImage = enabled; 488c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang mMainHandler.sendEmptyMessage(MSG_UPDATE_IMAGE_REQUESTS); 489c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang } 490c3b2d478f9032a8decf5c6254a238fc49e41b72cChih-Chung Chang 491bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang @Override 492bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang public boolean isCamera(int offset) { 493bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang return mCurrentIndex + offset == mCameraIndex; 494bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang } 495bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang 496d9355113da391f8bbddef1d2a2126ce6edc72291Chih-Chung Chang @Override 49743a80fd806247cb50e81bacda3ad21d210e9ae88Angus Kong public boolean isPanorama(int offset) { 49843a80fd806247cb50e81bacda3ad21d210e9ae88Angus Kong return isCamera(offset) && mIsPanorama; 49943a80fd806247cb50e81bacda3ad21d210e9ae88Angus Kong } 50043a80fd806247cb50e81bacda3ad21d210e9ae88Angus Kong 50143a80fd806247cb50e81bacda3ad21d210e9ae88Angus Kong @Override 502dbb6acc204ba6f095eb0e49e1298e9ceda2c3096Wu-cheng Li public boolean isStaticCamera(int offset) { 503dbb6acc204ba6f095eb0e49e1298e9ceda2c3096Wu-cheng Li return isCamera(offset) && mIsStaticCamera; 504dbb6acc204ba6f095eb0e49e1298e9ceda2c3096Wu-cheng Li } 505dbb6acc204ba6f095eb0e49e1298e9ceda2c3096Wu-cheng Li 506dbb6acc204ba6f095eb0e49e1298e9ceda2c3096Wu-cheng Li @Override 507d9355113da391f8bbddef1d2a2126ce6edc72291Chih-Chung Chang public boolean isVideo(int offset) { 508d9355113da391f8bbddef1d2a2126ce6edc72291Chih-Chung Chang MediaItem item = getItem(mCurrentIndex + offset); 509d9355113da391f8bbddef1d2a2126ce6edc72291Chih-Chung Chang return (item == null) 510d9355113da391f8bbddef1d2a2126ce6edc72291Chih-Chung Chang ? false 511d9355113da391f8bbddef1d2a2126ce6edc72291Chih-Chung Chang : item.getMediaType() == MediaItem.MEDIA_TYPE_VIDEO; 512d9355113da391f8bbddef1d2a2126ce6edc72291Chih-Chung Chang } 513d9355113da391f8bbddef1d2a2126ce6edc72291Chih-Chung Chang 514f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang @Override 5156b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang public boolean isDeletable(int offset) { 5166b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang MediaItem item = getItem(mCurrentIndex + offset); 5176b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang return (item == null) 5186b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang ? false 5196b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang : (item.getSupportedOperations() & MediaItem.SUPPORT_DELETE) != 0; 5206b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang } 5216b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang 5226b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang @Override 523f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang public int getLoadingState(int offset) { 524f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang ImageEntry entry = mImageCache.get(getPath(mCurrentIndex + offset)); 525f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (entry == null) return LOADING_INIT; 526f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (entry.failToLoad) return LOADING_FAIL; 527f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (entry.screenNail != null) return LOADING_COMPLETE; 528f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang return LOADING_INIT; 529f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang } 530f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang 5317817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 53215b351a22d02e89d882fc9fe32b3f4c512080e0aChih-Chung Chang public ScreenNail getScreenNail() { 5336b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang return getScreenNail(0); 534f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 535f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 5367817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 537f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int getImageHeight() { 538f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mTileProvider.getImageHeight(); 539f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 540f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 5417817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 542f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int getImageWidth() { 543f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mTileProvider.getImageWidth(); 544f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 545f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 5467817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 547f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int getLevelCount() { 548f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mTileProvider.getLevelCount(); 549f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 550f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 5517817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 552f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu public Bitmap getTile(int level, int x, int y, int tileSize) { 553f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu return mTileProvider.getTile(level, x, y, tileSize); 554f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 555f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 5567817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 557f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public boolean isEmpty() { 558f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mSize == 0; 559f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 560f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 5617817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 562f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int getCurrentIndex() { 563f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mCurrentIndex; 564f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 565f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 5667817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 567616a70fdb4473d2fbd7b70772a3a82b908aeae1eOwen Lin public MediaItem getMediaItem(int offset) { 568616a70fdb4473d2fbd7b70772a3a82b908aeae1eOwen Lin int index = mCurrentIndex + offset; 569616a70fdb4473d2fbd7b70772a3a82b908aeae1eOwen Lin if (index >= mContentStart && index < mContentEnd) { 570616a70fdb4473d2fbd7b70772a3a82b908aeae1eOwen Lin return mData[index % DATA_CACHE_SIZE]; 571616a70fdb4473d2fbd7b70772a3a82b908aeae1eOwen Lin } 572616a70fdb4473d2fbd7b70772a3a82b908aeae1eOwen Lin return null; 573f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 574f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 5757817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 576f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void setCurrentPhoto(Path path, int indexHint) { 577f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mItemPath == path) return; 578f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mItemPath = path; 579f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mCurrentIndex = indexHint; 580f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin updateSlidingWindow(); 581f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin updateImageCache(); 582b7ec5534c7b539be2397c27cfa5e8b992974c12dChih-Chung Chang fireDataChange(); 583f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 584f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // We need to reload content if the path doesn't match. 585616a70fdb4473d2fbd7b70772a3a82b908aeae1eOwen Lin MediaItem item = getMediaItem(0); 586f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (item != null && item.getPath() != path) { 587f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mReloadTask != null) mReloadTask.notifyDirty(); 588f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 589f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 590f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 5917817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 5926b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang public void setFocusHintDirection(int direction) { 5936b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang mFocusHintDirection = direction; 5946b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang } 5956b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang 5967817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 5976b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang public void setFocusHintPath(Path path) { 5986b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang mFocusHintPath = path; 5996b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang } 6006b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang 601f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void updateTileProvider() { 602f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang ImageEntry entry = mImageCache.get(getPath(mCurrentIndex)); 603f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (entry == null) { // in loading 604f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mTileProvider.clear(); 605f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 606f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin updateTileProvider(entry); 607f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 608f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 609f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 610f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void updateTileProvider(ImageEntry entry) { 61115b351a22d02e89d882fc9fe32b3f4c512080e0aChih-Chung Chang ScreenNail screenNail = entry.screenNail; 612f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin BitmapRegionDecoder fullImage = entry.fullImage; 613f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (screenNail != null) { 614f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (fullImage != null) { 61515b351a22d02e89d882fc9fe32b3f4c512080e0aChih-Chung Chang mTileProvider.setScreenNail(screenNail, 616f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin fullImage.getWidth(), fullImage.getHeight()); 617f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mTileProvider.setRegionDecoder(fullImage); 618f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 619f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int width = screenNail.getWidth(); 620f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int height = screenNail.getHeight(); 62115b351a22d02e89d882fc9fe32b3f4c512080e0aChih-Chung Chang mTileProvider.setScreenNail(screenNail, width, height); 622f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 623f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 624f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mTileProvider.clear(); 625f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 626f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 627f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 628f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void updateSlidingWindow() { 629f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // 1. Update the image window 630f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int start = Utils.clamp(mCurrentIndex - IMAGE_CACHE_SIZE / 2, 631f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 0, Math.max(0, mSize - IMAGE_CACHE_SIZE)); 632f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int end = Math.min(mSize, start + IMAGE_CACHE_SIZE); 633f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 634f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mActiveStart == start && mActiveEnd == end) return; 635f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 636f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mActiveStart = start; 637f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mActiveEnd = end; 638f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 639f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // 2. Update the data window 640f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin start = Utils.clamp(mCurrentIndex - DATA_CACHE_SIZE / 2, 641f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 0, Math.max(0, mSize - DATA_CACHE_SIZE)); 642f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin end = Math.min(mSize, start + DATA_CACHE_SIZE); 643f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mContentStart > mActiveStart || mContentEnd < mActiveEnd 644f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin || Math.abs(start - mContentStart) > MIN_LOAD_COUNT) { 645f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = mContentStart; i < mContentEnd; ++i) { 646f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (i < start || i >= end) { 647f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mData[i % DATA_CACHE_SIZE] = null; 648f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 649f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 650f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mContentStart = start; 651f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mContentEnd = end; 652f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mReloadTask != null) mReloadTask.notifyDirty(); 653f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 654f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 655f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 656f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void updateImageRequests() { 657f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (!mIsActive) return; 658f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 659f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int currentIndex = mCurrentIndex; 660f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin MediaItem item = mData[currentIndex % DATA_CACHE_SIZE]; 661f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (item == null || item.getPath() != mItemPath) { 662f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // current item mismatch - don't request image 663f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return; 664f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 665f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 666f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // 1. Find the most wanted request and start it (if not already started). 667f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Future<?> task = null; 668f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = 0; i < sImageFetchSeq.length; i++) { 669f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int offset = sImageFetchSeq[i].indexOffset; 670f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int bit = sImageFetchSeq[i].imageBit; 671b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang if (bit == BIT_FULL_IMAGE && !mNeedFullImage) continue; 672f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin task = startTaskIfNeeded(currentIndex + offset, bit); 673f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (task != null) break; 674f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 675f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 676f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // 2. Cancel everything else. 677f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (ImageEntry entry : mImageCache.values()) { 678f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (entry.screenNailTask != null && entry.screenNailTask != task) { 679f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin entry.screenNailTask.cancel(); 680f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin entry.screenNailTask = null; 681f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang entry.requestedScreenNail = MediaObject.INVALID_DATA_VERSION; 682f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 683f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (entry.fullImageTask != null && entry.fullImageTask != task) { 684f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin entry.fullImageTask.cancel(); 685f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin entry.fullImageTask = null; 686f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang entry.requestedFullImage = MediaObject.INVALID_DATA_VERSION; 687f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 688f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 689f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 690f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 691f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang private class ScreenNailJob implements Job<ScreenNail> { 69222493b29c32142f2588c623f5c78e9167352dddcOwen Lin private MediaItem mItem; 69322493b29c32142f2588c623f5c78e9167352dddcOwen Lin 69422493b29c32142f2588c623f5c78e9167352dddcOwen Lin public ScreenNailJob(MediaItem item) { 69522493b29c32142f2588c623f5c78e9167352dddcOwen Lin mItem = item; 69622493b29c32142f2588c623f5c78e9167352dddcOwen Lin } 69722493b29c32142f2588c623f5c78e9167352dddcOwen Lin 69822493b29c32142f2588c623f5c78e9167352dddcOwen Lin @Override 69915b351a22d02e89d882fc9fe32b3f4c512080e0aChih-Chung Chang public ScreenNail run(JobContext jc) { 70015b351a22d02e89d882fc9fe32b3f4c512080e0aChih-Chung Chang // We try to get a ScreenNail first, if it fails, we fallback to get 70115b351a22d02e89d882fc9fe32b3f4c512080e0aChih-Chung Chang // a Bitmap and then wrap it in a BitmapScreenNail instead. 70215b351a22d02e89d882fc9fe32b3f4c512080e0aChih-Chung Chang ScreenNail s = mItem.getScreenNail(); 70315b351a22d02e89d882fc9fe32b3f4c512080e0aChih-Chung Chang if (s != null) return s; 70415b351a22d02e89d882fc9fe32b3f4c512080e0aChih-Chung Chang 705f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // If this is a temporary item, don't try to get its bitmap because 706f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // it won't be available. We will get its bitmap after a data reload. 707f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (isTemporaryItem(mItem)) { 70849affdc4e274098a34e4eb2dbe4a89a750f1ba7fOwen Lin return newPlaceholderScreenNail(mItem); 709f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang } 710f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang 71122493b29c32142f2588c623f5c78e9167352dddcOwen Lin Bitmap bitmap = mItem.requestImage(MediaItem.TYPE_THUMBNAIL).run(jc); 71222493b29c32142f2588c623f5c78e9167352dddcOwen Lin if (jc.isCancelled()) return null; 71322493b29c32142f2588c623f5c78e9167352dddcOwen Lin if (bitmap != null) { 71422493b29c32142f2588c623f5c78e9167352dddcOwen Lin bitmap = BitmapUtils.rotateBitmap(bitmap, 71522493b29c32142f2588c623f5c78e9167352dddcOwen Lin mItem.getRotation() - mItem.getFullImageRotation(), true); 71622493b29c32142f2588c623f5c78e9167352dddcOwen Lin } 717030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin return bitmap == null ? null : new TiledScreenNail(bitmap); 71822493b29c32142f2588c623f5c78e9167352dddcOwen Lin } 71922493b29c32142f2588c623f5c78e9167352dddcOwen Lin } 72022493b29c32142f2588c623f5c78e9167352dddcOwen Lin 721f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang private class FullImageJob implements Job<BitmapRegionDecoder> { 722f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang private MediaItem mItem; 723f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang 724f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang public FullImageJob(MediaItem item) { 725f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang mItem = item; 726f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang } 727f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang 728f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang @Override 729f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang public BitmapRegionDecoder run(JobContext jc) { 730f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (isTemporaryItem(mItem)) { 731f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang return null; 732f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang } 733f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang return mItem.requestLargeImage().run(jc); 734f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang } 735f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang } 736f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang 737f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // Returns true if we think this is a temporary item created by Camera. A 738f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // temporary item is an image or a video whose data is still being 739f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // processed, but an incomplete entry is created first in MediaProvider, so 740f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // we can display them (in grey tile) even if they are not saved to disk 741f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // yet. When the image or video data is actually saved, we will get 742f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // notification from MediaProvider, reload data, and show the actual image 743f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // or video data. 744f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang private boolean isTemporaryItem(MediaItem mediaItem) { 745f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // Must have camera to create a temporary item. 746f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (mCameraIndex < 0) return false; 747f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // Must be an item in camera roll. 748f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (!(mediaItem instanceof LocalMediaItem)) return false; 749f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang LocalMediaItem item = (LocalMediaItem) mediaItem; 750f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (item.getBucketId() != MediaSetUtils.CAMERA_BUCKET_ID) return false; 751f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // Must have no size, but must have width and height information 752f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (item.getSize() != 0) return false; 753f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (item.getWidth() == 0) return false; 754f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (item.getHeight() == 0) return false; 755f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // Must be created in the last 10 seconds. 756f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (item.getDateInMs() - System.currentTimeMillis() > 10000) return false; 757f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang return true; 758f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang } 759f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang 760f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // Create a default ScreenNail when a ScreenNail is needed, but we don't yet 761f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // have one available (because the image data is still being saved, or the 762f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // Bitmap is still being loaded. 76349affdc4e274098a34e4eb2dbe4a89a750f1ba7fOwen Lin private ScreenNail newPlaceholderScreenNail(MediaItem item) { 764f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang int width = item.getWidth(); 765f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang int height = item.getHeight(); 766030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin return new TiledScreenNail(width, height); 767f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang } 768f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang 769f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Returns the task if we started the task or the task is already started. 770f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private Future<?> startTaskIfNeeded(int index, int which) { 771f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (index < mActiveStart || index >= mActiveEnd) return null; 772f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 773f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang ImageEntry entry = mImageCache.get(getPath(index)); 774f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (entry == null) return null; 775f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang MediaItem item = mData[index % DATA_CACHE_SIZE]; 776f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang Utils.assertTrue(item != null); 777f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang long version = item.getDataVersion(); 778f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 779f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (which == BIT_SCREEN_NAIL && entry.screenNailTask != null 780f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang && entry.requestedScreenNail == version) { 781f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return entry.screenNailTask; 782f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang } else if (which == BIT_FULL_IMAGE && entry.fullImageTask != null 783f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang && entry.requestedFullImage == version) { 784f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return entry.fullImageTask; 785f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 786f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 787f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (which == BIT_SCREEN_NAIL && entry.requestedScreenNail != version) { 788f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang entry.requestedScreenNail = version; 789f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin entry.screenNailTask = mThreadPool.submit( 79022493b29c32142f2588c623f5c78e9167352dddcOwen Lin new ScreenNailJob(item), 791f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang new ScreenNailListener(item)); 792f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // request screen nail 793f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return entry.screenNailTask; 794f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 795f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (which == BIT_FULL_IMAGE && entry.requestedFullImage != version 796f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin && (item.getSupportedOperations() 797f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin & MediaItem.SUPPORT_FULL_IMAGE) != 0) { 798f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang entry.requestedFullImage = version; 799f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin entry.fullImageTask = mThreadPool.submit( 800f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang new FullImageJob(item), 801f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang new FullImageListener(item)); 802f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // request full image 803f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return entry.fullImageTask; 804f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 805f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 806f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 807f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 808f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void updateImageCache() { 809f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang HashSet<Path> toBeRemoved = new HashSet<Path>(mImageCache.keySet()); 810f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = mActiveStart; i < mActiveEnd; ++i) { 811f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin MediaItem item = mData[i % DATA_CACHE_SIZE]; 812f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (item == null) continue; 813f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang Path path = item.getPath(); 814f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang ImageEntry entry = mImageCache.get(path); 815f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang toBeRemoved.remove(path); 816f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (entry != null) { 817f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (Math.abs(i - mCurrentIndex) > 1) { 818f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (entry.fullImageTask != null) { 819f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin entry.fullImageTask.cancel(); 820f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin entry.fullImageTask = null; 821f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 822f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin entry.fullImage = null; 823f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang entry.requestedFullImage = MediaObject.INVALID_DATA_VERSION; 824f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang } 825f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang if (entry.requestedScreenNail != item.getDataVersion()) { 826f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // This ScreenNail is outdated, we want to update it if it's 827f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang // still a placeholder. 828030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin if (entry.screenNail instanceof TiledScreenNail) { 829030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin TiledScreenNail s = (TiledScreenNail) entry.screenNail; 830f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang s.updatePlaceholderSize( 831f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang item.getWidth(), item.getHeight()); 832f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang } 833f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 834f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 835f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin entry = new ImageEntry(); 836f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang mImageCache.put(path, entry); 837f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 838f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 839f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 840f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Clear the data and requests for ImageEntries outside the new window. 841f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang for (Path path : toBeRemoved) { 842f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang ImageEntry entry = mImageCache.remove(path); 843f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (entry.fullImageTask != null) entry.fullImageTask.cancel(); 844f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (entry.screenNailTask != null) entry.screenNailTask.cancel(); 845b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang if (entry.screenNail != null) entry.screenNail.recycle(); 846f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 847030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 848030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin updateScreenNailUploadQueue(); 849f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 850f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 851f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private class FullImageListener 852f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin implements Runnable, FutureListener<BitmapRegionDecoder> { 853f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang private final Path mPath; 854f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private Future<BitmapRegionDecoder> mFuture; 855f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 856f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang public FullImageListener(MediaItem item) { 857f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang mPath = item.getPath(); 858f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 859f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 860e7327d0566b182c522ca6dfa8e04c649d8f631a0Owen Lin @Override 861f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void onFutureDone(Future<BitmapRegionDecoder> future) { 862f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mFuture = future; 863f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mMainHandler.sendMessage( 864f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mMainHandler.obtainMessage(MSG_RUN_OBJECT, this)); 865f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 866f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 867e7327d0566b182c522ca6dfa8e04c649d8f631a0Owen Lin @Override 868f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void run() { 869f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang updateFullImage(mPath, mFuture); 870f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 871f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 872f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 873f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private class ScreenNailListener 87415b351a22d02e89d882fc9fe32b3f4c512080e0aChih-Chung Chang implements Runnable, FutureListener<ScreenNail> { 875f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang private final Path mPath; 87615b351a22d02e89d882fc9fe32b3f4c512080e0aChih-Chung Chang private Future<ScreenNail> mFuture; 877f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 878f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang public ScreenNailListener(MediaItem item) { 879f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang mPath = item.getPath(); 880f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 881f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 882e7327d0566b182c522ca6dfa8e04c649d8f631a0Owen Lin @Override 88315b351a22d02e89d882fc9fe32b3f4c512080e0aChih-Chung Chang public void onFutureDone(Future<ScreenNail> future) { 884f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mFuture = future; 885f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mMainHandler.sendMessage( 886f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mMainHandler.obtainMessage(MSG_RUN_OBJECT, this)); 887f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 888f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 889e7327d0566b182c522ca6dfa8e04c649d8f631a0Owen Lin @Override 890f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void run() { 891f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang updateScreenNail(mPath, mFuture); 892f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 893f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 894f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 895f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static class ImageEntry { 896f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public BitmapRegionDecoder fullImage; 89715b351a22d02e89d882fc9fe32b3f4c512080e0aChih-Chung Chang public ScreenNail screenNail; 89815b351a22d02e89d882fc9fe32b3f4c512080e0aChih-Chung Chang public Future<ScreenNail> screenNailTask; 899f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public Future<BitmapRegionDecoder> fullImageTask; 900f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang public long requestedScreenNail = MediaObject.INVALID_DATA_VERSION; 901f5ce6aeba448f418c99736465f7a02dacd7715bbChih-Chung Chang public long requestedFullImage = MediaObject.INVALID_DATA_VERSION; 902f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public boolean failToLoad = false; 903f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 904f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 905f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private class SourceListener implements ContentListener { 9067817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 907f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void onContentDirty() { 908f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mReloadTask != null) mReloadTask.notifyDirty(); 909f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 910f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 911f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 912f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private <T> T executeAndWait(Callable<T> callable) { 913f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin FutureTask<T> task = new FutureTask<T>(callable); 914f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mMainHandler.sendMessage( 915f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mMainHandler.obtainMessage(MSG_RUN_OBJECT, task)); 916f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 917f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return task.get(); 918f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (InterruptedException e) { 919f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 920f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (ExecutionException e) { 921f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin throw new RuntimeException(e); 922f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 923f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 924f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 925f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static class UpdateInfo { 926f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public long version; 927f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public boolean reloadContent; 928f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public Path target; 929f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int indexHint; 930f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int contentStart; 931f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int contentEnd; 932f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 933f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int size; 934f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public ArrayList<MediaItem> items; 935f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 936f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 937f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private class GetUpdateInfo implements Callable<UpdateInfo> { 938f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 939f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private boolean needContentReload() { 940f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = mContentStart, n = mContentEnd; i < n; ++i) { 941f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mData[i % DATA_CACHE_SIZE] == null) return true; 942f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 943f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin MediaItem current = mData[mCurrentIndex % DATA_CACHE_SIZE]; 944f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return current == null || current.getPath() != mItemPath; 945f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 946f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 947f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 948f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public UpdateInfo call() throws Exception { 949113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin // TODO: Try to load some data in first update 950f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin UpdateInfo info = new UpdateInfo(); 951f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin info.version = mSourceVersion; 952f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin info.reloadContent = needContentReload(); 953f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin info.target = mItemPath; 954f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin info.indexHint = mCurrentIndex; 955f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin info.contentStart = mContentStart; 956f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin info.contentEnd = mContentEnd; 957f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin info.size = mSize; 958f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return info; 959f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 960f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 961f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 962f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private class UpdateContent implements Callable<Void> { 963f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin UpdateInfo mUpdateInfo; 964f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 965f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public UpdateContent(UpdateInfo updateInfo) { 966f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mUpdateInfo = updateInfo; 967f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 968f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 969f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 970f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public Void call() throws Exception { 971f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin UpdateInfo info = mUpdateInfo; 972f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mSourceVersion = info.version; 973f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 974f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (info.size != mSize) { 975f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mSize = info.size; 976f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mContentEnd > mSize) mContentEnd = mSize; 977f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mActiveEnd > mSize) mActiveEnd = mSize; 978f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 979f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 9806b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang mCurrentIndex = info.indexHint; 981f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin updateSlidingWindow(); 982f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 983f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (info.items != null) { 984f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int start = Math.max(info.contentStart, mContentStart); 985f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int end = Math.min(info.contentStart + info.items.size(), mContentEnd); 986f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int dataIndex = start % DATA_CACHE_SIZE; 987f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = start; i < end; ++i) { 988f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mData[dataIndex] = info.items.get(i - info.contentStart); 989f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (++dataIndex == DATA_CACHE_SIZE) dataIndex = 0; 990f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 991f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 9926b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang 9936b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang // update mItemPath 9946b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang MediaItem current = mData[mCurrentIndex % DATA_CACHE_SIZE]; 9956b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang mItemPath = current == null ? null : current.getPath(); 9966b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang 997f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin updateImageCache(); 998f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin updateTileProvider(); 999f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin updateImageRequests(); 1000d61248536b0dc28ca9e5f84b20e63a4c96ac3ff3Bobby Georgescu 1001d61248536b0dc28ca9e5f84b20e63a4c96ac3ff3Bobby Georgescu if (mDataListener != null) { 1002d61248536b0dc28ca9e5f84b20e63a4c96ac3ff3Bobby Georgescu mDataListener.onPhotoChanged(mCurrentIndex, mItemPath); 1003d61248536b0dc28ca9e5f84b20e63a4c96ac3ff3Bobby Georgescu } 1004d61248536b0dc28ca9e5f84b20e63a4c96ac3ff3Bobby Georgescu 1005b7ec5534c7b539be2397c27cfa5e8b992974c12dChih-Chung Chang fireDataChange(); 1006f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 1007f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 1008f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 1009f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1010f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private class ReloadTask extends Thread { 1011f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private volatile boolean mActive = true; 1012f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private volatile boolean mDirty = true; 1013f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1014f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private boolean mIsLoading = false; 1015f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1016f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void updateLoading(boolean loading) { 1017f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mIsLoading == loading) return; 1018f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mIsLoading = loading; 1019f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mMainHandler.sendEmptyMessage(loading ? MSG_LOAD_START : MSG_LOAD_FINISH); 1020f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 1021f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1022f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 1023f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void run() { 1024f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin while (mActive) { 1025f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin synchronized (this) { 1026f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (!mDirty && mActive) { 1027f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin updateLoading(false); 1028f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Utils.waitWithoutInterrupt(this); 1029f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin continue; 1030f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 1031f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 1032f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mDirty = false; 1033f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin UpdateInfo info = executeAndWait(new GetUpdateInfo()); 1034676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin updateLoading(true); 1035705dc819661cb8c8e839a04577b0641bd6caad53John Reck long version = mSource.reload(); 1036676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin if (info.version != version) { 1037676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin info.reloadContent = true; 1038676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin info.size = mSource.getMediaItemCount(); 1039676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin } 1040676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin if (!info.reloadContent) continue; 1041676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin info.items = mSource.getMediaItem( 1042676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin info.contentStart, info.contentEnd); 10436b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang 1044676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin int index = MediaSet.INDEX_NOT_FOUND; 10456b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang 1046676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin // First try to focus on the given hint path if there is one. 1047676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin if (mFocusHintPath != null) { 1048676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin index = findIndexOfPathInCache(info, mFocusHintPath); 1049676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin mFocusHintPath = null; 1050676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin } 10516b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang 1052676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin // Otherwise try to see if the currently focused item can be found. 1053676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin if (index == MediaSet.INDEX_NOT_FOUND) { 1054676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin MediaItem item = findCurrentMediaItem(info); 1055676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin if (item != null && item.getPath() == info.target) { 10566b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang index = info.indexHint; 1057676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin } else { 1058676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin index = findIndexOfTarget(info); 10596b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang } 1060676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin } 10616b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang 1062676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin // The image has been deleted. Focus on the next image (keep 1063676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin // mCurrentIndex unchanged) or the previous image (decrease 1064676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin // mCurrentIndex by 1). In page mode we want to see the next 1065676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin // image, so we focus on the next one. In film mode we want the 1066676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin // later images to shift left to fill the empty space, so we 1067676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin // focus on the previous image (so it will not move). In any 1068676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin // case the index needs to be limited to [0, mSize). 1069676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin if (index == MediaSet.INDEX_NOT_FOUND) { 1070676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin index = info.indexHint; 107141b3cff60905a96ab5b6f8e5f42bcc3bab1eb605Bobby Georgescu int focusHintDirection = mFocusHintDirection; 107241b3cff60905a96ab5b6f8e5f42bcc3bab1eb605Bobby Georgescu if (index == (mCameraIndex + 1)) { 107341b3cff60905a96ab5b6f8e5f42bcc3bab1eb605Bobby Georgescu focusHintDirection = FOCUS_HINT_NEXT; 107441b3cff60905a96ab5b6f8e5f42bcc3bab1eb605Bobby Georgescu } 107541b3cff60905a96ab5b6f8e5f42bcc3bab1eb605Bobby Georgescu if (focusHintDirection == FOCUS_HINT_PREVIOUS 107641b3cff60905a96ab5b6f8e5f42bcc3bab1eb605Bobby Georgescu && index > 0) { 1077676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin index--; 1078f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 1079676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin } 10803000f70d462f27ddf992a50b57db2ef9c8dcac15Mangesh Ghiware 1081676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin // Don't change index if mSize == 0 1082676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin if (mSize > 0) { 1083676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin if (index >= mSize) index = mSize - 1; 1084f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 10856b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang 1086676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin info.indexHint = index; 1087676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin 1088f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin executeAndWait(new UpdateContent(info)); 1089f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 1090f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 1091f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1092f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public synchronized void notifyDirty() { 1093f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mDirty = true; 1094f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin notifyAll(); 1095f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 1096f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1097f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public synchronized void terminate() { 1098f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mActive = false; 1099f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin notifyAll(); 1100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 1101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private MediaItem findCurrentMediaItem(UpdateInfo info) { 1103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ArrayList<MediaItem> items = info.items; 1104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int index = info.indexHint - info.contentStart; 1105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return index < 0 || index >= items.size() ? null : items.get(index); 1106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 1107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int findIndexOfTarget(UpdateInfo info) { 1109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (info.target == null) return info.indexHint; 1110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ArrayList<MediaItem> items = info.items; 1111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // First, try to find the item in the data just loaded 1113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (items != null) { 11146b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang int i = findIndexOfPathInCache(info, info.target); 11156b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang if (i != MediaSet.INDEX_NOT_FOUND) return i; 1116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 1117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Not found, find it in mSource. 1119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mSource.getIndexOfItem(info.target, info.indexHint); 1120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 11216b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang 11226b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang private int findIndexOfPathInCache(UpdateInfo info, Path path) { 11236b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang ArrayList<MediaItem> items = info.items; 11246b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang for (int i = 0, n = items.size(); i < n; ++i) { 11250086dbabb383a9ba5e06a8b49e3e180bfa36a64bChih-Chung Chang MediaItem item = items.get(i); 11260086dbabb383a9ba5e06a8b49e3e180bfa36a64bChih-Chung Chang if (item != null && item.getPath() == path) { 11276b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang return i + info.contentStart; 11286b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang } 11296b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang } 11306b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang return MediaSet.INDEX_NOT_FOUND; 11316b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang } 1132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 1133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin} 1134