Dialer: Remove persistent logger
* We don't use it
* Simulator: crashed on sharing anyway
* Generally not worth keeping
Change-Id: I5bd966b84997405dc884e7c6b800002770bbe1b7
diff --git a/java/com/android/dialer/binary/common/DialerApplication.java b/java/com/android/dialer/binary/common/DialerApplication.java
index 33164ae..69db1f9 100644
--- a/java/com/android/dialer/binary/common/DialerApplication.java
+++ b/java/com/android/dialer/binary/common/DialerApplication.java
@@ -23,7 +23,6 @@
import com.android.dialer.inject.HasRootComponent;
import com.android.dialer.notification.NotificationChannelManager;
-import com.android.dialer.persistentlog.PersistentLogger;
/** A common application subclass for all Dialer build variants. */
public abstract class DialerApplication extends Application implements HasRootComponent {
@@ -34,7 +33,6 @@
public void onCreate() {
Trace.beginSection("DialerApplication.onCreate");
super.onCreate();
- PersistentLogger.initialize(this);
NotificationChannelManager.initChannels(this);
Trace.endSection();
}
diff --git a/java/com/android/dialer/persistentlog/PersistentLogFileHandler.java b/java/com/android/dialer/persistentlog/PersistentLogFileHandler.java
deleted file mode 100644
index be9bd71..0000000
--- a/java/com/android/dialer/persistentlog/PersistentLogFileHandler.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- * Copyright (C) 2023 The LineageOS Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.dialer.persistentlog;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-
-import androidx.annotation.AnyThread;
-import androidx.annotation.MainThread;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.WorkerThread;
-import androidx.core.os.UserManagerCompat;
-import androidx.preference.PreferenceManager;
-
-import com.android.dialer.common.LogUtil;
-
-import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.EOFException;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
-
-/**
- * Handles serialization of byte arrays and read/write them to multiple rotating files. If a logText
- * file exceeds {@code fileSizeLimit} after a write, a new file will be used. if the total number of
- * files exceeds {@code fileCountLimit} the oldest ones will be deleted. The logs are stored in the
- * cache but the file index is stored in the data (clearing data will also clear the cache). The
- * logs will be stored under /cache_dir/persistent_log/{@code subfolder}, so multiple independent
- * logs can be created.
- *
- * <p>This class is NOT thread safe. All methods expect the constructor must be called on the same
- * worker thread.
- */
-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;
- private final int fileCountLimit;
-
- private SharedPreferences sharedPreferences;
-
- private File outputFile;
- private Context context;
-
- @MainThread
- PersistentLogFileHandler(String subfolder, int fileSizeLimit, int fileCountLimit) {
- this.subfolder = subfolder;
- this.fileSizeLimit = fileSizeLimit;
- this.fileCountLimit = fileCountLimit;
- }
-
- /** Must be called right after the logger thread is created. */
- @WorkerThread
- void initialize(Context context) {
- this.context = context;
- logDirectory = new File(new File(context.getCacheDir(), LOG_DIRECTORY), subfolder);
- initializeSharedPreference(context);
- }
-
- @WorkerThread
- private boolean initializeSharedPreference(Context context) {
- if (sharedPreferences == null && UserManagerCompat.isUserUnlocked(context)) {
- sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
- return true;
- }
- return sharedPreferences != null;
- }
-
- /**
- * Write the list of byte arrays to the current log file, prefixing each entry with its' length. A
- * new file will only be selected when the batch is completed, so the resulting file might be
- * larger then {@code fileSizeLimit}
- */
- @WorkerThread
- void writeLogs(List<byte[]> logs) throws IOException {
- if (outputFile == null) {
- selectNextFileToWrite();
- }
- outputFile.createNewFile();
- 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) {
- selectNextFileToWrite();
- }
- }
- }
-
- /** Concatenate all log files in chronicle order and return a byte array. */
- @WorkerThread
- @NonNull
- private byte[] readBlob() throws IOException {
- File[] files = getLogFiles();
-
- ByteBuffer byteBuffer = ByteBuffer.allocate(getTotalSize(files));
- for (File file : files) {
- byteBuffer.put(readAllBytes(file));
- }
- return byteBuffer.array();
- }
-
- private static int getTotalSize(File[] files) {
- int sum = 0;
- for (File file : files) {
- sum += (int) file.length();
- }
- return sum;
- }
-
- /** Parses the content of all files back to individual byte arrays. */
- @WorkerThread
- @NonNull
- List<byte[]> getLogs() throws IOException {
- byte[] blob = readBlob();
- List<byte[]> logs = new ArrayList<>();
- try (DataInputStream input = new DataInputStream(new ByteArrayInputStream(blob))) {
- byte[] log = readLog(input);
- while (log != null) {
- 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();
-
- if (files.length == 0 || files[files.length - 1].length() > fileSizeLimit) {
- if (files.length >= fileCountLimit) {
- for (int i = 0; i <= files.length - fileCountLimit; i++) {
- files[i].delete();
- }
- }
- outputFile = new File(logDirectory, String.valueOf(getAndIncrementNextFileIndex()));
- } else {
- outputFile = files[files.length - 1];
- }
- }
-
- @NonNull
- @WorkerThread
- private File[] getLogFiles() {
- logDirectory.mkdirs();
- File[] files = logDirectory.listFiles();
- if (files == null) {
- files = new File[0];
- }
- Arrays.sort(files, Comparator.comparingLong((File lhs) -> Long.valueOf(lhs.getName())));
- return files;
- }
-
- @Nullable
- @WorkerThread
- private byte[] readLog(DataInputStream inputStream) throws IOException, LogCorruptionException {
- try {
- 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;
- }
- }
-
- @NonNull
- @WorkerThread
- private static byte[] readAllBytes(File file) throws IOException {
- byte[] result = new byte[(int) file.length()];
- try (RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r")) {
- randomAccessFile.readFully(result);
- }
- return result;
- }
-
- @WorkerThread
- private int getAndIncrementNextFileIndex() throws IOException {
- if (!initializeSharedPreference(context)) {
- throw new IOException("Shared preference is not available");
- }
-
- int index = sharedPreferences.getInt(getNextFileKey(), 0);
- sharedPreferences.edit().putInt(getNextFileKey(), index + 1).commit();
- return index;
- }
-
- @AnyThread
- private String getNextFileKey() {
- return NEXT_FILE_INDEX_PREFIX + subfolder;
- }
-}
diff --git a/java/com/android/dialer/persistentlog/PersistentLogger.java b/java/com/android/dialer/persistentlog/PersistentLogger.java
deleted file mode 100644
index 9517d75..0000000
--- a/java/com/android/dialer/persistentlog/PersistentLogger.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- * Copyright (C) 2023 The LineageOS Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.dialer.persistentlog;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.HandlerThread;
-
-import androidx.annotation.AnyThread;
-import androidx.annotation.NonNull;
-import androidx.annotation.WorkerThread;
-import androidx.core.os.UserManagerCompat;
-
-import com.android.dialer.common.Assert;
-import com.android.dialer.common.LogUtil;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.LinkedBlockingQueue;
-
-/**
- * Logs data that is persisted across app termination and device reboot. The logs are stored as
- * rolling files in cache with a limit of {@link #LOG_FILE_SIZE_LIMIT} * {@link
- * #LOG_FILE_COUNT_LIMIT}. The log writing is batched and there is a {@link #FLUSH_DELAY_MILLIS}
- * delay before the logs are committed to disk to avoid excessive IO. If the app is terminated
- * before the logs are committed it will be lost. {@link
- * com.google.android.apps.dialer.crashreporter.SilentCrashReporter} is expected to handle such
- * cases.
- *
- * <p>{@link #logText(String, String)} should be used to log ad-hoc text logs. TODO(twyen): switch
- * to structured logging
- */
-public final class PersistentLogger {
-
- private static final int FLUSH_DELAY_MILLIS = 200;
- private static final String LOG_FOLDER = "plain_text";
- private static final int MESSAGE_FLUSH = 1;
-
- private static final int LOG_FILE_SIZE_LIMIT = 64 * 1024;
- private static final int LOG_FILE_COUNT_LIMIT = 8;
-
- private static PersistentLogFileHandler fileHandler;
-
- private static HandlerThread loggerThread;
- private static Handler loggerThreadHandler;
-
- private static final LinkedBlockingQueue<byte[]> messageQueue = new LinkedBlockingQueue<>();
-
- private PersistentLogger() {}
-
- public static void initialize(Context context) {
- fileHandler =
- new PersistentLogFileHandler(LOG_FOLDER, LOG_FILE_SIZE_LIMIT, LOG_FILE_COUNT_LIMIT);
- loggerThread = new HandlerThread("PersistentLogger");
- loggerThread.start();
- loggerThreadHandler =
- new Handler(
- loggerThread.getLooper(),
- (message) -> {
- if (message.what == MESSAGE_FLUSH) {
- if (messageQueue.isEmpty()) {
- return true;
- }
- loggerThreadHandler.removeMessages(MESSAGE_FLUSH);
- List<byte[]> messages = new ArrayList<>();
- messageQueue.drainTo(messages);
- if (!UserManagerCompat.isUserUnlocked(context)) {
- return true;
- }
- try {
- fileHandler.writeLogs(messages);
- } catch (IOException e) {
- LogUtil.e("PersistentLogger.MESSAGE_FLUSH", "error writing message", e);
- }
- }
- return true;
- });
- loggerThreadHandler.post(() -> fileHandler.initialize(context));
- }
-
- static HandlerThread getLoggerThread() {
- return loggerThread;
- }
-
- @AnyThread
- public static void logText(String tag, String string) {
- log(buildTextLog(tag, string));
- }
-
- @AnyThread
- static void log(byte[] data) {
- messageQueue.add(data);
- loggerThreadHandler.sendEmptyMessageDelayed(MESSAGE_FLUSH, FLUSH_DELAY_MILLIS);
- }
-
- /** Dump the log as human readable string. Blocks until the dump is finished. */
- @NonNull
- @WorkerThread
- public static String dumpLogToString() {
- Assert.isWorkerThread();
- DumpStringRunnable dumpStringRunnable = new DumpStringRunnable();
- loggerThreadHandler.post(dumpStringRunnable);
- try {
- return dumpStringRunnable.get();
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- return "Cannot dump logText: " + e;
- }
- }
-
- private static class DumpStringRunnable implements Runnable {
- private String result;
- private final CountDownLatch latch = new CountDownLatch(1);
-
- @Override
- public void run() {
- result = dumpLogToStringInternal();
- latch.countDown();
- }
-
- public String get() throws InterruptedException {
- latch.await();
- return result;
- }
- }
-
- @NonNull
- @WorkerThread
- private static String dumpLogToStringInternal() {
- StringBuilder result = new StringBuilder();
- List<byte[]> logs;
- try {
- logs = readLogs();
- } catch (IOException e) {
- return "Cannot dump logText: " + e;
- }
-
- for (byte[] log : logs) {
- result.append(new String(log, StandardCharsets.UTF_8)).append("\n");
- }
- return result.toString();
- }
-
- @NonNull
- @WorkerThread
- static List<byte[]> readLogs() throws IOException {
- Assert.isWorkerThread();
- return fileHandler.getLogs();
- }
-
- private static byte[] buildTextLog(String tag, String string) {
- Calendar c = Calendar.getInstance();
- return String.format("%tm-%td %tH:%tM:%tS.%tL - %s - %s", c, c, c, c, c, c, tag, string)
- .getBytes(StandardCharsets.UTF_8);
- }
-}
diff --git a/java/com/android/dialer/simulator/impl/SimulatorMainPortal.java b/java/com/android/dialer/simulator/impl/SimulatorMainPortal.java
index 9667f21..caea72a 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorMainPortal.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorMainPortal.java
@@ -104,7 +104,6 @@
.put("Clean database", () -> SimulatorUtils.cleanDatabase(context))
.put("clear preferred SIM", () -> SimulatorUtils.clearPreferredSim(context))
.put("Sync voicemail", () -> SimulatorUtils.syncVoicemail(context))
- .put("Share persistent log", () -> SimulatorUtils.sharePersistentLog(context))
.put(
"Enable simulator mode",
() -> {
diff --git a/java/com/android/dialer/simulator/impl/SimulatorUtils.java b/java/com/android/dialer/simulator/impl/SimulatorUtils.java
index 9bd4578..2f99453 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorUtils.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorUtils.java
@@ -33,7 +33,6 @@
import com.android.dialer.databasepopulator.CallLogPopulator;
import com.android.dialer.databasepopulator.ContactsPopulator;
import com.android.dialer.databasepopulator.VoicemailPopulator;
-import com.android.dialer.persistentlog.PersistentLogger;
import com.android.dialer.preferredsim.PreferredSimFallbackContract;
import java.util.ArrayList;
@@ -107,23 +106,6 @@
context.sendBroadcast(intent);
}
- public static void sharePersistentLog(@NonNull Context context) {
- DialerExecutorComponent.get(context)
- .dialerExecutorFactory()
- .createNonUiTaskBuilder(new ShareLogWorker())
- .onSuccess(
- (String log) -> {
- Intent intent = new Intent(Intent.ACTION_SEND);
- intent.setType("text/plain");
- intent.putExtra(Intent.EXTRA_TEXT, log);
- if (intent.resolveActivity(context.getPackageManager()) != null) {
- context.startActivity(intent);
- }
- })
- .build()
- .executeSerial(null);
- }
-
public static void addVoicemailNotifications(@NonNull Context context, int notificationNum) {
LogUtil.enterBlock("SimulatorNotifications.addVoicemailNotifications");
List<ContentValues> voicemails = new ArrayList<>();
@@ -188,14 +170,6 @@
}
}
- private static class ShareLogWorker implements Worker<Void, String> {
- @Nullable
- @Override
- public String doInBackground(Void unused) {
- return PersistentLogger.dumpLogToString();
- }
- }
-
private static class PopulateDatabaseWorkerInput {
final Context context;
final boolean fastMode;
diff --git a/java/com/android/voicemail/impl/VvmLog.java b/java/com/android/voicemail/impl/VvmLog.java
index 1a7514a..c9e82ac 100644
--- a/java/com/android/voicemail/impl/VvmLog.java
+++ b/java/com/android/voicemail/impl/VvmLog.java
@@ -17,7 +17,6 @@
package com.android.voicemail.impl;
import com.android.dialer.common.LogUtil;
-import com.android.dialer.persistentlog.PersistentLogger;
import com.android.voicemail.impl.utils.IndentingPrintWriter;
import java.io.FileDescriptor;
@@ -34,10 +33,6 @@
private static final LocalLog localLog = new LocalLog(MAX_OMTP_VVM_LOGS);
- public static void log(String tag, String log) {
- PersistentLogger.logText(tag, log);
- }
-
public static void dump(FileDescriptor fd, PrintWriter printwriter, String[] args) {
IndentingPrintWriter indentingPrintWriter = new IndentingPrintWriter(printwriter, " ");
indentingPrintWriter.increaseIndent();
@@ -46,62 +41,50 @@
}
public static void e(String tag, String log) {
- log(tag, log);
LogUtil.e(tag, log);
}
public static void e(String tag, String log, Throwable e) {
- log(tag, log + " " + e);
LogUtil.e(tag, log, e);
}
public static void w(String tag, String log) {
- log(tag, log);
LogUtil.w(tag, log);
}
public static void w(String tag, String log, Throwable e) {
- log(tag, log + " " + e);
LogUtil.w(tag, log, e);
}
public static void i(String tag, String log) {
- log(tag, log);
LogUtil.i(tag, log);
}
public static void i(String tag, String log, Throwable e) {
- log(tag, log + " " + e);
LogUtil.i(tag, log, e);
}
public static void d(String tag, String log) {
- log(tag, log);
LogUtil.d(tag, log);
}
public static void d(String tag, String log, Throwable e) {
- log(tag, log + " " + e);
LogUtil.d(tag, log, e);
}
public static void v(String tag, String log) {
- log(tag, log);
LogUtil.v(tag, log);
}
public static void v(String tag, String log, Throwable e) {
- log(tag, log + " " + e);
LogUtil.v(tag, log, e);
}
public static void wtf(String tag, String log) {
- log(tag, log);
LogUtil.e(tag, log);
}
public static void wtf(String tag, String log, Throwable e) {
- log(tag, log + " " + e);
LogUtil.e(tag, log, e);
}