1/*
2 * Copyright (C) 2013 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
17package com.android.inputmethod.research;
18
19import android.content.Context;
20import android.util.Log;
21
22import java.io.File;
23import java.io.FileFilter;
24
25/**
26 * Manages log files.
27 *
28 * This class handles all aspects where and how research log data is stored.  This includes
29 * generating log filenames in the correct place with the correct names, and cleaning up log files
30 * under this directory.
31 */
32public class ResearchLogDirectory {
33    public static final String TAG = ResearchLogDirectory.class.getSimpleName();
34    /* package */ static final String LOG_FILENAME_PREFIX = "researchLog";
35    private static final String FILENAME_SUFFIX = ".txt";
36    private static final String USER_RECORDING_FILENAME_PREFIX = "recording";
37
38    private static final ReadOnlyLogFileFilter sUploadableLogFileFilter =
39            new ReadOnlyLogFileFilter();
40
41    private final File mFilesDir;
42
43    static class ReadOnlyLogFileFilter implements FileFilter {
44        @Override
45        public boolean accept(final File pathname) {
46            return pathname.getName().startsWith(ResearchLogDirectory.LOG_FILENAME_PREFIX)
47                    && !pathname.canWrite();
48        }
49    }
50
51    /**
52     * Creates a new ResearchLogDirectory, creating the storage directory if it does not exist.
53     */
54    public ResearchLogDirectory(final Context context) {
55        mFilesDir = getLoggingDirectory(context);
56        if (mFilesDir == null) {
57            throw new NullPointerException("No files directory specified");
58        }
59        if (!mFilesDir.exists()) {
60            mFilesDir.mkdirs();
61        }
62    }
63
64    private File getLoggingDirectory(final Context context) {
65        // TODO: Switch to using a subdirectory of getFilesDir().
66        return context.getFilesDir();
67    }
68
69    /**
70     * Get an array of log files that are ready for uploading.
71     *
72     * A file is ready for uploading if it is marked as read-only.
73     *
74     * @return the array of uploadable files
75     */
76    public File[] getUploadableLogFiles() {
77        try {
78            return mFilesDir.listFiles(sUploadableLogFileFilter);
79        } catch (final SecurityException e) {
80            Log.e(TAG, "Could not cleanup log directory, permission denied", e);
81            return new File[0];
82        }
83    }
84
85    public void cleanupLogFilesOlderThan(final long time) {
86        try {
87            for (final File file : mFilesDir.listFiles()) {
88                final String filename = file.getName();
89                if ((filename.startsWith(LOG_FILENAME_PREFIX)
90                        || filename.startsWith(USER_RECORDING_FILENAME_PREFIX))
91                        && (file.lastModified() < time)) {
92                    file.delete();
93                }
94            }
95        } catch (final SecurityException e) {
96            Log.e(TAG, "Could not cleanup log directory, permission denied", e);
97        }
98    }
99
100    public File getLogFilePath(final long time, final long nanoTime) {
101        return new File(mFilesDir, getUniqueFilename(LOG_FILENAME_PREFIX, time, nanoTime));
102    }
103
104    public File getUserRecordingFilePath(final long time, final long nanoTime) {
105        return new File(mFilesDir, getUniqueFilename(USER_RECORDING_FILENAME_PREFIX, time,
106                nanoTime));
107    }
108
109    private static String getUniqueFilename(final String prefix, final long time,
110            final long nanoTime) {
111        return prefix + "-" + time + "-" + nanoTime + FILENAME_SUFFIX;
112    }
113}
114