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

Commit 9835370d authored by Dmitri Plotnikov's avatar Dmitri Plotnikov
Browse files

Consistently close BatteryUsageStats objects

Bug: 371614748
Test: atest PowerStatsTests; atest PowerStatsTestRavenwood
Flag: EXEMPT_bugfix

Change-Id: Ibdd49c3dccb899330d6bd05c311669cac281fb06
parent 3b204907
Loading
Loading
Loading
Loading
+61 −1
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ import android.util.Range;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BatteryStatsHistory;
import com.android.internal.os.BatteryStatsHistoryIterator;
import com.android.internal.os.MonotonicClock;
@@ -43,7 +45,9 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Contains a snapshot of battery attribution data, on a per-subsystem and per-UID basis.
@@ -126,6 +130,12 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
    // Max window size. CursorWindow uses only as much memory as needed.
    private static final long BATTERY_CONSUMER_CURSOR_WINDOW_SIZE = 20_000_000; // bytes

    /**
     * Used by tests to ensure all BatteryUsageStats instances are closed.
     */
    @VisibleForTesting
    public static boolean DEBUG_INSTANCE_COUNT;

    private static final int STATSD_PULL_ATOM_MAX_BYTES = 45000;

    private static final int[] UID_USAGE_TIME_PROCESS_STATES = {
@@ -153,7 +163,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
    private final List<UserBatteryConsumer> mUserBatteryConsumers;
    private final AggregateBatteryConsumer[] mAggregateBatteryConsumers;
    private final BatteryStatsHistory mBatteryStatsHistory;
    private BatteryConsumer.BatteryConsumerDataLayout mBatteryConsumerDataLayout;
    private final BatteryConsumer.BatteryConsumerDataLayout mBatteryConsumerDataLayout;
    private CursorWindow mBatteryConsumersCursorWindow;

    private BatteryUsageStats(@NonNull Builder builder) {
@@ -873,6 +883,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable {

    @Override
    public void close() throws IOException {
        onCursorWindowReleased(mBatteryConsumersCursorWindow);
        mBatteryConsumersCursorWindow.close();
        mBatteryConsumersCursorWindow = null;
    }
@@ -880,6 +891,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
    @Override
    protected void finalize() throws Throwable {
        if (mBatteryConsumersCursorWindow != null) {
            // Do not decrement sOpenCusorWindowCount. All instances should be closed explicitly
            mBatteryConsumersCursorWindow.close();
        }
        super.finalize();
@@ -934,6 +946,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
                boolean includesPowerStateData, double minConsumedPowerThreshold) {
            mBatteryConsumersCursorWindow =
                    new CursorWindow(null, BATTERY_CONSUMER_CURSOR_WINDOW_SIZE);
            onCursorWindowAllocated(mBatteryConsumersCursorWindow);
            mBatteryConsumerDataLayout = BatteryConsumer.createBatteryConsumerDataLayout(
                    customPowerComponentNames, includePowerModels, includeProcessStateData,
                    includeScreenStateData, includesPowerStateData);
@@ -996,6 +1009,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
         */
        public void discard() {
            mBatteryConsumersCursorWindow.close();
            onCursorWindowReleased(mBatteryConsumersCursorWindow);
        }

        /**
@@ -1264,4 +1278,50 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
            }
        }
    }

    @GuardedBy("BatteryUsageStats.class")
    private static Map<CursorWindow, Exception> sInstances;

    private static void onCursorWindowAllocated(CursorWindow window) {
        if (!DEBUG_INSTANCE_COUNT) {
            return;
        }

        synchronized (BatteryUsageStats.class) {
            if (sInstances == null) {
                sInstances = new HashMap<>();
            }
            sInstances.put(window, new Exception());
        }
    }

    private static void onCursorWindowReleased(CursorWindow window) {
        if (!DEBUG_INSTANCE_COUNT) {
            return;
        }

        synchronized (BatteryUsageStats.class) {
            sInstances.remove(window);
        }
    }

    /**
     * Used by tests to ensure all BatteryUsageStats instances are closed.
     */
    @VisibleForTesting
    public static void assertAllInstancesClosed() {
        if (!DEBUG_INSTANCE_COUNT) {
            throw new IllegalStateException("DEBUG_INSTANCE_COUNT is false");
        }

        synchronized (BatteryUsageStats.class) {
            if (!sInstances.isEmpty()) {
                Exception callSite = sInstances.entrySet().iterator().next().getValue();
                int count = sInstances.size();
                sInstances.clear();
                throw new IllegalStateException(
                        "Instances of BatteryUsageStats not closed: " + count, callSite);
            }
        }
    }
}
+9 −6
Original line number Diff line number Diff line
@@ -3178,13 +3178,16 @@ public final class BatteryStatsService extends IBatteryStats.Stub
            mStats.collectPowerStatsSamples();
        }

        BatteryUsageStats batteryUsageStats =
                mBatteryUsageStatsProvider.getBatteryUsageStats(mStats, query);
        try (BatteryUsageStats batteryUsageStats =
                     mBatteryUsageStatsProvider.getBatteryUsageStats(mStats, query)) {
            if (proto) {
                batteryUsageStats.dumpToProto(fd);
            } else {
                batteryUsageStats.dump(pw, "  ");
            }
        } catch (IOException e) {
            Slog.e(TAG, "Cannot close BatteryUsageStats", e);
        }
    }

    private int doEnableOrDisable(PrintWriter pw, int i, String[] args, boolean enable) {
+5 −0
Original line number Diff line number Diff line
@@ -51,6 +51,11 @@ class AccumulatedBatteryUsageStatsSection extends PowerStatsSpan.Section {
        mBatteryUsageStats.build().dump(ipw, "");
    }

    @Override
    public void close() {
        mBatteryUsageStats.discard();
    }

    static class Reader implements PowerStatsSpan.SectionReader {
        @Override
        public String getType() {
+22 −20
Original line number Diff line number Diff line
@@ -295,7 +295,8 @@ public class BatteryUsageStatsProvider {
                    stats.builder = ((AccumulatedBatteryUsageStatsSection) section)
                            .getBatteryUsageStatsBuilder();
                    stats.startWallClockTime = powerStatsSpan.getMetadata().getStartTime();
                    stats.startMonotonicTime = powerStatsSpan.getMetadata().getStartMonotonicTime();
                    stats.startMonotonicTime =
                            powerStatsSpan.getMetadata().getStartMonotonicTime();
                    stats.endMonotonicTime = powerStatsSpan.getMetadata().getEndMonotonicTime();
                    break;
                }
@@ -484,8 +485,8 @@ public class BatteryUsageStatsProvider {
                continue;
            }

            PowerStatsSpan powerStatsSpan = mPowerStatsStore.loadPowerStatsSpan(
                    spanMetadata.getId(), BatteryUsageStatsSection.TYPE);
            try (PowerStatsSpan powerStatsSpan = mPowerStatsStore.loadPowerStatsSpan(
                    spanMetadata.getId(), BatteryUsageStatsSection.TYPE)) {
                if (powerStatsSpan == null) {
                    continue;
                }
@@ -509,6 +510,7 @@ public class BatteryUsageStatsProvider {
                    builder.add(snapshot);
                }
            }
        }
        return builder.build();
    }
}
+11 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.power.stats;

import android.os.BatteryUsageStats;
import android.util.IndentingPrintWriter;
import android.util.Slog;

import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
@@ -28,6 +29,7 @@ import java.io.IOException;

class BatteryUsageStatsSection extends PowerStatsSpan.Section {
    public static final String TYPE = "battery-usage-stats";
    private static final String TAG = "BatteryUsageStatsSection";

    private final BatteryUsageStats mBatteryUsageStats;

@@ -50,6 +52,15 @@ class BatteryUsageStatsSection extends PowerStatsSpan.Section {
        mBatteryUsageStats.dump(ipw, "");
    }

    @Override
    public void close() {
        try {
            mBatteryUsageStats.close();
        } catch (IOException e) {
            Slog.e(TAG, "Closing BatteryUsageStats", e);
        }
    }

    static class Reader implements PowerStatsSpan.SectionReader {
        @Override
        public String getType() {
Loading