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 17 package com.android.inputmethod.research; 18 19 import android.content.Context; 20 import android.util.Log; 21 22 import java.io.File; 23 import 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 */ 32 public 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