diff options
18 files changed, 529 insertions, 671 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 08ca742e0..1eda90bf7 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. +<!-- Copyright (c) 2010-2014, 2016, The Linux Foundation. All rights reserved. Not a Contribution. Copyright (C) 2007 The Android Open Source Project @@ -328,16 +328,6 @@ android:theme="@style/Theme.Gallery" android:configChanges="orientation|keyboardHidden|screenSize" /> - <activity android:name="com.android.gallery3d.util.ViewGifImage" - android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" - android:configChanges="orientation|keyboardHidden|screenSize|keyboard|navigation"> - <intent-filter> - <action android:name="com.android.gallery3d.VIEW_GIF" /> - <data android:mimeType="image/gif" /> - <category android:name="android.intent.category.DEFAULT" /> - </intent-filter> - </activity> - <provider android:name="com.android.gallery3d.provider.GalleryProvider" android:syncable="false" android:grantUriPermissions="true" diff --git a/res/layout/view_gif_image.xml b/res/layout/view_gif_image.xml deleted file mode 100644 index 976549a6b..000000000 --- a/res/layout/view_gif_image.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <LinearLayout - android:id="@+id/image_absoluteLayout" - android:layout_height="match_parent" - android:layout_width="match_parent"> - <ImageView android:id="@+id/image_display_area" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:clickable="true"> - </ImageView> - </LinearLayout> - -</RelativeLayout> diff --git a/src/com/android/gallery3d/app/MovieControllerOverlay.java b/src/com/android/gallery3d/app/MovieControllerOverlay.java index b2851e020..72b95fd38 100644 --- a/src/com/android/gallery3d/app/MovieControllerOverlay.java +++ b/src/com/android/gallery3d/app/MovieControllerOverlay.java @@ -22,6 +22,7 @@ import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.Rect; import android.graphics.drawable.VectorDrawable; +import android.media.MediaPlayer; import android.os.Handler; import android.text.TextUtils; import android.util.DisplayMetrics; @@ -442,6 +443,18 @@ public class MovieControllerOverlay extends CommonControllerOverlay implements mScreenModeManager.setScreenMode(ScreenModeManager.SCREENMODE_BIGSCREEN); } + private void updateBackgroundColor() { + switch (mState) { + case PAUSED: + case PLAYING: + case BUFFERING: + setBackgroundColor(Color.TRANSPARENT); + break; + default: + setBackgroundColor(Color.BLACK); + } + } + public IContrllerOverlayExt getOverlayExt() { return mOverlayExt; } @@ -463,31 +476,16 @@ public class MovieControllerOverlay extends CommonControllerOverlay implements private boolean mAlwaysShowBottom; @Override - public void showBuffering(boolean fullBuffer, int percent) { - if (LOG) { - Log.v(TAG, "showBuffering(" + fullBuffer + ", " + percent - + ") " + "lastState=" + mLastState + ", state=" + mState); - } - if (fullBuffer) { - // do not show text and loading - mTimeBar.setSecondaryProgress(percent); - return; - } + public void showBuffering(int what) { if (mState == State.PAUSED || mState == State.PLAYING) { mLastState = mState; } - if (percent >= 0 && percent < 100) { // valid value + if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START) { mState = State.BUFFERING; - String text = "media controller buffering"; - mTimeBar.setInfo(text); showMainView(mLoadingView); - } else if (percent == 100) { - mState = mLastState; - mTimeBar.setInfo(null); - showMainView(mPlayPauseReplayView);// restore play pause state - } else { // here to restore old state + } else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END || what == TimeBar.UNKNOWN) { mState = mLastState; - mTimeBar.setInfo(null); + showMainView(mPlayPauseReplayView); } } @@ -497,7 +495,7 @@ public class MovieControllerOverlay extends CommonControllerOverlay implements Log.v(TAG, "clearBuffering()"); } mTimeBar.setSecondaryProgress(TimeBar.UNKNOWN); - showBuffering(false, TimeBar.UNKNOWN); + showBuffering(TimeBar.UNKNOWN); } public void showReconnecting(int times) { @@ -558,11 +556,7 @@ public class MovieControllerOverlay extends CommonControllerOverlay implements mAlwaysShowBottom = alwaysShow; if (!alwaysShow) { // clear background setBackgroundDrawable(null); - if (mState == State.PAUSED || mState == State.PLAYING) { - setBackgroundColor(Color.TRANSPARENT); - }else { - setBackgroundColor(Color.BLACK); - } + updateBackgroundColor(); } else { setBackgroundResource(R.drawable.media_default_bkg); if (foreShow) { @@ -879,11 +873,7 @@ public class MovieControllerOverlay extends CommonControllerOverlay implements public void onShow() { Log.v(TAG, "ControllerRewindAndForwardExt onShow: "+mState); mContollerButtons.setVisibility(View.VISIBLE); - if (mState == State.PAUSED || mState == State.PLAYING) { - setBackgroundColor(Color.TRANSPARENT); - } else { - setBackgroundColor(Color.BLACK); - } + updateBackgroundColor(); } public void onLayout(int l, int r, int b) { diff --git a/src/com/android/gallery3d/app/MoviePlayer.java b/src/com/android/gallery3d/app/MoviePlayer.java index e1b8709b3..0ecc8bf20 100755 --- a/src/com/android/gallery3d/app/MoviePlayer.java +++ b/src/com/android/gallery3d/app/MoviePlayer.java @@ -810,6 +810,9 @@ public class MoviePlayer implements } else if (what == MediaPlayer.MEDIA_INFO_METADATA_UPDATE && mServerTimeoutExt != null) { Log.e(TAG, "setServerTimeout " + extra); mServerTimeoutExt.setTimeout(extra * 1000); + } else if ((what == MediaPlayer.MEDIA_INFO_BUFFERING_START + || what == MediaPlayer.MEDIA_INFO_BUFFERING_END) && mOverlayExt != null) { + mOverlayExt.showBuffering(what); } if (mRetryExt.onInfo(mp, what, extra)) { return true; @@ -819,8 +822,6 @@ public class MoviePlayer implements @Override public void onBufferingUpdate(MediaPlayer mp, int percent) { - boolean fullBuffer = isFullBuffer(); - mOverlayExt.showBuffering(fullBuffer, percent); } @Override diff --git a/src/com/android/gallery3d/app/PhotoDataAdapter.java b/src/com/android/gallery3d/app/PhotoDataAdapter.java index aa28b5557..d65c0d1c8 100755 --- a/src/com/android/gallery3d/app/PhotoDataAdapter.java +++ b/src/com/android/gallery3d/app/PhotoDataAdapter.java @@ -34,6 +34,7 @@ import com.android.gallery3d.data.MediaSet; import com.android.gallery3d.data.Path; import com.android.gallery3d.data.SnailItem; import com.android.gallery3d.glrenderer.TiledTexture; +import com.android.gallery3d.ui.BitmapScreenNail; import com.android.gallery3d.ui.PhotoView; import com.android.gallery3d.ui.ScreenNail; import com.android.gallery3d.ui.SynchronizedHandler; @@ -41,11 +42,14 @@ import com.android.gallery3d.ui.TileImageViewAdapter; import com.android.gallery3d.ui.TiledScreenNail; import com.android.gallery3d.util.Future; import com.android.gallery3d.util.FutureListener; +import com.android.gallery3d.util.GifDecoder; +import com.android.gallery3d.util.GifRequest; import com.android.gallery3d.util.MediaSetUtils; import com.android.gallery3d.util.ThreadPool; import com.android.gallery3d.util.ThreadPool.Job; import com.android.gallery3d.util.ThreadPool.JobContext; +import java.lang.Exception; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -71,6 +75,7 @@ public class PhotoDataAdapter implements PhotoPage.Model { private static final int BIT_SCREEN_NAIL = 1; private static final int BIT_FULL_IMAGE = 2; + private static final int BIT_GIF_ANIMATION = 3; private static final long NOTIFY_DIRTY_WAIT_TIME = 10; // sImageFetchSeq is the fetching sequence for images. @@ -91,7 +96,7 @@ public class PhotoDataAdapter implements PhotoPage.Model { static { int k = 0; - sImageFetchSeq = new ImageFetch[1 + (IMAGE_CACHE_SIZE - 1) * 2 + 3]; + sImageFetchSeq = new ImageFetch[1 + (IMAGE_CACHE_SIZE - 1) * 2 + 4]; sImageFetchSeq[k++] = new ImageFetch(0, BIT_SCREEN_NAIL); for (int i = 1; i < IMAGE_CACHE_SIZE; ++i) { @@ -102,6 +107,7 @@ public class PhotoDataAdapter implements PhotoPage.Model { sImageFetchSeq[k++] = new ImageFetch(0, BIT_FULL_IMAGE); sImageFetchSeq[k++] = new ImageFetch(1, BIT_FULL_IMAGE); sImageFetchSeq[k++] = new ImageFetch(-1, BIT_FULL_IMAGE); + sImageFetchSeq[k++] = new ImageFetch(0, BIT_GIF_ANIMATION); } private final TileImageViewAdapter mTileProvider = new TileImageViewAdapter(); @@ -160,6 +166,7 @@ public class PhotoDataAdapter implements PhotoPage.Model { private boolean mNeedFullImage; private int mFocusHintDirection = FOCUS_HINT_NEXT; private Path mFocusHintPath = null; + private AbstractGalleryActivity mActivity; // If Bundle is from widget, it's true, otherwise it's false. private boolean mIsFromWidget = false; @@ -181,6 +188,7 @@ public class PhotoDataAdapter implements PhotoPage.Model { public PhotoDataAdapter(AbstractGalleryActivity activity, PhotoView view, MediaSet mediaSet, Path itemPath, int indexHint, int cameraIndex, boolean isPanorama, boolean isStaticCamera) { + mActivity = activity; mSource = Utils.checkNotNull(mediaSet); mPhotoView = Utils.checkNotNull(view); mItemPath = Utils.checkNotNull(itemPath); @@ -470,6 +478,8 @@ public class PhotoDataAdapter implements PhotoPage.Model { ImageEntry entry = mImageCache.get(item.getPath()); if (entry == null) return null; + ScreenNail targetScreenNail = getTargetScreenNail(entry); + if (targetScreenNail != null) return targetScreenNail; // Create a default ScreenNail if the real one is not available yet, // except for camera that a black screen is better than a gray tile. if (entry.screenNail == null && !isCamera(offset)) { @@ -631,7 +641,7 @@ public class PhotoDataAdapter implements PhotoPage.Model { } private void updateTileProvider(ImageEntry entry) { - ScreenNail screenNail = entry.screenNail; + ScreenNail screenNail = getTargetScreenNail(entry); BitmapRegionDecoder fullImage = entry.fullImage; if (screenNail != null) { if (fullImage != null) { @@ -648,6 +658,15 @@ public class PhotoDataAdapter implements PhotoPage.Model { } } + + private ScreenNail getTargetScreenNail(ImageEntry entry) { + if (null == entry) return null; + if (null != entry.currentGifFrame){ + return entry.currentGifFrame; + } + return entry.screenNail; + } + private void updateSlidingWindow() { // 1. Update the image window int start = Utils.clamp(mCurrentIndex - IMAGE_CACHE_SIZE / 2, @@ -733,6 +752,12 @@ public class PhotoDataAdapter implements PhotoPage.Model { entry.fullImageTask = null; entry.requestedFullImage = MediaObject.INVALID_DATA_VERSION; } + + if (entry.gifDecoderTask != null && entry.gifDecoderTask != task) { + entry.gifDecoderTask.cancel(); + entry.gifDecoderTask = null; + entry.requestedGif = MediaObject.INVALID_DATA_VERSION; + } } } @@ -782,6 +807,23 @@ public class PhotoDataAdapter implements PhotoPage.Model { } } + + private class GifDecoderJob implements Job<GifDecoder> { + private MediaItem mItem; + + public GifDecoderJob(MediaItem item) { + mItem = item; + } + + @Override + public GifDecoder run(JobContext jc) { + if (isTemporaryItem(mItem)) { + return null; + } + return new GifRequest(mItem.getContentUri(), mActivity).run(jc); + } + } + // Returns true if we think this is a temporary item created by Camera. A // temporary item is an image or a video whose data is still being // processed, but an incomplete entry is created first in MediaProvider, so @@ -830,6 +872,9 @@ public class PhotoDataAdapter implements PhotoPage.Model { } else if (which == BIT_FULL_IMAGE && entry.fullImageTask != null && entry.requestedFullImage == version) { return entry.fullImageTask; + } else if (which == BIT_GIF_ANIMATION && entry.gifDecoderTask != null + && entry.requestedGif == version) { + return entry.gifDecoderTask; } if (which == BIT_SCREEN_NAIL && entry.requestedScreenNail != version) { @@ -850,6 +895,18 @@ public class PhotoDataAdapter implements PhotoPage.Model { // request full image return entry.fullImageTask; } + + if (which == BIT_GIF_ANIMATION + && (entry.requestedGif != version) + && isGif(0)) { + entry.requestedGif = version; + entry.gifDecoderTask = mThreadPool.submit( + new GifDecoderJob(item), + new GifDecoderListener(item.getPath())); + // request gif decoder + return entry.gifDecoderTask; + } + return null; } @@ -879,6 +936,20 @@ public class PhotoDataAdapter implements PhotoPage.Model { item.getWidth(), item.getHeight()); } } + + if (Math.abs(i - mCurrentIndex) > 0) { + if (entry.gifDecoderTask != null) { + entry.gifDecoderTask.cancel(); + entry.gifDecoderTask = null; + } + entry.gifDecoder = null; + entry.requestedGif = MediaItem.INVALID_DATA_VERSION; + if (null != entry.currentGifFrame) { + //recycle cached gif frame + entry.currentGifFrame.recycle(); + entry.currentGifFrame = null; + } + } } else { entry = new ImageEntry(); mImageCache.put(path, entry); @@ -940,6 +1011,158 @@ public class PhotoDataAdapter implements PhotoPage.Model { } } + private class GifDecoderListener + implements Runnable, FutureListener<GifDecoder> { + private final Path mPath; + private Future<GifDecoder> mFuture; + + public GifDecoderListener(Path path) { + mPath = path; + } + + @Override + public void onFutureDone(Future<GifDecoder> future) { + mFuture = future; + if (null != mFuture.get()) { + mMainHandler.sendMessage( + mMainHandler.obtainMessage(MSG_RUN_OBJECT, this)); + } + } + + @Override + public void run() { + updateGifDecoder(mPath, mFuture); + } + } + + private void updateGifDecoder(Path path, + Future<GifDecoder> future) { + + ImageEntry entry = mImageCache.get(path); + if (entry == null || entry.gifDecoderTask != future) { + return; + } + + entry.gifDecoderTask = null; + entry.gifDecoder = future.get(); + + playGif(path); + updateImageRequests(); + + } + + private void playGif(Path path) { + ImageEntry entry = mImageCache.get(path); + if (null == entry) return; + if (entry.gifDecoder != null && entry.gifDecoder.getFrameCount() != 0) { + if (entry.gifDecoder.mWidth <= 0 || entry.gifDecoder.mHeight <= 0) { + return; + } + + int currentIndex = mCurrentIndex; + if (path == getPath(currentIndex)) { + GifEntry gifEntry = new GifEntry(); + gifEntry.gifDecoder = entry.gifDecoder; + gifEntry.animatedIndex = currentIndex; + gifEntry.entry = entry; + + mMainHandler.sendMessage( + mMainHandler.obtainMessage(MSG_RUN_OBJECT, + new GifRunnable(path, gifEntry))); + } + } + } + + private class GifRunnable implements Runnable { + + private GifEntry mGifEntry; + private Path mPath; + + private void free() { + if (null != mGifEntry.gifDecoder) { + mGifEntry.gifDecoder.free(); + mGifEntry.gifDecoder = null; + } + + if (null != mGifEntry) { + mGifEntry = null; + } + } + + public GifRunnable(Path path, GifEntry gifEntry) { + mPath = path; + mGifEntry = gifEntry; + if (null == mGifEntry || null == mGifEntry.gifDecoder) { + free(); + return; + } + boolean imageChanged = mGifEntry.animatedIndex != mCurrentIndex; + MediaItem item = getMediaItem(0); + Path currentPath = (item != null ? item.getPath() : null); + imageChanged |= path != currentPath; + if (imageChanged) { + free(); + return; + } + mGifEntry.currentFrame = 0; + mGifEntry.totalFrameCount = mGifEntry.gifDecoder.getFrameCount(); + if (mGifEntry.totalFrameCount <= 1) { + free(); + return; + } + } + + @Override + public void run() { + if (!mIsActive) { + free(); + return; + } + + if (null == mGifEntry || null == mGifEntry.gifDecoder) { + free(); + return; + } + + boolean imageChanged = mGifEntry.animatedIndex != mCurrentIndex; + MediaItem item = getMediaItem(0); + Path currentPath = (item != null ? item.getPath() : null); + imageChanged |= mPath != currentPath; + if (imageChanged) { + free(); + return; + } + + Bitmap frameBitmap = mGifEntry.gifDecoder.getFrameImage(mGifEntry.currentFrame); + if (null == frameBitmap) { + free(); + return; + } + long delay = (long) mGifEntry.gifDecoder.getDelay(mGifEntry.currentFrame); + mGifEntry.currentFrame = (mGifEntry.currentFrame + 1) % mGifEntry.totalFrameCount; + + ScreenNail gifFrame = new BitmapScreenNail(frameBitmap); + if (mGifEntry.entry.currentGifFrame != null) { + mGifEntry.entry.currentGifFrame.recycle(); + mGifEntry.entry.currentGifFrame = null; + } + mGifEntry.entry.currentGifFrame = gifFrame; + updateTileProvider(mGifEntry.entry); + mPhotoView.notifyImageChange(0); + mMainHandler.sendMessageDelayed( + mMainHandler.obtainMessage(MSG_RUN_OBJECT, this), delay); + } + } + + + private static class GifEntry { + public ImageEntry entry; + public GifDecoder gifDecoder; + public int animatedIndex; + public int currentFrame; + public int totalFrameCount; + } + private static class ImageEntry { public BitmapRegionDecoder fullImage; public ScreenNail screenNail; @@ -948,6 +1171,11 @@ public class PhotoDataAdapter implements PhotoPage.Model { public long requestedScreenNail = MediaObject.INVALID_DATA_VERSION; public long requestedFullImage = MediaObject.INVALID_DATA_VERSION; public boolean failToLoad = false; + + public GifDecoder gifDecoder; + public Future<GifDecoder> gifDecoderTask; + public ScreenNail currentGifFrame; + public long requestedGif = MediaObject.INVALID_DATA_VERSION; } private class SourceListener implements ContentListener { diff --git a/src/com/android/gallery3d/app/PhotoPage.java b/src/com/android/gallery3d/app/PhotoPage.java index deb3b855c..7bda6dc16 100644 --- a/src/com/android/gallery3d/app/PhotoPage.java +++ b/src/com/android/gallery3d/app/PhotoPage.java @@ -78,7 +78,6 @@ import com.android.gallery3d.ui.SelectionManager; import com.android.gallery3d.ui.SynchronizedHandler; import com.android.gallery3d.util.GalleryUtils; import com.android.gallery3d.util.UsageStatistics; -import com.android.gallery3d.util.ViewGifImage; import java.util.ArrayList; import java.util.Locale; @@ -1275,10 +1274,6 @@ public abstract class PhotoPage extends ActivityState implements // item is not ready or it is camera preview, ignore return; } - if (item.getMimeType().equals(MediaItem.MIME_TYPE_GIF)) { - viewAnimateGif((Activity) mActivity, item.getContentUri()); - return; - } int supported = item.getSupportedOperations(); boolean playVideo = ((supported & MediaItem.SUPPORT_PLAY) != 0); @@ -1738,12 +1733,4 @@ public abstract class PhotoPage extends ActivityState implements } } - private static void viewAnimateGif(Activity activity, Uri uri) { - Intent intent = new Intent(ViewGifImage.VIEW_GIF_ACTION, uri); - String scheme = uri.getScheme(); - if ("file".equals(scheme)) { - intent.setDataAndType(uri, "image/gif"); - } - activity.startActivity(intent); - } } diff --git a/src/com/android/gallery3d/app/TimeLineDataLoader.java b/src/com/android/gallery3d/app/TimeLineDataLoader.java index 7816c2943..bd2193ff9 100755..100644 --- a/src/com/android/gallery3d/app/TimeLineDataLoader.java +++ b/src/com/android/gallery3d/app/TimeLineDataLoader.java @@ -39,7 +39,6 @@ public class TimeLineDataLoader { @SuppressWarnings("unused") private static final String TAG = "TimeLineDataLoader"; private static final int DATA_CACHE_SIZE = 1000; - private boolean mNewVersion = false; private static final int MSG_LOAD_START = 1; private static final int MSG_LOAD_FINISH = 2; @@ -54,18 +53,15 @@ public class TimeLineDataLoader { public static interface DataListener { public void onContentChanged(int index); - public void onSizeChanged(int size); - public void onVersionChanged(); + public void onSizeChanged(); } - private int mActiveStart = 0; private int mActiveEnd = 0; private int mContentStart = 0; private int mContentEnd = 0; - private ArrayList<MediaItem> mTotalMediaItems; private final MediaSet mSource; private long mSourceVersion = MediaObject.INVALID_DATA_VERSION; @@ -122,9 +118,8 @@ public class TimeLineDataLoader { mSource.removeContentListener(mSourceListener); } - public MediaSet getMediaSet(int index) { - MediaSet mediaSet = ((ClusterAlbumSet)mSource).getAlbumFromindex(index); + MediaSet mediaSet = ((ClusterAlbumSet)mSource).getAlbumFromindex(index); return mediaSet; } @@ -139,10 +134,6 @@ public class TimeLineDataLoader { return ((ClusterAlbumSet) mSource).getSubMediaSetCount(); } - public ArrayList<MediaItem> getAllMediaItems() { - return mTotalMediaItems; - } - public int getActiveStart() { return mActiveStart; } @@ -155,6 +146,16 @@ public class TimeLineDataLoader { return mSize; } + public int[] getSubMediaSetCount() { + ClusterAlbumSet set = (ClusterAlbumSet) mSource; + int albumCount = set.getSubMediaSetCount(); + int[] counts = new int[albumCount]; + for (int i = albumCount - 1; i >= 0; --i) { + counts[i] = set.getSubMediaSet(i).getSelectableItemCount(); + } + return counts; + } + // Returns the index of the MediaItem with the given path or // -1 if the path is not cached public int findItem(Path id) { @@ -298,13 +299,10 @@ public class TimeLineDataLoader { @Override public Void call() throws Exception { UpdateInfo info = mUpdateInfo; - if ( info.version != mSourceVersion) { - mNewVersion = true; - } mSourceVersion = info.version; if (mSize != info.size) { mSize = info.size; - if (mDataListener != null) mDataListener.onSizeChanged(mSize); + if (mDataListener != null) mDataListener.onSizeChanged(); if (mContentEnd > mSize) mContentEnd = mSize; if (mActiveEnd > mSize) mActiveEnd = mSize; } @@ -370,12 +368,13 @@ public class TimeLineDataLoader { @Override public void run() { - Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); boolean updateComplete = false; + long version = MediaObject.INVALID_DATA_VERSION; while (mActive) { synchronized (this) { - if (mActive && !mDirty && updateComplete) { + if (mActive && !mDirty && updateComplete + && version != MediaObject.INVALID_DATA_VERSION) { updateLoading(false); if (mFailedVersion != MediaObject.INVALID_DATA_VERSION) { } @@ -387,7 +386,7 @@ public class TimeLineDataLoader { mDirty = false; } updateLoading(true); - long version = mSource.reload(); + version = mSource.reload(); UpdateInfo info = executeAndWait(new GetUpdateInfo(version)); updateComplete = info == null; if (updateComplete) { @@ -402,11 +401,6 @@ public class TimeLineDataLoader { } executeAndWait(new UpdateContent(info)); - if (mNewVersion) { - mNewVersion = false; - mTotalMediaItems = mSource.getMediaItem(0, mSource.getMediaItemCount()); - mDataListener.onVersionChanged(); - } } updateLoading(false); } diff --git a/src/com/android/gallery3d/app/TimeLinePage.java b/src/com/android/gallery3d/app/TimeLinePage.java index 618f219f4..618f219f4 100755..100644 --- a/src/com/android/gallery3d/app/TimeLinePage.java +++ b/src/com/android/gallery3d/app/TimeLinePage.java diff --git a/src/com/android/gallery3d/data/ClusterAlbumSet.java b/src/com/android/gallery3d/data/ClusterAlbumSet.java index 4046a1595..33074bea2 100644 --- a/src/com/android/gallery3d/data/ClusterAlbumSet.java +++ b/src/com/android/gallery3d/data/ClusterAlbumSet.java @@ -32,6 +32,7 @@ public class ClusterAlbumSet extends MediaSet implements ContentListener { private static final String TAG = "ClusterAlbumSet"; private GalleryApp mApplication; private MediaSet mBaseSet; + private long mBaseDataVersion; private int mKind; private ArrayList<ClusterAlbum> mAlbums = new ArrayList<ClusterAlbum>(); private boolean mFirstReloadDone; @@ -47,6 +48,7 @@ public class ClusterAlbumSet extends MediaSet implements ContentListener { super(path, INVALID_DATA_VERSION); mApplication = application; mBaseSet = baseSet; + mBaseDataVersion = mBaseSet.getDataVersion(); mKind = kind; baseSet.addContentListener(this); } @@ -68,15 +70,12 @@ public class ClusterAlbumSet extends MediaSet implements ContentListener { @Override public long reload() { - synchronized(this){ - if (mBaseSet.reload() > mDataVersion) { - if (mFirstReloadDone) { - updateClustersContents(); - } else { - updateClusters(); - mFirstReloadDone = true; - } + synchronized (this) { + if (mBaseSet.reload() > mBaseDataVersion) { + updateClusters(); + mFirstReloadDone = true; mDataVersion = nextVersionNumber(); + mBaseDataVersion = mDataVersion; } if (mKind == ClusterSource.CLUSTER_ALBUMSET_TIME) { calculateTotalItemsCount(); @@ -112,7 +111,6 @@ public class ClusterAlbumSet extends MediaSet implements ContentListener { clustering = new SizeClustering(context); break; } - clustering.run(mBaseSet); int n = clustering.getNumberOfClusters(); DataManager dataManager = mApplication.getDataManager(); diff --git a/src/com/android/gallery3d/ui/PhotoView.java b/src/com/android/gallery3d/ui/PhotoView.java index 6e1c662c4..228229006 100644 --- a/src/com/android/gallery3d/ui/PhotoView.java +++ b/src/com/android/gallery3d/ui/PhotoView.java @@ -736,7 +736,7 @@ public class PhotoView extends GLView { canvas.translate((int) (cx + 0.5f), (int) (cy + 0.5f)); int s = (int) (scale * Math.min(r.width(), r.height()) + 0.5f); //Full pic locates at index 0 of the array in PhotoDataAdapter - if (mModel.isVideo(0) || mModel.isGif(0)) { + if (mModel.isVideo(0)) { drawVideoPlayIcon(canvas, s); } if (mLoadingState == Model.LOADING_FAIL ) { @@ -866,7 +866,7 @@ public class PhotoView extends GLView { invalidate(); } int s = Math.min(drawW, drawH); - if (mModel.isVideo(mIndex) || mModel.isGif(mIndex)) { + if (mModel.isVideo(mIndex)) { drawVideoPlayIcon(canvas, s); } diff --git a/src/com/android/gallery3d/ui/TimeLineSlidingWindow.java b/src/com/android/gallery3d/ui/TimeLineSlidingWindow.java index 6fdd34935..5041ba683 100644 --- a/src/com/android/gallery3d/ui/TimeLineSlidingWindow.java +++ b/src/com/android/gallery3d/ui/TimeLineSlidingWindow.java @@ -42,9 +42,8 @@ public class TimeLineSlidingWindow implements TimeLineDataLoader.DataListener { private static final int JOB_LIMIT = 2; public static interface Listener { - public void onSizeChanged(int size); + public void onSizeChanged(int[] size); public void onContentChanged(); - public void onVersionChanged(); public int getTitleWidth(); } @@ -185,10 +184,6 @@ public class TimeLineSlidingWindow implements TimeLineDataLoader.DataListener { } } - public ArrayList<MediaItem> getAllMediaItems() { - return mSource.getAllMediaItems(); - } - private void updateTextureUploadQueue() { if (!mIsActive) return; mTileUploader.clear(); @@ -355,10 +350,11 @@ public class TimeLineSlidingWindow implements TimeLineDataLoader.DataListener { } @Override - public void onSizeChanged(int size) { + public void onSizeChanged() { + int size = mSource.size(); if (mSize != size) { mSize = size; - if (mListener != null) mListener.onSizeChanged(mSize); + if (mListener != null) mListener.onSizeChanged(mSource.getSubMediaSetCount()); if (mContentEnd > mSize) mContentEnd = mSize; if (mActiveEnd > mSize) mActiveEnd = mSize; } @@ -377,11 +373,6 @@ public class TimeLineSlidingWindow implements TimeLineDataLoader.DataListener { } } - @Override - public void onVersionChanged() { - mListener.onVersionChanged(); - } - public void resume() { mIsActive = true; TiledTexture.prepareResources(); diff --git a/src/com/android/gallery3d/ui/TimeLineSlotRenderer.java b/src/com/android/gallery3d/ui/TimeLineSlotRenderer.java index adad59c01..b0a8a0cba 100644 --- a/src/com/android/gallery3d/ui/TimeLineSlotRenderer.java +++ b/src/com/android/gallery3d/ui/TimeLineSlotRenderer.java @@ -99,10 +99,6 @@ public class TimeLineSlotRenderer extends AbstractSlotRenderer { : texture; } - public ArrayList<MediaItem> getAllMediaItems() { - return mDataWindow.getAllMediaItems(); - } - protected int renderOverlay(GLCanvas canvas, int index, TimeLineSlidingWindow.AlbumEntry entry, int width, int height) { int renderRequestFlags = 0; @@ -133,17 +129,12 @@ public class TimeLineSlotRenderer extends AbstractSlotRenderer { } @Override - public void onSizeChanged(int size) { + public void onSizeChanged(int[] size) { mSlotView.setSlotCount(size); mSlotView.invalidate(); } @Override - public void onVersionChanged() { - mSlotView.onVersionChanged(); - } - - @Override public int getTitleWidth() { return mSlotView.getTitleWidth(); } @@ -184,14 +175,12 @@ public class TimeLineSlotRenderer extends AbstractSlotRenderer { public void setModel(TimeLineDataLoader model) { if (mDataWindow != null) { mDataWindow.setListener(null); - mSlotView.setSlotCount(0); mDataWindow = null; } if (model != null) { mDataWindow = new TimeLineSlidingWindow(mActivity, model, CACHE_SIZE, mLabelSpec, mSelectionManager, mSlotView); mDataWindow.setListener(new MyDataModelListener()); - mSlotView.setSlotCount(model.size()); } } diff --git a/src/com/android/gallery3d/ui/TimeLineSlotView.java b/src/com/android/gallery3d/ui/TimeLineSlotView.java index dadd5ff25..5c93d31bd 100644 --- a/src/com/android/gallery3d/ui/TimeLineSlotView.java +++ b/src/com/android/gallery3d/ui/TimeLineSlotView.java @@ -85,9 +85,6 @@ public class TimeLineSlotView extends GLView { public static final int OVERSCROLL_3D = 0; - // to prevent allocating memory - private final Rect mTempRect = new Rect(); - // Flag to check whether it is come from Photo Page. private boolean isFromPhotoPage = false; @@ -105,18 +102,19 @@ public class TimeLineSlotView extends GLView { } public void setCenterIndex(int index) { - int slotCount = mLayout.mSlotCount; - if (index < 0 || index >= slotCount) { + int size = mLayout.getSlotSize(); + if (index < 0 || index >= size) { return; } - Rect rect = mLayout.getSlotRect(index, mTempRect); + Rect rect = mLayout.getSlotRect(index); int position = (rect.top + rect.bottom - getHeight()) / 2; setScrollPosition(position); } public void makeSlotVisible(int index) { - Rect rect = mLayout.getSlotRect(index, mTempRect); + Rect rect = mLayout.getSlotRect(index); + if (rect == null) return; int visibleBegin = mScrollY; int visibleLength = getHeight(); int visibleEnd = visibleBegin + visibleLength; @@ -146,13 +144,6 @@ public class TimeLineSlotView extends GLView { public void setScrollPosition(int position) { - /*if (View.LAYOUT_DIRECTION_RTL == TextUtils - .getLayoutDirectionFromLocale(Locale.getDefault()) - && position == 0 && !isFromPhotoPage) { - // If RTL and not from Photo Page, set position to max. - position = mLayout.getScrollLimit(); - }*/ - position = Utils.clamp(position, 0, mLayout.getScrollLimit()); mScroller.setPosition(position); updateScrollPosition(position, false); @@ -167,7 +158,7 @@ public class TimeLineSlotView extends GLView { if (!changeSize) return; mWidth = r - l; - // Make sure we are still at a resonable scroll position after the size + // Make sure we are still at a reasonable scroll position after the size // is changed (like orientation change). We choose to keep the center // visible slot still visible. This is arbitrary but reasonable. int visibleIndex = @@ -181,13 +172,13 @@ public class TimeLineSlotView extends GLView { public void startScatteringAnimation(RelativePosition position) { mAnimation = new ScatteringAnimation(position); mAnimation.start(); - if (mLayout.mSlotCount != 0) invalidate(); + if (mLayout.getSlotSize() != 0) invalidate(); } public void startRisingAnimation() { mAnimation = new RisingAnimation(); mAnimation.start(); - if (mLayout.mSlotCount != 0) invalidate(); + if (mLayout.getSlotSize() != 0) invalidate(); } private void updateScrollPosition(int position, boolean force) { @@ -203,7 +194,7 @@ public class TimeLineSlotView extends GLView { } public Rect getSlotRect(int slotIndex) { - return mLayout.getSlotRect(slotIndex, new Rect()); + return mLayout.getSlotRect(slotIndex); } @Override @@ -297,7 +288,7 @@ public class TimeLineSlotView extends GLView { private int renderItem( GLCanvas canvas, int index, int pass, boolean paperActive) { - Rect rect = mLayout.getSlotRect(index, mTempRect); + Rect rect = mLayout.getSlotRect(index); if (rect == null) return 0; canvas.save(GLCanvas.SAVE_FLAG_ALPHA | GLCanvas.SAVE_FLAG_MATRIX); canvas.translate(rect.left, rect.top, 0); @@ -364,10 +355,10 @@ public class TimeLineSlotView extends GLView { root.lockRenderThread(); try { if (isDown) return; - int index = mLayout.getSlotIndexByPosition(e.getX(), e.getY()); - if (index != INDEX_NONE) { + Slot slot = mLayout.getSlotByPosition(e.getX(), e.getY()); + if (slot != null) { isDown = true; - mListener.onDown(index); + mListener.onDown(slot.index); } } finally { root.unlockRenderThread(); @@ -413,19 +404,11 @@ public class TimeLineSlotView extends GLView { public boolean onSingleTapUp(MotionEvent e) { cancelDown(false); if (mDownInScrolling) return true; - RectSlot slot = mLayout.getRectSlotByPosition(e.getX(), e.getY()); - if (slot == null) { - return true; - } - int index = slot.slotIndex; - if (index != INDEX_NONE) { - if (slot.mediaType == MediaObject.MEDIA_TYPE_TIMELINE_TITLE) { - mListener.onSingleTapUp(index, true); - return true; - } - mListener.onSingleTapUp(index, false); - } - return true; + Slot slot = mLayout.getSlotByPosition(e.getX(), e.getY()); + if (slot != null) { + mListener.onSingleTapUp(slot.index, slot.isTitle); + } + return true; } @Override @@ -434,17 +417,9 @@ public class TimeLineSlotView extends GLView { if (mDownInScrolling) return; lockRendering(); try { - RectSlot slot = mLayout.getRectSlotByPosition(e.getX(), e.getY()); - if (slot == null) return; - - int index = slot.slotIndex; - if (index != INDEX_NONE) { - if (slot.mediaType == MediaObject.MEDIA_TYPE_TIMELINE_TITLE) { - mListener.onLongTap(index, true); - - } else { - mListener.onLongTap(index, false); - } + Slot slot = mLayout.getSlotByPosition(e.getX(), e.getY()); + if (slot != null) { + mListener.onLongTap(slot.index, slot.isTitle); } } finally { unlockRendering(); @@ -456,9 +431,8 @@ public class TimeLineSlotView extends GLView { mStartIndex = index; } - // Return true if the layout parameters have been changed - public boolean setSlotCount(int slotCount) { - boolean changed = mLayout.setSlotCount(slotCount); + public void setSlotCount(int[] count) { + mLayout.setSlotCount(count); // mStartIndex is applied the first time setSlotCount is called. if (mStartIndex != INDEX_NONE) { @@ -467,12 +441,6 @@ public class TimeLineSlotView extends GLView { } // Reset the scroll position to avoid scrolling over the updated limit. setScrollPosition(mScrollY); - return changed; - } - - public void onVersionChanged() { - mLayout.createSlots(); - invalidate(); } public int getVisibleStart() { @@ -522,14 +490,14 @@ public class TimeLineSlotView extends GLView { } public class Layout { - private int mVisibleStart; private int mVisibleEnd; - public int mSlotCount; + public int mSlotSize; private int mSlotWidth; private int mSlotHeight; private int mSlotGap; + private int[] mSlotCount; private Spec mSpec; @@ -540,30 +508,41 @@ public class TimeLineSlotView extends GLView { private int mContentLength; private int mScrollPosition; - private ArrayList<Integer> mHeightList; - private HashMap<Integer, RectSlot> mMediaSlotMap; - public void setSlotSpec(TimeLineSlotView.Spec spec) { mSpec = spec; } - public boolean setSlotCount(int slotCount) { - if (slotCount == mSlotCount) return false; - mSlotCount = slotCount; - initLayoutParameters(); - updateVisibleSlotRange(); - return true; + public void setSlotCount(int[] count) { + mSlotCount = count; + if (mHeight != 0) { + initLayoutParameters(); + createSlots(); + } } - public Rect getSlotRect(int index, Rect rect) { + public int getSlotSize() { + return mSlotSize; + } + + public Rect getSlotRect(int index) { if (index >= mVisibleStart && index < mVisibleEnd && mVisibleEnd != 0) { - RectSlot slot = getRectSlot(index); - if (slot == null) { - return null; + int height = 0, base = 0, top = 0; + for (int count : mSlotCount) { + if (index == base) { + return getSlotRect(getSlot(true, index, index, top)); + } + top += mSpec.titleHeight; + ++base; + + if (index >= base && index < base + count) { + return getSlotRect(getSlot(false, index, base, top)); + } + int rows = (count + mUnitCount - 1) / mUnitCount; + top += mSlotHeight * rows + mSlotGap * (rows > 0 ? rows - 1 : 0); + base += count; } - return getSlotRect(slot, rect); } - return rect; + return null; } private void initLayoutParameters() { @@ -577,11 +556,12 @@ public class TimeLineSlotView extends GLView { } private void setSize(int width, int height) { - mWidth = width; - mHeight = height; - initLayoutParameters(); - createSlots(); - updateVisibleSlotRange(); + if (width != mWidth || height != mHeight) { + mWidth = width; + mHeight = height; + initLayoutParameters(); + createSlots(); + } } public void setScrollPosition(int position) { @@ -590,57 +570,30 @@ public class TimeLineSlotView extends GLView { updateVisibleSlotRange(); } - private Rect getSlotRect(RectSlot slot, Rect rect) { - if (rect == null) { - Log.e(TAG, "LAYOUT: null rect passed"); - Utils.assertTrue(false); - } - int x = 0; - int y = 0; - int w = mSlotWidth; - int h = 0; - if (slot.mediaType == MediaObject.MEDIA_TYPE_TIMELINE_TITLE) { - x = 0; - y = slot.totalHeight - (mSpec.titleHeight); - w = mWidth; - h = mSpec.titleHeight; + private Rect getSlotRect(Slot slot) { + int x, y, w, h; + if (slot.isTitle) { + x = 0; + y = slot.top; + w = mWidth; + h = mSpec.titleHeight; } else { - x = slot.slotCol * (mSlotWidth + mSlotGap); - y = slot.totalHeight -(mSlotHeight); - w = mSlotWidth; - h = mSlotHeight; + x = slot.col * (mSlotWidth + mSlotGap); + y = slot.top; + w = mSlotWidth; + h = mSlotHeight; } - rect.set(x, y, x + w, y + h); - return rect; + return new Rect(x, y, x + w, y + h); } private synchronized void updateVisibleSlotRange() { int position = mScrollPosition; - if(mHeightList!= null && mHeightList.size()>0 ) { - int indexStart = Arrays.binarySearch(mHeightList.toArray(new Integer[0]), position); - int indexEnd = Arrays.binarySearch(mHeightList.toArray(new Integer[0]), position+mHeight); - if(indexStart<0) { - indexStart = (indexStart * (- 1)) - 1; - } if (indexEnd<0) { - indexEnd = (indexEnd * (- 1)) - 1; + if (mSlotCount != null) { + Slot begin = getSlotByPosition(0, mScrollPosition, true, false), + end = getSlotByPosition(0, mScrollPosition + mHeight, true, true); + if (begin != null && end != null) { + setVisibleRange(begin.index, end.index); } - - if (indexStart > mHeightList.size() - 1) { - indexStart = mHeightList.size() - 1; - } - int startSlotIndex = mHeightList.indexOf(mHeightList.get(indexStart)); - if(indexEnd> mHeightList.size()-1) { - indexEnd = mHeightList.size()-1; - } - int endSlotIndex = mHeightList.lastIndexOf(mHeightList.get(indexEnd)); - - - int endSlotIndexStr = mHeightList.indexOf(mHeightList.get(indexEnd)); - if(((endSlotIndex-endSlotIndexStr) % mUnitCount) == (mUnitCount-1) && (startSlotIndex>mUnitCount)) { - startSlotIndex= startSlotIndex-mUnitCount; - } - - setVisibleRange(startSlotIndex, Math.min(mSlotCount, endSlotIndex + 1)); } } @@ -665,133 +618,101 @@ public class TimeLineSlotView extends GLView { return mVisibleEnd; } - public int getSlotIndexByPosition(float x, float y) { - RectSlot slot = getRectSlotByPosition(x, y); - if (slot == null) return INDEX_NONE; - - return slot.slotIndex; - + private Slot getSlot(boolean isTitle, int index, int indexBase, int top) { + if (isTitle) { + return new Slot(true, index, 0, top); + } else { + int row = (index - indexBase) / mUnitCount; + return new Slot(false, index, (index - indexBase) % mUnitCount, + top + row * (mSlotHeight + mSlotGap)); + } } - public RectSlot getRectSlotByPosition(float x, float y) { - int absoluteX = Math.round(x); - int absoluteY = Math.round(y) + mScrollPosition; - - if (absoluteX < 0 || absoluteY < 0) { + public Slot getSlotByPosition(float x, float y, boolean rowStart, boolean roundUp) { + if (x < 0 || y < 0 || mSlotCount == null) { return null; } - if (absoluteY > mContentLength) - return null; - - int columnIdx = absoluteX / (mSlotWidth + mSlotGap); - - RectSlot rectSlot; - - if (mHeightList != null && mHeightList.size() > 0) { - int index = Arrays.binarySearch(mHeightList.toArray(new Integer[0]), absoluteY); - if (index < 0) { - index = (index * -1) - 1; - } - if (index >= mHeightList.size()) { - index = mHeightList.size() - 1; - } - int startIndex = mHeightList.indexOf(mHeightList.get(index)); - int maxIndex = mHeightList.lastIndexOf(mHeightList.get(index)); - if (mMediaSlotMap.get(startIndex).mediaType == - MediaObject.MEDIA_TYPE_TIMELINE_TITLE) { - return mMediaSlotMap.get(startIndex); + int pos = (int) y, index = 0, top = 0; + for (int count : mSlotCount) { + int h = mSpec.titleHeight; + if (pos < top + h) { + if (roundUp) { + return getSlot(false, index + 1, index, top + h); + } else { + return getSlot(true, index, index, top); + } } - for (int i = startIndex; (i < startIndex + mUnitCount) && (i <= maxIndex); i++) { - rectSlot = mMediaSlotMap.get(i); - if (rectSlot.slotCol == columnIdx) { - return rectSlot; + top += h; + ++index; + + int rows = (count + mUnitCount - 1) / mUnitCount; + h = mSlotHeight * rows + mSlotGap * (rows > 0 ? rows - 1 : 0); + if (pos < top + h) { + int row = ((int) pos - top) / (mSlotHeight + mSlotGap); + int col = 0; + if (roundUp) { + int idx = (row + 1) * mUnitCount; + if (idx > count) + idx = count + 1; + return getSlot(false, index + idx, index, top + mSlotHeight); + } + if (!rowStart) { + col = ((int) x) / (mSlotWidth + mSlotGap); + if (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) + == View.LAYOUT_DIRECTION_RTL) { + col = mUnitCount - col; + } + if (row * mUnitCount + col >= count) { + break; + } } + return getSlot(false, index + row * mUnitCount + col, index, top); } + top += h; + index += count; + } + if (roundUp) { + return getSlot(false, index, index, top); } return null; } - public int getScrollLimit() { - if (mHeightList != null && mHeightList.size() > 0) { - return Math.max(0, mContentLength -mHeight); - } - return 0; + public Slot getSlotByPosition(float x, float y) { + return getSlotByPosition(x, mScrollPosition + y, false, false); } - + public int getScrollLimit() { + return Math.max(0, mContentLength - mHeight); + } public void createSlots() { - ArrayList<MediaItem> mediaItemlist = new ArrayList<MediaItem>(); - if (mRenderer != null) { - mediaItemlist = mRenderer.getAllMediaItems(); - } - if (mHeightList == null) { - mHeightList = new ArrayList<Integer>(); - } - if (mMediaSlotMap == null) { - mMediaSlotMap = new HashMap<Integer, RectSlot>(); - } - mHeightList.clear(); - mMediaSlotMap.clear(); - if (mediaItemlist != null && mediaItemlist.size() > 0) { - boolean isPrevTitle = false; - int j = 0; - int col = 0; - int totalHeight = 0; - for (int i = 0; i < mediaItemlist.size(); ++i) { - MediaItem info = mediaItemlist.get(i); - - if (info.getMediaType() == MediaObject.MEDIA_TYPE_TIMELINE_TITLE) { - totalHeight += (mSpec.titleHeight + mSlotGap); - isPrevTitle = true; - col = 0; - } else { - if (isPrevTitle) { - j = 0; - isPrevTitle = false; - } else { - ++j; - } - if (j % mUnitCount == 0) { - totalHeight += (mSlotHeight + mSlotGap); - col = 0; - } else { - col = j % mUnitCount; - } - - } - mHeightList.add(totalHeight); - if (View.LAYOUT_DIRECTION_RTL == TextUtils - .getLayoutDirectionFromLocale(Locale.getDefault())) { - col = mUnitCount - col - 1; - } - RectSlot rectslot = new RectSlot(info.getMediaType(), i, col, totalHeight); - mMediaSlotMap.put(rectslot.slotIndex, rectslot); + int height = 0; + int size = 0; + if (mSlotCount != null) { + for (int count : mSlotCount) { + int rows = (count + mUnitCount - 1) / mUnitCount; + height += mSlotHeight * rows + mSlotGap * (rows > 0 ? rows - 1 : 0); + size += 1 + count; } - mContentLength = mHeightList.get(mHeightList.size() -1); - mSlotCount = mediaItemlist.size(); + height += mSpec.titleHeight * mSlotCount.length; + mContentLength = height; + mSlotSize = size; + updateVisibleSlotRange(); } - updateVisibleSlotRange(); - } - - public RectSlot getRectSlot(int slotIndex) { - return mMediaSlotMap.get(slotIndex); } } + private static class Slot { + public boolean isTitle; + public int index; + public int col; + public int top; - - public static class RectSlot { - public int mediaType; - public int slotIndex; - public int slotCol; - public int totalHeight; - - public RectSlot(int type, int index, int col, int height) { - mediaType = type; - slotIndex = index; - slotCol = col; - totalHeight = height; + public Slot(boolean isTitle, int index, int col, int top) { + this.isTitle = isTitle; + this.index = index; + this.col = col; + this.top = top; } } } diff --git a/src/com/android/gallery3d/util/GIFView.java b/src/com/android/gallery3d/util/GIFView.java deleted file mode 100644 index 6c6c49b95..000000000 --- a/src/com/android/gallery3d/util/GIFView.java +++ /dev/null @@ -1,234 +0,0 @@ -package com.android.gallery3d.util; - -import com.android.gallery3d.R; - -import android.content.Context; -import android.content.ContentResolver; -import android.content.res.AssetManager; -import android.database.Cursor; -//import android.drm.DrmHelper; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.net.Uri; -import android.os.Handler; -import android.os.Message; -import android.util.Log; -import android.widget.ImageView; -import android.widget.Toast; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.io.IOException; - -public class GIFView extends ImageView implements GifAction { - - private static final String TAG = "GIFView"; - private static final float SCALE_LIMIT = 4; - private static final long FRAME_DELAY = 200; //milliseconds - - private GifDecoder mGifDecoder = null; - private Bitmap mCurrentImage = null; - private DrawThread mDrawThread = null; - - private Uri mUri; - private Context mContext; - - public GIFView(Context context) { - super(context); - mContext = context; - } - - public boolean setDrawable(Uri uri) { - if (null == uri) { - return false; - } - mUri = uri; - - // Let decode the GIF image from byte stream instead of file stream -// String filepath = DrmHelper.getFilePath(mContext, mUri); -// if (DrmHelper.isDrmFile(filepath)) { -// byte[] bytes = DrmHelper.getDrmImageBytes(filepath); -// DrmHelper.manageDrmLicense(mContext, this.getHandler(), filepath, -// "image/gif"); -// if (bytes == null) { -// return false; -// } -// startDecode(bytes); -// return true; -// } - - InputStream is = getInputStream(uri); - if (is == null || (getFileSize (is) == 0)) { - return false; - } - startDecode(is); - return true; - } - - private int getFileSize (InputStream is) { - if(is == null) return 0; - - int size = 0; - try { - if (is instanceof FileInputStream) { - FileInputStream f = (FileInputStream) is; - size = (int) f.getChannel().size(); - } else { - while (-1 != is.read()) { - size++; - } - } - - } catch (IOException e) { - Log.e(TAG, "catch exception:" + e); - } - - return size; - - } - - private InputStream getInputStream (Uri uri) { - ContentResolver cr = mContext.getContentResolver(); - InputStream input = null; - try { - input = cr.openInputStream(uri); - } catch (IOException e) { - Log.e(TAG, "catch exception:" + e); - } - return input; - } - - private void startDecode(InputStream is) { - freeGifDecoder(); - mGifDecoder = new GifDecoder(is, this); - mGifDecoder.start(); - } - - private void startDecode(byte[] bytes) { - freeGifDecoder(); - mGifDecoder = new GifDecoder(bytes, this); - mGifDecoder.start(); - } - - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - if (mGifDecoder == null) { - return; - } - - if (mCurrentImage == null) { - mCurrentImage = mGifDecoder.getImage(); - } - if (mCurrentImage == null) { - // if this gif can not be displayed, just try to show it as jpg by parsing mUri - setImageURI(mUri); - return; - } - setImageURI(null); - int saveCount = canvas.getSaveCount(); - canvas.save(); - canvas.translate(getPaddingLeft(), getPaddingTop()); - Rect sRect = null; - Rect dRect = null; - - int imageHeight = mCurrentImage.getHeight(); - int imageWidth = mCurrentImage.getWidth(); - - int displayHeight = ViewGifImage.mDM.heightPixels; - int displayWidth = ViewGifImage.mDM.widthPixels; - - int width, height; - if (imageWidth >= displayWidth || imageHeight >= displayHeight) { - // scale-down the image - if (imageWidth * displayHeight > displayWidth * imageHeight) { - width = displayWidth; - height = (imageHeight * width) / imageWidth; - } else { - height = displayHeight; - width = (imageWidth * height) / imageHeight; - } - } else { - // scale-up the image - float scale = Math.min(SCALE_LIMIT, Math.min(displayWidth / (float) imageWidth, - displayHeight / (float) imageHeight)); - width = (int) (imageWidth * scale); - height = (int) (imageHeight * scale); - } - dRect = new Rect((displayWidth - width) / 2, (displayHeight - height) / 2, - (displayWidth + width) / 2, (displayHeight + height) / 2); - canvas.drawBitmap(mCurrentImage, sRect, dRect, null); - canvas.restoreToCount(saveCount); - } - - public void parseOk(boolean parseStatus, int frameIndex) { - if (parseStatus) { - //indicates the start of a new GIF - if (mGifDecoder != null && frameIndex == -1 - && mGifDecoder.getFrameCount() > 1) { - if (mDrawThread != null) { - mDrawThread = null; - } - mDrawThread = new DrawThread(); - mDrawThread.start(); - } - } else { - Log.e(TAG, "parse error"); - } - } - - private Handler mRedrawHandler = new Handler() { - public void handleMessage(Message msg) { - invalidate(); - } - }; - - private class DrawThread extends Thread { - public void run() { - if (mGifDecoder == null) { - return; - } - - while (true) { - if (!isShown() || mRedrawHandler == null) { - break; - } - if (mGifDecoder == null) { - return; - } - GifFrame frame = mGifDecoder.next(); - mCurrentImage = frame.mImage; - - Message msg = mRedrawHandler.obtainMessage(); - mRedrawHandler.sendMessage(msg); - try { - Thread.sleep(getDelay(frame)); - } catch (InterruptedException e) { - Log.e(TAG, "catch exception:" + e); - } - } - } - - } - - private long getDelay (GifFrame frame) { - //in milliseconds - return frame.mDelayInMs == 0 ? FRAME_DELAY : frame.mDelayInMs; - } - - private void freeGifDecoder () { - if (mGifDecoder != null) { - mGifDecoder.free(); - mGifDecoder = null; - } - - } - - public void freeMemory() { - if (mDrawThread != null) { - mDrawThread = null; - } - freeGifDecoder(); - } -} diff --git a/src/com/android/gallery3d/util/GifDecoder.java b/src/com/android/gallery3d/util/GifDecoder.java index 4235fc5a5..1342355e6 100755 --- a/src/com/android/gallery3d/util/GifDecoder.java +++ b/src/com/android/gallery3d/util/GifDecoder.java @@ -7,7 +7,7 @@ import android.util.Log; import java.io.ByteArrayInputStream; import java.io.InputStream; -public class GifDecoder extends Thread { +public class GifDecoder { public static final int STATUS_PARSING = 0; public static final int STATUS_FORMAT_ERROR = 1; @@ -71,14 +71,16 @@ public class GifDecoder extends Thread { public GifDecoder(byte[] data, GifAction act) { mGifData = data; mGifAction = act; + startDecoder(); } public GifDecoder(InputStream is, GifAction act) { mIS = is; mGifAction = act; + startDecoder(); } - public void run() { + public void startDecoder() { if (mIS != null) { readStream(); } else if (mGifData != null) { @@ -295,10 +297,14 @@ public class GifDecoder extends Thread { readContents(); if (mFrameCount < 0) { mStatus = STATUS_FORMAT_ERROR; - mGifAction.parseOk(false, -1); + if (mGifAction != null) { + mGifAction.parseOk(false, -1); + } } else { mStatus = STATUS_FINISH; - mGifAction.parseOk(true, -1); + if (mGifAction != null) { + mGifAction.parseOk(true, -1); + } } } try { @@ -308,7 +314,9 @@ public class GifDecoder extends Thread { } } else { mStatus = STATUS_OPEN_ERROR; - mGifAction.parseOk(false, -1); + if (mGifAction != null) { + mGifAction.parseOk(false, -1); + } } return mStatus; } @@ -624,7 +632,9 @@ public class GifDecoder extends Thread { mAct[mTransIndex] = save; } resetFrame(); - mGifAction.parseOk(true, mFrameCount); + if (mGifAction != null) { + mGifAction.parseOk(true, mFrameCount); + } } catch (OutOfMemoryError e) { Log.e("GifDecoder", ">>> log : " + e.toString()); e.printStackTrace(); diff --git a/src/com/android/gallery3d/util/GifRequest.java b/src/com/android/gallery3d/util/GifRequest.java new file mode 100755 index 000000000..ea928ad91 --- /dev/null +++ b/src/com/android/gallery3d/util/GifRequest.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.gallery3d.util; + +import android.content.ContentResolver; +import android.content.Context; +import android.net.Uri; +import android.util.Log; + +import com.android.gallery3d.util.ThreadPool.Job; +import com.android.gallery3d.util.ThreadPool.JobContext; + +import java.io.InputStream; +import java.io.IOException; + + +public class GifRequest implements Job<GifDecoder> { + + private static final String TAG = "GifRequest"; + Uri itemUri; + Context mContext; + + public GifRequest(Uri uri, Context context) { + itemUri = uri; + mContext = context; + } + + private InputStream getInputStream(Uri uri) { + ContentResolver cr = mContext.getContentResolver(); + InputStream input = null; + try { + input = cr.openInputStream(uri); + } catch (IOException e) { + Log.e(TAG, "catch exception:" + e); + } + return input; + } + + @Override + public GifDecoder run(JobContext jc) { + InputStream input = getInputStream(itemUri); + if (input != null) { + return new GifDecoder(getInputStream(itemUri), null); + } else { + return null; + } + } + + +} + diff --git a/src/com/android/gallery3d/util/ViewGifImage.java b/src/com/android/gallery3d/util/ViewGifImage.java deleted file mode 100755 index cdd509280..000000000 --- a/src/com/android/gallery3d/util/ViewGifImage.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.android.gallery3d.util; - -import com.android.gallery3d.R; - -import android.app.Activity; -import android.content.res.Configuration; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.util.DisplayMetrics; -import android.view.ViewGroup.LayoutParams; -import android.widget.ImageView; -import android.widget.LinearLayout; - -public class ViewGifImage extends Activity { - private static final String TAG = "ViewGifImage"; - public static final String VIEW_GIF_ACTION = "com.android.gallery3d.VIEW_GIF"; - - public static DisplayMetrics mDM; - - private ImageView mGifView; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.view_gif_image); - mDM = new DisplayMetrics(); - getWindowManager().getDefaultDisplay().getMetrics(mDM); - if (getIntent().getAction() != null - && getIntent().getAction().equals(VIEW_GIF_ACTION)) { - Uri gifUri = getIntent().getData(); - showGifPicture(gifUri); - } - } - - @Override - protected void onStop() { - super.onStop(); - finish(); - } - - @Override - protected void onDestroy() { - if (mGifView != null && mGifView instanceof GIFView) { - ((GIFView) mGifView).freeMemory(); - mGifView = null; - } - super.onDestroy(); - } - - private void showGifPicture(Uri uri) { - mGifView = new GIFView(this); - ((LinearLayout) findViewById(R.id.image_absoluteLayout)).addView(mGifView, - new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); - if (((GIFView) mGifView).setDrawable(uri)) return; - - finish(); - - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - getWindowManager().getDefaultDisplay().getMetrics(mDM); - super.onConfigurationChanged(newConfig); - } -} diff --git a/src/org/codeaurora/gallery3d/ext/IContrllerOverlayExt.java b/src/org/codeaurora/gallery3d/ext/IContrllerOverlayExt.java index da50cdffc..73bef5e86 100644 --- a/src/org/codeaurora/gallery3d/ext/IContrllerOverlayExt.java +++ b/src/org/codeaurora/gallery3d/ext/IContrllerOverlayExt.java @@ -5,10 +5,9 @@ package org.codeaurora.gallery3d.ext; public interface IContrllerOverlayExt { /** * Show buffering state. - * @param fullBuffer - * @param percent + * @param what */ - void showBuffering(boolean fullBuffer, int percent); + void showBuffering(int what); /** * Clear buffering state. */ |
