1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.camera.session; 18 19 import android.content.Context; 20 21 import com.android.camera.debug.Log; 22 import com.android.camera.util.FileUtil; 23 24 import java.io.File; 25 import java.io.FileFilter; 26 import java.io.IOException; 27 28 /** 29 * Default implementation of {@link SessionStorageManager}. 30 */ 31 public class SessionStorageManagerImpl implements SessionStorageManager { 32 private static final Log.Tag TAG = new Log.Tag("SesnStorageMgrImpl"); 33 34 /** Delete temporary session directory remnants after ONE day. */ 35 private static final int MAX_SESSION_AGE_MILLIS = 24 * 60 * 60 * 1000; 36 37 /** The base directory for all temporary data. */ 38 private final File mBaseDirectory; 39 40 /** 41 * This is where we used to store temp session data, but it was the wrong 42 * place. But we want to make sure it's cleaned up for users that upgraded. 43 */ 44 private final File mDeprecatedBaseDirectory; 45 46 /** 47 * Creates a new {@link SessionStorageManager} instance. 48 * 49 * @param context A valid Android context to be used for determining the 50 * base directory. 51 * @return A session storage manager. 52 */ create(Context context)53 public static SessionStorageManager create(Context context) { 54 return new SessionStorageManagerImpl(context.getExternalCacheDir(), 55 context.getExternalFilesDir(null)); 56 } 57 SessionStorageManagerImpl(File baseDirectory, File deprecatedBaseDirectory)58 SessionStorageManagerImpl(File baseDirectory, File deprecatedBaseDirectory) { 59 mBaseDirectory = baseDirectory; 60 mDeprecatedBaseDirectory = deprecatedBaseDirectory; 61 } 62 63 @Override getSessionDirectory(String subDirectory)64 public File getSessionDirectory(String subDirectory) throws IOException { 65 File sessionDirectory = new File(mBaseDirectory, subDirectory); 66 if (!sessionDirectory.exists() && !sessionDirectory.mkdirs()) { 67 throw new IOException("Could not create session directory: " + sessionDirectory); 68 } 69 70 if (!sessionDirectory.isDirectory()) { 71 throw new IOException("Session directory is not a directory: " + sessionDirectory); 72 } 73 74 // Make sure there are no expired sessions in this directory. 75 cleanUpExpiredSessions(sessionDirectory); 76 77 // For upgraded users, make sure we also clean up the old location. 78 File deprecatedSessionDirectory = new File(mDeprecatedBaseDirectory, subDirectory); 79 cleanUpExpiredSessions(deprecatedSessionDirectory); 80 81 return sessionDirectory; 82 } 83 84 @Override createTemporaryOutputPath(String subDirectory, String title)85 public File createTemporaryOutputPath(String subDirectory, String title) throws IOException { 86 File tempDirectory = null; 87 try { 88 tempDirectory = new File( 89 getSessionDirectory(subDirectory), title); 90 } catch (IOException e) { 91 Log.e(TAG, "Could not get temp session directory", e); 92 throw new IOException("Could not get temp session directory", e); 93 } 94 if (!tempDirectory.mkdirs()) { 95 throw new IOException("Could not create output data directory."); 96 } 97 File tempFile = new File(tempDirectory, title + ".jpg"); 98 try { 99 if (!tempFile.exists()) { 100 if (!tempFile.createNewFile()) { 101 throw new IOException("Could not create output data file."); 102 } 103 } 104 } catch (IOException e) { 105 Log.e(TAG, "Could not create temp session file", e); 106 throw new IOException("Could not create temp session file", e); 107 } 108 109 if (!tempFile.canWrite()) { 110 throw new IOException("Temporary output file is not writeable."); 111 } 112 return tempFile; 113 } 114 115 /** 116 * Goes through all temporary sessions and deletes the ones that are older 117 * than a certain age. 118 */ cleanUpExpiredSessions(File baseDirectory)119 private void cleanUpExpiredSessions(File baseDirectory) { 120 File[] sessionDirs = baseDirectory.listFiles(new FileFilter() { 121 @Override 122 public boolean accept(File file) { 123 return file.isDirectory(); 124 } 125 }); 126 if (sessionDirs == null) { 127 return; 128 } 129 130 final long nowInMillis = System.currentTimeMillis(); 131 for (File sessionDir : sessionDirs) { 132 Log.v(TAG, "Check for potential clean-up: " + sessionDir.getAbsolutePath()); 133 if (sessionDir.lastModified() < (nowInMillis - MAX_SESSION_AGE_MILLIS)) { 134 if (!FileUtil.deleteDirectoryRecursively(sessionDir)) { 135 Log.w(TAG, "Could not clean up " + sessionDir.getAbsolutePath()); 136 } 137 } 138 } 139 } 140 } 141