diff options
-rw-r--r-- | java/com/android/dialer/persistentlog/PersistentLogFileHandler.java | 61 | ||||
-rw-r--r-- | java/com/android/dialer/persistentlog/PersistentLogger.java | 10 |
2 files changed, 69 insertions, 2 deletions
diff --git a/java/com/android/dialer/persistentlog/PersistentLogFileHandler.java b/java/com/android/dialer/persistentlog/PersistentLogFileHandler.java index 5c7a28c5b..8bd8335a2 100644 --- a/java/com/android/dialer/persistentlog/PersistentLogFileHandler.java +++ b/java/com/android/dialer/persistentlog/PersistentLogFileHandler.java @@ -27,6 +27,7 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.WorkerThread; import android.support.v4.os.UserManagerCompat; +import com.android.dialer.common.LogUtil; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -58,6 +59,16 @@ final class PersistentLogFileHandler { private static final String LOG_DIRECTORY = "persistent_log"; private static final String NEXT_FILE_INDEX_PREFIX = "persistent_long_next_file_index_"; + private static final byte[] ENTRY_PREFIX = {'P'}; + private static final byte[] ENTRY_POSTFIX = {'L'}; + + private static class LogCorruptionException extends Exception { + + public LogCorruptionException(String message) { + super(message); + } + }; + private File logDirectory; private final String subfolder; private final int fileSizeLimit; @@ -106,8 +117,10 @@ final class PersistentLogFileHandler { try (DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(outputFile, true))) { for (byte[] log : logs) { + outputStream.write(ENTRY_PREFIX); outputStream.writeInt(log.length); outputStream.write(log); + outputStream.write(ENTRY_POSTFIX); } outputStream.close(); if (outputFile.length() > fileSizeLimit) { @@ -116,6 +129,21 @@ final class PersistentLogFileHandler { } } + void writeRawLogsForTest(byte[] data) throws IOException { + if (outputFile == null) { + selectNextFileToWrite(); + } + outputFile.createNewFile(); + try (DataOutputStream outputStream = + new DataOutputStream(new FileOutputStream(outputFile, true))) { + outputStream.write(data); + outputStream.close(); + if (outputFile.length() > fileSizeLimit) { + selectNextFileToWrite(); + } + } + } + /** Concatenate all log files in chronicle order and return a byte array. */ @WorkerThread @NonNull @@ -149,10 +177,21 @@ final class PersistentLogFileHandler { logs.add(log); log = readLog(input); } + } catch (LogCorruptionException e) { + LogUtil.e("PersistentLogFileHandler.getLogs", "logs corrupted, deleting", e); + deleteLogs(); + return new ArrayList<>(); } return logs; } + private void deleteLogs() throws IOException { + for (File file : getLogFiles()) { + file.delete(); + } + selectNextFileToWrite(); + } + @WorkerThread private void selectNextFileToWrite() throws IOException { File[] files = getLogFiles(); @@ -186,10 +225,28 @@ final class PersistentLogFileHandler { @Nullable @WorkerThread - private static byte[] readLog(DataInputStream inputStream) throws IOException { + private byte[] readLog(DataInputStream inputStream) throws IOException, LogCorruptionException { try { - byte[] data = new byte[inputStream.readInt()]; + byte[] prefix = new byte[ENTRY_PREFIX.length]; + if (inputStream.read(prefix) == -1) { + // EOF + return null; + } + if (!Arrays.equals(prefix, ENTRY_PREFIX)) { + throw new LogCorruptionException("entry prefix mismatch"); + } + int dataLength = inputStream.readInt(); + if (dataLength > fileSizeLimit) { + throw new LogCorruptionException("data length over max size"); + } + byte[] data = new byte[dataLength]; inputStream.read(data); + + byte[] postfix = new byte[ENTRY_POSTFIX.length]; + inputStream.read(postfix); + if (!Arrays.equals(postfix, ENTRY_POSTFIX)) { + throw new LogCorruptionException("entry postfix mismatch"); + } return data; } catch (EOFException e) { return null; diff --git a/java/com/android/dialer/persistentlog/PersistentLogger.java b/java/com/android/dialer/persistentlog/PersistentLogger.java index 7d82ec1a1..847625ec5 100644 --- a/java/com/android/dialer/persistentlog/PersistentLogger.java +++ b/java/com/android/dialer/persistentlog/PersistentLogger.java @@ -110,6 +110,16 @@ public final class PersistentLogger { loggerThreadHandler.sendEmptyMessageDelayed(MESSAGE_FLUSH, FLUSH_DELAY_MILLIS); } + @VisibleForTesting + /** write raw bytes directly to the log file, likely corrupting it. */ + static void rawLogForTest(byte[] data) { + try { + fileHandler.writeRawLogsForTest(data); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + /** Dump the log as human readable string. Blocks until the dump is finished. */ @NonNull @WorkerThread |