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     /**
85      * Goes through all temporary sessions and deletes the ones that are older
86      * than a certain age.
87      */
cleanUpExpiredSessions(File baseDirectory)88     private void cleanUpExpiredSessions(File baseDirectory) {
89         File[] sessionDirs = baseDirectory.listFiles(new FileFilter() {
90             @Override
91             public boolean accept(File file) {
92                 return file.isDirectory();
93             }
94         });
95         if (sessionDirs == null) {
96             return;
97         }
98 
99         final long nowInMillis = System.currentTimeMillis();
100         for (File sessionDir : sessionDirs) {
101             if (sessionDir.lastModified() < (nowInMillis - MAX_SESSION_AGE_MILLIS)) {
102                 if (!FileUtil.deleteDirectoryRecursively(sessionDir)) {
103                     Log.w(TAG, "Could not clean up " + sessionDir.getAbsolutePath());
104                 }
105             }
106         }
107     }
108 }
109