diff options
Diffstat (limited to 'src/com/android/gallery3d/data')
-rw-r--r-- | src/com/android/gallery3d/data/DataManager.java | 6 | ||||
-rw-r--r-- | src/com/android/gallery3d/data/LocalImage.java | 89 | ||||
-rw-r--r-- | src/com/android/gallery3d/data/MediaItem.java | 8 | ||||
-rw-r--r-- | src/com/android/gallery3d/data/MediaObject.java | 33 | ||||
-rw-r--r-- | src/com/android/gallery3d/data/PanoramaMetadataJob.java | 40 | ||||
-rw-r--r-- | src/com/android/gallery3d/data/UriImage.java | 89 |
6 files changed, 192 insertions, 73 deletions
diff --git a/src/com/android/gallery3d/data/DataManager.java b/src/com/android/gallery3d/data/DataManager.java index 95954e59a..3d2c0c2f0 100644 --- a/src/com/android/gallery3d/data/DataManager.java +++ b/src/com/android/gallery3d/data/DataManager.java @@ -250,6 +250,12 @@ public class DataManager { return getMediaObject(path).getSupportedOperations(); } + // getAll will cause this call to wait if any of the operations + // are expensive to compute. Do not call in UI thread. + public int getSupportedOperations(Path path, boolean getAll) { + return getMediaObject(path).getSupportedOperations(getAll); + } + public void delete(Path path) { getMediaObject(path).delete(); } diff --git a/src/com/android/gallery3d/data/LocalImage.java b/src/com/android/gallery3d/data/LocalImage.java index 5d6d39dcf..dba6b68eb 100644 --- a/src/com/android/gallery3d/data/LocalImage.java +++ b/src/com/android/gallery3d/data/LocalImage.java @@ -36,8 +36,11 @@ import com.android.gallery3d.app.GalleryApp; import com.android.gallery3d.app.StitchingProgressManager; import com.android.gallery3d.common.ApiHelper; import com.android.gallery3d.common.BitmapUtils; +import com.android.gallery3d.util.Future; +import com.android.gallery3d.util.FutureListener; import com.android.gallery3d.util.GalleryUtils; import com.android.gallery3d.util.LightCycleHelper; +import com.android.gallery3d.util.LightCycleHelper.PanoramaMetadata; import com.android.gallery3d.util.ThreadPool.Job; import com.android.gallery3d.util.ThreadPool.JobContext; import com.android.gallery3d.util.UpdateHelper; @@ -101,11 +104,11 @@ public class LocalImage extends LocalMediaItem { public int rotation; - private boolean mUsePanoramaViewer; - private boolean mUsePanoramaViewerInitialized; - - private boolean mIsPanorama360; - private boolean mIsPanorama360Initialized; + private Object mLock = new Object(); + private Future<PanoramaMetadata> mGetPanoMetadataTask; + private boolean mPanoramaMetadataInitialized; + private PanoramaMetadata mPanoramaMetadata; + private SupportedOperationsListener mListener; public LocalImage(Path path, GalleryApp application, Cursor cursor) { super(path, nextVersionNumber()); @@ -255,9 +258,9 @@ public class LocalImage extends LocalMediaItem { operation |= SUPPORT_SHOW_ON_MAP; } - if (usePanoramaViewer()) { + if (mPanoramaMetadata != null && mPanoramaMetadata.mUsePanoramaViewer) { operation |= SUPPORT_PANORAMA; - if (isPanorama360()) { + if (mPanoramaMetadata.mIsPanorama360) { operation |= SUPPORT_PANORAMA360; // disable destructive rotate and crop for 360 degree panorama operation &= ~(SUPPORT_ROTATE | SUPPORT_CROP); @@ -267,6 +270,55 @@ public class LocalImage extends LocalMediaItem { } @Override + public int getSupportedOperations(boolean getAll) { + synchronized (mLock) { + if (getAll && !mPanoramaMetadataInitialized) { + if (mGetPanoMetadataTask == null) { + mGetPanoMetadataTask = getThreadPool().submit( + new PanoramaMetadataJob(mApplication.getAndroidContext(), + getContentUri())); + } + mPanoramaMetadata = mGetPanoMetadataTask.get(); + mPanoramaMetadataInitialized = true; + } + } + return getSupportedOperations(); + } + + @Override + public void setSupportedOperationsListener(SupportedOperationsListener l) { + synchronized (mLock) { + if (mPanoramaMetadataInitialized) return; // no more updates + + if (l == null) { + if (mGetPanoMetadataTask != null) { + mGetPanoMetadataTask.cancel(); + mGetPanoMetadataTask = null; + } + } else { + if (mGetPanoMetadataTask == null) { + mGetPanoMetadataTask = getThreadPool().submit( + new PanoramaMetadataJob(mApplication.getAndroidContext(), + getContentUri()), + new FutureListener<PanoramaMetadata>() { + @Override + public void onFutureDone(Future<PanoramaMetadata> future) { + mGetPanoMetadataTask = null; + if (future.isCancelled()) return; + mPanoramaMetadata = future.get(); + mPanoramaMetadataInitialized = true; + if (mListener != null) { + mListener.onChange(getSupportedOperations()); + } + } + }); + } + } + mListener = l; + } + } + + @Override public void delete() { GalleryUtils.assertNotInRenderThread(); Uri baseUri = Images.Media.EXTERNAL_CONTENT_URI; @@ -360,27 +412,4 @@ public class LocalImage extends LocalMediaItem { public String getFilePath() { return filePath; } - - @Override - public boolean usePanoramaViewer() { - if (!mUsePanoramaViewerInitialized) { - Context context = mApplication.getAndroidContext(); - mUsePanoramaViewer = LightCycleHelper.hasLightCycleView(context) - && LightCycleHelper.isPanorama(mApplication.getContentResolver(), - getContentUri()); - mUsePanoramaViewerInitialized = true; - } - return mUsePanoramaViewer; - } - - @Override - public boolean isPanorama360() { - // cache flag for faster access - if (!mIsPanorama360Initialized) { - mIsPanorama360 = LightCycleHelper.isPanorama360( - mApplication.getAndroidContext(), getContentUri()); - mIsPanorama360Initialized = true; - } - return mIsPanorama360; - } } diff --git a/src/com/android/gallery3d/data/MediaItem.java b/src/com/android/gallery3d/data/MediaItem.java index da59abeef..19084d41e 100644 --- a/src/com/android/gallery3d/data/MediaItem.java +++ b/src/com/android/gallery3d/data/MediaItem.java @@ -103,14 +103,6 @@ public abstract class MediaItem extends MediaObject { return ""; } - public boolean usePanoramaViewer() { - return false; - } - - public boolean isPanorama360() { - return false; - } - // Returns width and height of the media item. // Returns 0, 0 if the information is not available. public abstract int getWidth(); diff --git a/src/com/android/gallery3d/data/MediaObject.java b/src/com/android/gallery3d/data/MediaObject.java index a16b9666d..382a5c792 100644 --- a/src/com/android/gallery3d/data/MediaObject.java +++ b/src/com/android/gallery3d/data/MediaObject.java @@ -18,6 +18,8 @@ package com.android.gallery3d.data; import android.net.Uri; +import com.android.gallery3d.util.ThreadPool; + public abstract class MediaObject { @SuppressWarnings("unused") private static final String TAG = "MediaObject"; @@ -37,14 +39,20 @@ public abstract class MediaObject { public static final int SUPPORT_INFO = 1 << 10; public static final int SUPPORT_IMPORT = 1 << 11; public static final int SUPPORT_TRIM = 1 << 12; - public static final int SUPPORT_PANORAMA = 1 << 13; - public static final int SUPPORT_PANORAMA360 = 1 << 14; - public static final int SUPPORT_UNLOCK = 1 << 15; - public static final int SUPPORT_BACK = 1 << 16; - public static final int SUPPORT_ACTION = 1 << 17; - public static final int SUPPORT_CAMERA_SHORTCUT = 1 << 18; + public static final int SUPPORT_UNLOCK = 1 << 13; + public static final int SUPPORT_BACK = 1 << 14; + public static final int SUPPORT_ACTION = 1 << 15; + public static final int SUPPORT_CAMERA_SHORTCUT = 1 << 16; + // The panorama specific bits are expensive to compute. + // Use SupportedOperationsListener to request them. + public static final int SUPPORT_PANORAMA = 1 << 30; + public static final int SUPPORT_PANORAMA360 = 1 << 31; public static final int SUPPORT_ALL = 0xffffffff; + public static interface SupportedOperationsListener { + public void onChange(int operations); + } + // These are the bits returned from getMediaType(): public static final int MEDIA_TYPE_UNKNOWN = 1; public static final int MEDIA_TYPE_IMAGE = 2; @@ -72,6 +80,11 @@ public abstract class MediaObject { protected final Path mPath; + private static ThreadPool sThreadPool = new ThreadPool(1, 1); + public static ThreadPool getThreadPool() { + return sThreadPool; + } + public MediaObject(Path path, long version) { path.setObject(this); mPath = path; @@ -86,6 +99,14 @@ public abstract class MediaObject { return 0; } + public int getSupportedOperations(boolean getAll) { + return 0; + } + + public void setSupportedOperationsListener(SupportedOperationsListener l) { + // nothing to do + } + public void delete() { throw new UnsupportedOperationException(); } diff --git a/src/com/android/gallery3d/data/PanoramaMetadataJob.java b/src/com/android/gallery3d/data/PanoramaMetadataJob.java new file mode 100644 index 000000000..e0a69c41f --- /dev/null +++ b/src/com/android/gallery3d/data/PanoramaMetadataJob.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.data; + +import android.content.Context; +import android.net.Uri; + +import com.android.gallery3d.util.LightCycleHelper; +import com.android.gallery3d.util.LightCycleHelper.PanoramaMetadata; +import com.android.gallery3d.util.ThreadPool.Job; +import com.android.gallery3d.util.ThreadPool.JobContext; + +class PanoramaMetadataJob implements Job<PanoramaMetadata> { + Context mContext; + Uri mUri; + + public PanoramaMetadataJob(Context context, Uri uri) { + mContext = context; + mUri = uri; + } + + @Override + public PanoramaMetadata run(JobContext jc) { + return LightCycleHelper.getPanoramaMetadata(mContext, mUri); + } +} diff --git a/src/com/android/gallery3d/data/UriImage.java b/src/com/android/gallery3d/data/UriImage.java index b2cbc7d68..5fab667b8 100644 --- a/src/com/android/gallery3d/data/UriImage.java +++ b/src/com/android/gallery3d/data/UriImage.java @@ -28,7 +28,10 @@ import android.os.ParcelFileDescriptor; import com.android.gallery3d.app.GalleryApp; import com.android.gallery3d.common.BitmapUtils; import com.android.gallery3d.common.Utils; +import com.android.gallery3d.util.Future; +import com.android.gallery3d.util.FutureListener; import com.android.gallery3d.util.LightCycleHelper; +import com.android.gallery3d.util.LightCycleHelper.PanoramaMetadata; import com.android.gallery3d.util.ThreadPool.CancelListener; import com.android.gallery3d.util.ThreadPool.Job; import com.android.gallery3d.util.ThreadPool.JobContext; @@ -56,10 +59,12 @@ public class UriImage extends MediaItem { private int mWidth; private int mHeight; private int mRotation; - private boolean mUsePanoramaViewer; - private boolean mUsePanoramaViewerInitialized; - private boolean mIsPanorama360; - private boolean mIsPanorama360Initialized; + + private Object mLock = new Object(); + private Future<PanoramaMetadata> mGetPanoMetadataTask; + private boolean mPanoramaMetadataInitialized; + private PanoramaMetadata mPanoramaMetadata; + private SupportedOperationsListener mListener; private GalleryApp mApplication; @@ -220,9 +225,9 @@ public class UriImage extends MediaItem { if (BitmapUtils.isSupportedByRegionDecoder(mContentType)) { supported |= SUPPORT_FULL_IMAGE; } - if (usePanoramaViewer()) { + if (mPanoramaMetadata != null && mPanoramaMetadata.mUsePanoramaViewer) { supported |= SUPPORT_PANORAMA; - if (isPanorama360()) { + if (mPanoramaMetadata.mIsPanorama360) { supported |= SUPPORT_PANORAMA360; // disable destructive crop for 360 degree panorama supported &= ~SUPPORT_CROP; @@ -231,6 +236,55 @@ public class UriImage extends MediaItem { return supported; } + @Override + public int getSupportedOperations(boolean getAll) { + synchronized (mLock) { + if (getAll && !mPanoramaMetadataInitialized) { + if (mGetPanoMetadataTask == null) { + mGetPanoMetadataTask = getThreadPool().submit( + new PanoramaMetadataJob(mApplication.getAndroidContext(), + getContentUri())); + } + mPanoramaMetadata = mGetPanoMetadataTask.get(); + mPanoramaMetadataInitialized = true; + } + } + return getSupportedOperations(); + } + + @Override + public void setSupportedOperationsListener(SupportedOperationsListener l) { + synchronized (mLock) { + if (mPanoramaMetadataInitialized) return; // no more updates + + if (l != null) { + if (mGetPanoMetadataTask != null) { + mGetPanoMetadataTask.cancel(); + mGetPanoMetadataTask = null; + } + } else { + if (mGetPanoMetadataTask == null) { + mGetPanoMetadataTask = getThreadPool().submit( + new PanoramaMetadataJob(mApplication.getAndroidContext(), + getContentUri()), + new FutureListener<PanoramaMetadata>() { + @Override + public void onFutureDone(Future<PanoramaMetadata> future) { + mGetPanoMetadataTask = null; + if (future.isCancelled()) return; + mPanoramaMetadata = future.get(); + mPanoramaMetadataInitialized = true; + if (mListener != null) { + mListener.onChange(getSupportedOperations()); + } + } + }); + } + } + mListener = l; + } + } + private boolean isSharable() { // We cannot grant read permission to the receiver since we put // the data URI in EXTRA_STREAM instead of the data part of an intent @@ -297,27 +351,4 @@ public class UriImage extends MediaItem { public int getRotation() { return mRotation; } - - @Override - public boolean usePanoramaViewer() { - if (!mUsePanoramaViewerInitialized) { - Context context = mApplication.getAndroidContext(); - mUsePanoramaViewer = LightCycleHelper.hasLightCycleView(context) - && LightCycleHelper.isPanorama(mApplication.getContentResolver(), - getContentUri()); - mUsePanoramaViewerInitialized = true; - } - return mUsePanoramaViewer; - } - - @Override - public boolean isPanorama360() { - // cache flag for faster access - if (!mIsPanorama360Initialized) { - mIsPanorama360 = LightCycleHelper.isPanorama360( - mApplication.getAndroidContext(), getContentUri()); - mIsPanorama360Initialized = true; - } - return mIsPanorama360; - } } |