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