Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 516e13f8 authored by Dmitri Plotnikov's avatar Dmitri Plotnikov
Browse files

Add a persistent log to facilitate debugging of battery history issues

Bug: 407828438
Test: presubmit
Flag: EXEMPT refactor
Change-Id: Id35f7ba3bd08654848afd119458b1a4d00d0f47f
parent d633dcc1
Loading
Loading
Loading
Loading
+65 −0
Original line number Diff line number Diff line
@@ -38,12 +38,17 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
import android.util.ArraySet;
import android.util.Log;
import android.util.LogWriter;
import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
@@ -369,6 +374,10 @@ public class BatteryStatsHistory {
    private int mIteratorCookie;
    private final BatteryStatsHistory mWritableHistory;

    // Enable this locally in order to collect the persistent log generated by `debugLog` calls
    private static final boolean DEBUG_LOG_ENABLED = false;
    private static final String DEBUG_LOG_FILE = "/data/system/battery-history/debuglog.txt";

    /**
     * A delegate for android.os.Trace to allow testing static calls. Due to
     * limitations in Android Tracing (b/153319140), the delegate also records
@@ -628,6 +637,9 @@ public class BatteryStatsHistory {
     */
    public void reset() {
        synchronized (this) {
            // The file is optional. If missing, the call is a no-op
            new File(DEBUG_LOG_FILE).delete();

            mMonotonicHistorySize = 0;
            initHistoryBuffer();
            if (mStore != null) {
@@ -1912,6 +1924,10 @@ public class BatteryStatsHistory {
        int deltaTimeToken;
        if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
            deltaTimeToken = BatteryStatsHistory.DELTA_TIME_LONG;
            if (DEBUG_LOG_ENABLED) {
                // Negative or excessively large time deltas are unexpected.
                debugLog(cur, last, "Unexpected time delta: " + deltaTime, true);
            }
        } else if (deltaTime >= BatteryStatsHistory.DELTA_TIME_ABS) {
            deltaTimeToken = BatteryStatsHistory.DELTA_TIME_INT;
        } else {
@@ -2452,4 +2468,53 @@ public class BatteryStatsHistory {
            }
        }
    }

    private long mDebugLogBaseTimeUtc;
    private long mDebugLogBaseMonotonicTime;

    /**
     * Logs a detailed message to {@link #DEBUG_LOG_FILE}. This should only be enabled
     * on a local built with the purposes of researching battery history issues.
     */
    private void debugLog(HistoryItem item, HistoryItem last, String message,
            boolean includeStack) {
        if (!DEBUG_LOG_ENABLED) {
            return;
        }

        PrintWriter logWriter;
        try {
            logWriter = new PrintWriter(
                    new FileOutputStream(DEBUG_LOG_FILE, /* append */ true));
        } catch (IOException e) {
            Slog.e(TAG, "Cannot create debug log file");
            logWriter = new PrintWriter(new LogWriter(Log.DEBUG, TAG));
        }

        if (mDebugLogBaseTimeUtc == 0) {
            mDebugLogBaseTimeUtc = mClock.currentTimeMillis();
            mDebugLogBaseMonotonicTime = mMonotonicClock.monotonicTime();
        }

        BatteryStats.HistoryPrinter historyPrinter = new BatteryStats.HistoryPrinter();

        long currentTimeSaved = last.currentTime;
        last.currentTime = mDebugLogBaseTimeUtc + (last.time - mDebugLogBaseMonotonicTime);
        historyPrinter.printNextItem(logWriter, last, 0, false, true);
        last.currentTime = currentTimeSaved;

        currentTimeSaved = item.currentTime;
        item.currentTime = mDebugLogBaseTimeUtc + (item.time - mDebugLogBaseMonotonicTime);
        historyPrinter.printNextItem(logWriter, item, 0, false, true);
        item.currentTime = currentTimeSaved;

        logWriter.println("    " + message);

        if (includeStack) {
            new Exception("Stack trace").printStackTrace(logWriter);
        }

        logWriter.println();
        logWriter.close();
    }
}