Home | History | Annotate | Download | only in session
      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      */
     53     public static SessionStorageManager create(Context context) {
     54         return new SessionStorageManagerImpl(context.getExternalCacheDir(),
     55                 context.getExternalFilesDir(null));
     56     }
     57 
     58     SessionStorageManagerImpl(File baseDirectory, File deprecatedBaseDirectory) {
     59         mBaseDirectory = baseDirectory;
     60         mDeprecatedBaseDirectory = deprecatedBaseDirectory;
     61     }
     62 
     63     @Override
     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
     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      */
    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