124069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling/*
224069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling * Copyright (C) 2014 The Android Open Source Project
324069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling *
424069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling * Licensed under the Apache License, Version 2.0 (the "License");
524069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling * you may not use this file except in compliance with the License.
624069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling * You may obtain a copy of the License at
724069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling *
824069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling *      http://www.apache.org/licenses/LICENSE-2.0
924069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling *
1024069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling * Unless required by applicable law or agreed to in writing, software
1124069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling * distributed under the License is distributed on an "AS IS" BASIS,
1224069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1324069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling * See the License for the specific language governing permissions and
1424069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling * limitations under the License.
1524069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling */
1624069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling
1724069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberlingpackage com.android.camera.session;
1824069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling
1924069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberlingimport android.content.ContentResolver;
2024069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberlingimport android.location.Location;
2124069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberlingimport android.net.Uri;
2224069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling
2324069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberlingimport com.android.camera.Storage;
2424069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberlingimport com.android.camera.debug.Log;
2524069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling
2624069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberlingimport java.io.File;
2724069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling
2824069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling/**
2924069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling * Default implementation of the {@link StackSaver} interface. It creates a
3024069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling * directory for each stack and stores images and if needed also metadata inside
3124069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling * that directory.
3224069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling * <p>
3324069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling * TODO: Add placeholder support for stack writing.
3424069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling * </p>
3524069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling */
3624069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberlingpublic class StackSaverImpl implements StackSaver {
3724069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling    private static final Log.Tag TAG = new Log.Tag("StackSaverImpl");
3824069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling    /** The stacked images are stored in this directory. */
3924069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling    private final File mStackDirectory;
4024069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling    private final ContentResolver mContentResolver;
4124069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling    private final Location mGpsLocation;
4224069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling
4324069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling    /**
4424069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling     * Instantiate a new stack saver implementation.
4524069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling     *
4624069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling     * @param stackDirectory the directory, which either exists already or can
4724069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling     *            be created, into which images belonging to this stack are
4824069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling     *            belonging.
4924069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling     * @param gpsLocation the GPS location to attach to all stacked images.
5024069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling     * @param contentResolver content resolver for storing the data in media
5124069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling     *            store. TODO: Replace with a media storage storer that can be
5224069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling     *            mocked out in tests.
5324069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling     */
544361352633d1e106c1574c02ddd27c8891c5ee78Shashi Shekhar    public StackSaverImpl(File stackDirectory, Location gpsLocation,
554361352633d1e106c1574c02ddd27c8891c5ee78Shashi Shekhar            ContentResolver contentResolver) {
5624069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling        mStackDirectory = stackDirectory;
5724069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling        mGpsLocation = gpsLocation;
5824069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling        mContentResolver = contentResolver;
5924069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling    }
6024069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling
6124069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling    @Override
624361352633d1e106c1574c02ddd27c8891c5ee78Shashi Shekhar    public Uri saveStackedImage(File inputImagePath, String title, int width, int height,
634361352633d1e106c1574c02ddd27c8891c5ee78Shashi Shekhar            int imageOrientation, long captureTimeEpoch, String mimeType) {
6424069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling        String filePath =
6524069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling                Storage.generateFilepath(mStackDirectory.getAbsolutePath(), title, mimeType);
6624069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling        Log.d(TAG, "Saving using stack image saver: " + filePath);
674361352633d1e106c1574c02ddd27c8891c5ee78Shashi Shekhar        File outputImagePath = new File(filePath);
6824069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling
694361352633d1e106c1574c02ddd27c8891c5ee78Shashi Shekhar        if (Storage.renameFile(inputImagePath, outputImagePath)) {
704361352633d1e106c1574c02ddd27c8891c5ee78Shashi Shekhar            long fileLength = outputImagePath.length();
714361352633d1e106c1574c02ddd27c8891c5ee78Shashi Shekhar            if (fileLength > 0) {
724361352633d1e106c1574c02ddd27c8891c5ee78Shashi Shekhar                return Storage.addImageToMediaStore(mContentResolver, title, captureTimeEpoch,
734361352633d1e106c1574c02ddd27c8891c5ee78Shashi Shekhar                        mGpsLocation, imageOrientation, fileLength, filePath, width, height,
744361352633d1e106c1574c02ddd27c8891c5ee78Shashi Shekhar                        mimeType);
754361352633d1e106c1574c02ddd27c8891c5ee78Shashi Shekhar            }
7624069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling        }
774361352633d1e106c1574c02ddd27c8891c5ee78Shashi Shekhar
784361352633d1e106c1574c02ddd27c8891c5ee78Shashi Shekhar        Log.e(TAG, String.format("Unable to rename file from %s to %s.",
794361352633d1e106c1574c02ddd27c8891c5ee78Shashi Shekhar                inputImagePath.getPath(),
804361352633d1e106c1574c02ddd27c8891c5ee78Shashi Shekhar                filePath));
8124069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling        return null;
8224069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling    }
8324069e7a9cc9b4f908f18a71301285ccf5e164f6Sascha Haeberling}
84