From d32b92d96ad07f15f6130a8608a67ab96c962a96 Mon Sep 17 00:00:00 2001 From: ztenghui Date: Thu, 18 Jul 2013 14:40:10 -0700 Subject: Update Uri instead of removing In this way, the processing service can have a better presentation. The cache key now include the file Uri and local abs path if exists. bug:9468909 Change-Id: I0919c09ad26bea2e798c99ad376996547f8f2bf8 --- .../android/gallery3d/data/ImageCacheRequest.java | 10 +-- .../android/gallery3d/data/ImageCacheService.java | 19 ++--- src/com/android/gallery3d/data/LocalImage.java | 10 +-- src/com/android/gallery3d/data/LocalVideo.java | 10 +-- .../gallery3d/filtershow/tools/SaveImage.java | 82 ++++++++-------------- .../android/gallery3d/util/LightCycleHelper.java | 15 ++++ 6 files changed, 74 insertions(+), 72 deletions(-) diff --git a/src/com/android/gallery3d/data/ImageCacheRequest.java b/src/com/android/gallery3d/data/ImageCacheRequest.java index 475614962..6cbc5c5ea 100644 --- a/src/com/android/gallery3d/data/ImageCacheRequest.java +++ b/src/com/android/gallery3d/data/ImageCacheRequest.java @@ -32,17 +32,19 @@ abstract class ImageCacheRequest implements Job { private Path mPath; private int mType; private int mTargetSize; + private long mTimeModified; public ImageCacheRequest(GalleryApp application, - Path path, int type, int targetSize) { + Path path, long timeModified, int type, int targetSize) { mApplication = application; mPath = path; mType = type; mTargetSize = targetSize; + mTimeModified = timeModified; } private String debugTag() { - return mPath + "," + + return mPath + "," + mTimeModified + "," + ((mType == MediaItem.TYPE_THUMBNAIL) ? "THUMB" : (mType == MediaItem.TYPE_MICROTHUMBNAIL) ? "MICROTHUMB" : "?"); } @@ -53,7 +55,7 @@ abstract class ImageCacheRequest implements Job { BytesBuffer buffer = MediaItem.getBytesBufferPool().get(); try { - boolean found = cacheService.getImageData(mPath, mType, buffer); + boolean found = cacheService.getImageData(mPath, mTimeModified, mType, buffer); if (jc.isCancelled()) return null; if (found) { BitmapFactory.Options options = new BitmapFactory.Options(); @@ -92,7 +94,7 @@ abstract class ImageCacheRequest implements Job { byte[] array = BitmapUtils.compressToBytes(bitmap); if (jc.isCancelled()) return null; - cacheService.putImageData(mPath, mType, array); + cacheService.putImageData(mPath, mTimeModified, mType, array); return bitmap; } diff --git a/src/com/android/gallery3d/data/ImageCacheService.java b/src/com/android/gallery3d/data/ImageCacheService.java index 527d6c8cd..1c7cb8c5e 100644 --- a/src/com/android/gallery3d/data/ImageCacheService.java +++ b/src/com/android/gallery3d/data/ImageCacheService.java @@ -46,7 +46,8 @@ public class ImageCacheService { } /** - * Gets the cached image data for the given path and type. + * Gets the cached image data for the given path, + * timeModified and type. * * The image data will be stored in buffer.data, started from * buffer.offset for buffer.length bytes. If the @@ -54,8 +55,8 @@ public class ImageCacheService { * * @return true if the image data is found; false if not found. */ - public boolean getImageData(Path path, int type, BytesBuffer buffer) { - byte[] key = makeKey(path, type); + public boolean getImageData(Path path, long timeModified, int type, BytesBuffer buffer) { + byte[] key = makeKey(path, timeModified, type); long cacheKey = Utils.crc64Long(key); try { LookupRequest request = new LookupRequest(); @@ -76,8 +77,8 @@ public class ImageCacheService { return false; } - public void putImageData(Path path, int type, byte[] value) { - byte[] key = makeKey(path, type); + public void putImageData(Path path, long timeModified, int type, byte[] value) { + byte[] key = makeKey(path, timeModified, type); long cacheKey = Utils.crc64Long(key); ByteBuffer buffer = ByteBuffer.allocate(key.length + value.length); buffer.put(key); @@ -91,8 +92,8 @@ public class ImageCacheService { } } - public void clearImageData(Path path, int type) { - byte[] key = makeKey(path, type); + public void clearImageData(Path path, long timeModified, int type) { + byte[] key = makeKey(path, timeModified, type); long cacheKey = Utils.crc64Long(key); synchronized (mCache) { try { @@ -103,8 +104,8 @@ public class ImageCacheService { } } - private static byte[] makeKey(Path path, int type) { - return GalleryUtils.getBytes(path.toString() + "+" + type); + private static byte[] makeKey(Path path, long timeModified, int type) { + return GalleryUtils.getBytes(path.toString() + "+" + timeModified + "+" + type); } private static boolean isSameKey(byte[] key, byte[] buffer) { diff --git a/src/com/android/gallery3d/data/LocalImage.java b/src/com/android/gallery3d/data/LocalImage.java index eb1efae66..cc70dd457 100644 --- a/src/com/android/gallery3d/data/LocalImage.java +++ b/src/com/android/gallery3d/data/LocalImage.java @@ -173,15 +173,17 @@ public class LocalImage extends LocalMediaItem { @Override public Job requestImage(int type) { - return new LocalImageRequest(mApplication, mPath, type, filePath); + return new LocalImageRequest(mApplication, mPath, dateModifiedInSec, + type, filePath); } public static class LocalImageRequest extends ImageCacheRequest { private String mLocalFilePath; - LocalImageRequest(GalleryApp application, Path path, int type, - String localFilePath) { - super(application, path, type, MediaItem.getTargetSize(type)); + LocalImageRequest(GalleryApp application, Path path, long timeModified, + int type, String localFilePath) { + super(application, path, timeModified, type, + MediaItem.getTargetSize(type)); mLocalFilePath = localFilePath; } diff --git a/src/com/android/gallery3d/data/LocalVideo.java b/src/com/android/gallery3d/data/LocalVideo.java index b1e1cb3aa..4b8774ca4 100644 --- a/src/com/android/gallery3d/data/LocalVideo.java +++ b/src/com/android/gallery3d/data/LocalVideo.java @@ -152,15 +152,17 @@ public class LocalVideo extends LocalMediaItem { @Override public Job requestImage(int type) { - return new LocalVideoRequest(mApplication, getPath(), type, filePath); + return new LocalVideoRequest(mApplication, getPath(), dateModifiedInSec, + type, filePath); } public static class LocalVideoRequest extends ImageCacheRequest { private String mLocalFilePath; - LocalVideoRequest(GalleryApp application, Path path, int type, - String localFilePath) { - super(application, path, type, MediaItem.getTargetSize(type)); + LocalVideoRequest(GalleryApp application, Path path, long timeModified, + int type, String localFilePath) { + super(application, path, timeModified, type, + MediaItem.getTargetSize(type)); mLocalFilePath = localFilePath; } diff --git a/src/com/android/gallery3d/filtershow/tools/SaveImage.java b/src/com/android/gallery3d/filtershow/tools/SaveImage.java index 9b13af13d..3489fbe73 100644 --- a/src/com/android/gallery3d/filtershow/tools/SaveImage.java +++ b/src/com/android/gallery3d/filtershow/tools/SaveImage.java @@ -29,8 +29,6 @@ import android.provider.MediaStore.Images; import android.provider.MediaStore.Images.ImageColumns; import android.util.Log; -import com.android.gallery3d.R; -import com.android.gallery3d.app.PhotoPage; import com.android.gallery3d.common.Utils; import com.android.gallery3d.exif.ExifInterface; import com.android.gallery3d.filtershow.FilterShowActivity; @@ -75,11 +73,6 @@ public class SaveImage { private static final String POSTFIX_JPG = ".jpg"; private static final String AUX_DIR_NAME = ".aux"; - // When this is true, the source file will be saved into auxiliary directory - // and hidden from MediaStore. Otherwise, the source will be kept as the - // same. - private static final boolean USE_AUX_DIR = true; - private final Context mContext; private final Uri mSourceUri; private final Callback mCallback; @@ -119,8 +112,6 @@ public class SaveImage { // names starting with "local." will be deleted. // This pattern will facilitate the multiple images deletion in the auxiliary // directory. - // - // TODO: Move the saving into a background service. /** * @param context @@ -292,9 +283,8 @@ public class SaveImage { // create a local copy as usual. if (srcFile != null) { srcFile.renameTo(mDestinationFile); - uri = SaveImage.insertContent(mContext, mSelectedImageUri, mDestinationFile, - System.currentTimeMillis()); - removeSelectedImage(); + uri = SaveImage.updateUriContent(mContext, mSelectedImageUri, + mDestinationFile, System.currentTimeMillis()); } } return uri; @@ -326,12 +316,8 @@ public class SaveImage { // If necessary, move the source file into the auxiliary directory, // newSourceUri is then pointing to the new location. // If no file is moved, newSourceUri will be the same as mSourceUri. - Uri newSourceUri; - if (USE_AUX_DIR) { - newSourceUri = moveSrcToAuxIfNeeded(mSourceUri, mDestinationFile); - } else { - newSourceUri = mSourceUri; - } + Uri newSourceUri = moveSrcToAuxIfNeeded(mSourceUri, mDestinationFile); + // Stopgap fix for low-memory devices. while (noBitmap) { try { @@ -349,39 +335,35 @@ public class SaveImage { bitmap = pipeline.renderFinalImage(bitmap, preset); updateProgress(); - Object xmp = getPanoramaXMPData(mSelectedImageUri, preset); - ExifInterface exif = getExifData(mSelectedImageUri); + Object xmp = getPanoramaXMPData(newSourceUri, preset); + ExifInterface exif = getExifData(newSourceUri); + updateProgress(); // Set tags long time = System.currentTimeMillis(); exif.addDateTimeStampTag(ExifInterface.TAG_DATE_TIME, time, TimeZone.getDefault()); exif.setTag(exif.buildTag(ExifInterface.TAG_ORIENTATION, ExifInterface.Orientation.TOP_LEFT)); - // Remove old thumbnail exif.removeCompressedThumbnail(); + updateProgress(); + // If we succeed in writing the bitmap as a jpeg, return a uri. if (putExifData(mDestinationFile, exif, bitmap)) { putPanoramaXMPData(mDestinationFile, xmp); - uri = SaveImage.insertContent(mContext, mSelectedImageUri, mDestinationFile, - time); + // mDestinationFile will save the newSourceUri info in the XMP. + XmpPresets.writeFilterXMP(mContext, newSourceUri, + mDestinationFile, preset); + + // After this call, mSelectedImageUri will be actually + // pointing at the new file mDestinationFile. + uri = SaveImage.updateUriContent(mContext, mSelectedImageUri, + mDestinationFile, time); } updateProgress(); - // mDestinationFile will save the newSourceUri info in the XMP. - XmpPresets.writeFilterXMP(mContext, newSourceUri, mDestinationFile, preset); - updateProgress(); - - // Since we have a new image inserted to media store, we can - // safely remove the old one which is selected by the user. - // TODO: we should fix that, do an update instead of insert+remove, - // as well as asking Gallery to update its cached version of the image - if (USE_AUX_DIR) { - removeSelectedImage(); - } - updateProgress(); noBitmap = false; UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, "SaveComplete", null); @@ -398,15 +380,6 @@ public class SaveImage { return uri; } - private void removeSelectedImage() { - String scheme = mSelectedImageUri.getScheme(); - if (scheme != null && scheme.equals(ContentResolver.SCHEME_CONTENT)) { - if (mSelectedImageUri.getAuthority().equals(MediaStore.AUTHORITY)) { - mContext.getContentResolver().delete(mSelectedImageUri, null, null); - } - } - } - /** * Move the source file to auxiliary directory if needed and return the Uri * pointing to this new source file. @@ -463,7 +436,7 @@ public class SaveImage { String filename = new SimpleDateFormat(TIME_STAMP_NAME).format(new Date(time)); File saveDirectory = getFinalSaveDirectory(context, sourceUri); File file = new File(saveDirectory, filename + ".JPG"); - return insertContent(context, sourceUri, file, time); + return updateUriContent(context, sourceUri, file, time); } public static void saveImage(ImagePreset preset, final FilterShowActivity filterShowActivity, @@ -583,12 +556,14 @@ public class SaveImage { } /** - * Insert the content (saved file) with proper source photo properties. + * Update the content Uri with the new file and proper source properties. + * The old file will be removed if it is local. */ - public static Uri insertContent(Context context, Uri sourceUri, File file, long time) { - time /= 1000; - + public static Uri updateUriContent(Context context, Uri sourceUri, File file, long time) { + File oldSelectedFile = getLocalFileFromUri(context, sourceUri); final ContentValues values = new ContentValues(); + + time /= 1000; values.put(Images.Media.TITLE, file.getName()); values.put(Images.Media.DISPLAY_NAME, file.getName()); values.put(Images.Media.MIME_TYPE, "image/jpeg"); @@ -621,8 +596,13 @@ public class SaveImage { } }); - return context.getContentResolver().insert( - Images.Media.EXTERNAL_CONTENT_URI, values); + context.getContentResolver().update(sourceUri, values, null, null); + + if (oldSelectedFile != null && oldSelectedFile.exists()) { + oldSelectedFile.delete(); + } + + return sourceUri; } } diff --git a/src_pd/com/android/gallery3d/util/LightCycleHelper.java b/src_pd/com/android/gallery3d/util/LightCycleHelper.java index bceeea6b4..5cd910f8f 100644 --- a/src_pd/com/android/gallery3d/util/LightCycleHelper.java +++ b/src_pd/com/android/gallery3d/util/LightCycleHelper.java @@ -17,6 +17,7 @@ package com.android.gallery3d.util; import android.app.Activity; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.net.Uri; @@ -82,4 +83,18 @@ public class LightCycleHelper { public static StitchingProgressManager createStitchingManagerInstance(GalleryApp app) { return null; } + + /** + * Get the file path from a Media storage URI. + */ + public static String getPathFromURI(ContentResolver contentResolver, Uri contentUri) { + return null; + } + + /** + * Get the modified time from a Media storage URI. + */ + public static long getModifiedTimeFromURI(ContentResolver contentResolver, Uri contentUri) { + return 0; + } } -- cgit v1.2.3