Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 09169dd2 authored by ztenghui's avatar ztenghui
Browse files

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
parent 3f003414
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -32,17 +32,19 @@ abstract class ImageCacheRequest implements Job<Bitmap> {
    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<Bitmap> {

        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<Bitmap> {
        byte[] array = BitmapUtils.compressToBytes(bitmap);
        if (jc.isCancelled()) return null;

        cacheService.putImageData(mPath, mType, array);
        cacheService.putImageData(mPath, mTimeModified, mType, array);
        return bitmap;
    }

+10 −9
Original line number Diff line number Diff line
@@ -46,7 +46,8 @@ public class ImageCacheService {
    }

    /**
     * Gets the cached image data for the given <code>path</code> and <code>type</code>.
     * Gets the cached image data for the given <code>path</code>,
     *  <code>timeModified</code> and <code>type</code>.
     *
     * The image data will be stored in <code>buffer.data</code>, started from
     * <code>buffer.offset</code> for <code>buffer.length</code> 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) {
+6 −4
Original line number Diff line number Diff line
@@ -173,15 +173,17 @@ public class LocalImage extends LocalMediaItem {

    @Override
    public Job<Bitmap> 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;
        }

+6 −4
Original line number Diff line number Diff line
@@ -152,15 +152,17 @@ public class LocalVideo extends LocalMediaItem {

    @Override
    public Job<Bitmap> 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;
        }

+31 −51
Original line number Diff line number Diff line
@@ -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);
                }
                updateProgress();

                    // mDestinationFile will save the newSourceUri info in the XMP.
                XmpPresets.writeFilterXMP(mContext, newSourceUri, mDestinationFile, preset);
                updateProgress();
                    XmpPresets.writeFilterXMP(mContext, newSourceUri,
                            mDestinationFile, preset);

                // 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();
                    // After this call, mSelectedImageUri will be actually
                    // pointing at the new file mDestinationFile.
                    uri = SaveImage.updateUriContent(mContext, mSelectedImageUri,
                            mDestinationFile, time);
                }
                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;
    }

}
Loading