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

Commit 2f73ecdf authored by Kweku Adams's avatar Kweku Adams
Browse files

Adding initial protos for batterystats dump.

Timer is the basic stat tracking object that's used for a lot of the
data in batterystats.
ControllerActivity data is tracked both per uid and for the entire
system, so it makes sense to define it now independently.
For the BatteryStatsHelper change: there's a small window of time after
boot where getSystemService will return null. I ran into it.

BUG: 65750808
Test: flash device and check incident proto output
Change-Id: I15e7d046a43f76d5f53d05b5138ea40f42e19d59
parent 11c41f7c
Loading
Loading
Loading
Loading
+96 −8
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.os;
import android.app.job.JobParameters;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.service.batterystats.BatteryStatsServiceDumpProto;
import android.telephony.SignalStrength;
import android.text.format.DateFormat;
import android.util.ArrayMap;
@@ -29,11 +30,13 @@ import android.util.Printer;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.view.Display;

import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
@@ -220,7 +223,7 @@ public abstract class BatteryStats implements Parcelable {
     * New in version 27:
     *   - Always On Display (screen doze mode) time and power
     */
    static final String CHECKIN_VERSION = "27";
    static final int CHECKIN_VERSION = 27;

    /**
     * Old version, we hit 9 and ran out of room, need to remove.
@@ -2987,6 +2990,31 @@ public abstract class BatteryStats implements Parcelable {
        }
    }

    /**
     * Dump a given timer stat to the proto stream.
     *
     * @param proto the ProtoOutputStream to log to
     * @param fieldId type of data, the field to save to (e.g. AggregatedBatteryStats.WAKELOCK)
     * @param timer a {@link Timer} to dump stats for
     * @param rawRealtimeUs the current elapsed realtime of the system in microseconds
     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT
     */
    private static void dumpTimer(ProtoOutputStream proto, long fieldId,
                                        Timer timer, long rawRealtime, int which) {
        if (timer == null) {
            return;
        }
        // Convert from microseconds to milliseconds with rounding
        final long totalTimeMs = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
        final int count = timer.getCountLocked(which);
        if (totalTimeMs != 0 || count != 0) {
            final long token = proto.start(fieldId);
            proto.write(TimerProto.DURATION_MS, totalTimeMs);
            proto.write(TimerProto.COUNT, count);
            proto.end(token);
        }
    }

    /**
     * Checks if the ControllerActivityCounter has any data worth dumping.
     */
@@ -3039,6 +3067,38 @@ public abstract class BatteryStats implements Parcelable {
        pw.println();
    }

    /**
     * Dumps the ControllerActivityCounter if it has any data worth dumping.
     */
    private static void dumpControllerActivityProto(ProtoOutputStream proto, long fieldId,
                                                    ControllerActivityCounter counter,
                                                    int which) {
        if (!controllerActivityHasData(counter, which)) {
            return;
        }

        final long cToken = proto.start(fieldId);

        proto.write(ControllerActivityProto.IDLE_DURATION_MS,
                counter.getIdleTimeCounter().getCountLocked(which));
        proto.write(ControllerActivityProto.RX_DURATION_MS,
                counter.getRxTimeCounter().getCountLocked(which));
        proto.write(ControllerActivityProto.POWER_MAH,
                counter.getPowerCounter().getCountLocked(which) / (1000 * 60 * 60));

        long tToken;
        LongCounter[] txCounters = counter.getTxTimeCounters();
        for (int i = 0; i < txCounters.length; ++i) {
            LongCounter c = txCounters[i];
            tToken = proto.start(ControllerActivityProto.TX);
            proto.write(ControllerActivityProto.TxLevel.LEVEL, i);
            proto.write(ControllerActivityProto.TxLevel.DURATION_MS, c.getCountLocked(which));
            proto.end(tToken);
        }

        proto.end(cToken);
    }

    private final void printControllerActivityIfInteresting(PrintWriter pw, StringBuilder sb,
                                                            String prefix, String controllerName,
                                                            ControllerActivityCounter counter,
@@ -5491,6 +5551,7 @@ public abstract class BatteryStats implements Parcelable {
    }

    public void prepareForDumpLocked() {
        // We don't need to require subclasses implement this.
    }

    public static class HistoryPrinter {
@@ -6312,6 +6373,7 @@ public abstract class BatteryStats implements Parcelable {
        }
    }

    // This is called from BatteryStatsService.
    @SuppressWarnings("unused")
    public void dumpCheckinLocked(Context context, PrintWriter pw,
            List<ApplicationInfo> apps, int flags, long histStart) {
@@ -6323,10 +6385,7 @@ public abstract class BatteryStats implements Parcelable {

        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();

        final boolean filtering = (flags &
                (DUMP_HISTORY_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0;

        if ((flags&DUMP_INCLUDE_HISTORY) != 0 || (flags&DUMP_HISTORY_ONLY) != 0) {
        if ((flags & (DUMP_INCLUDE_HISTORY | DUMP_HISTORY_ONLY)) != 0) {
            if (startIteratingHistoryLocked()) {
                try {
                    for (int i=0; i<getHistoryStringPoolSize(); i++) {
@@ -6350,7 +6409,7 @@ public abstract class BatteryStats implements Parcelable {
            }
        }

        if (filtering && (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) {
        if ((flags & DUMP_HISTORY_ONLY) != 0) {
            return;
        }

@@ -6383,7 +6442,7 @@ public abstract class BatteryStats implements Parcelable {
                }
            }
        }
        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
        if ((flags & DUMP_DAILY_ONLY) == 0) {
            dumpDurationSteps(pw, "", DISCHARGE_STEP_DATA, getDischargeLevelStepTracker(), true);
            String[] lineArgs = new String[1];
            long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime() * 1000);
@@ -6403,4 +6462,33 @@ public abstract class BatteryStats implements Parcelable {
                    (flags&DUMP_DEVICE_WIFI_ONLY) != 0);
        }
    }

    /** Dump batterystats data to a proto. @hide */
    public void dumpProtoLocked(Context context, FileDescriptor fd, List<ApplicationInfo> apps,
            int flags, long historyStart) {
        final ProtoOutputStream proto = new ProtoOutputStream(fd);
        final long bToken = proto.start(BatteryStatsServiceDumpProto.BATTERYSTATS);
        prepareForDumpLocked();

        proto.write(BatteryStatsProto.REPORT_VERSION, CHECKIN_VERSION);
        proto.write(BatteryStatsProto.PARCEL_VERSION, getParcelVersion());
        proto.write(BatteryStatsProto.START_PLATFORM_VERSION, getStartPlatformVersion());
        proto.write(BatteryStatsProto.END_PLATFORM_VERSION, getEndPlatformVersion());

        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();

        if ((flags & (DUMP_INCLUDE_HISTORY | DUMP_HISTORY_ONLY)) != 0) {
            if (startIteratingHistoryLocked()) {
                // TODO: implement dumpProtoHistoryLocked(proto);
            }
        }

        if ((flags & (DUMP_HISTORY_ONLY | DUMP_DAILY_ONLY)) == 0) {
            // TODO: implement dumpProtoAppsLocked(proto, apps);
            // TODO: implement dumpProtoSystemLocked(proto);
        }

        proto.end(bToken);
        proto.flush();
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -143,6 +143,9 @@ public class BatteryStatsHelper {
    public static boolean checkWifiOnly(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(
                Context.CONNECTIVITY_SERVICE);
        if (cm == null) {
            return false;
        }
        return !cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
    }

+69 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source 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.
 */

syntax = "proto3";

option java_multiple_files = true;

package android.os;

message BatteryStatsProto {
  int32 report_version = 1;
  int64 parcel_version = 2;
  string start_platform_version = 3;
  string end_platform_version = 4;
  BatteryHistoryProto history = 5;
  repeated UidProto uids = 6;
  SystemProto system = 7;
}

message BatteryHistoryProto {
}

message ControllerActivityProto {
  // Time (milliseconds) spent in the idle state.
  int64 idle_duration_ms = 1;
  // Time (milliseconds) spent in the receive state.
  int64 rx_duration_ms = 2;
  // Total power (mAh) consumed by the controller in all states. The value may
  // always be 0 if the device doesn't support power calculations.
  int64 power_mah = 3;

  // Represents a transmit level, where each level may draw a different amount
  // of power. The levels themselves are controller-specific (and may possibly
  // be device specific...yet to be confirmed).
  message TxLevel {
    // Transmit level. Higher levels draw more power.
    int32 level = 1;
    // Time spent in this specific transmit level state.
    int64 duration_ms = 2;
  }
  repeated TxLevel tx = 4;
}

message SystemProto {
}

message TimerProto {
  int64 duration_ms = 1;
  int64 count = 2;
}

message UidProto {
  // Combination of app ID and user ID.
  int32 uid = 1;
  repeated string package_names = 2;
}
+6 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import "frameworks/base/libs/incident/proto/android/privacy.proto";
import "frameworks/base/libs/incident/proto/android/section.proto";
import "frameworks/base/core/proto/android/service/appwidget.proto";
import "frameworks/base/core/proto/android/service/battery.proto";
import "frameworks/base/core/proto/android/service/batterystats.proto";
import "frameworks/base/core/proto/android/service/fingerprint.proto";
import "frameworks/base/core/proto/android/service/diskstats.proto";
import "frameworks/base/core/proto/android/service/netstats.proto";
@@ -84,6 +85,11 @@ message IncidentProto {
        (section).args = "notification --proto"
    ];

    android.service.batterystats.BatteryStatsServiceDumpProto batterystats = 3005 [
        (section).type = SECTION_DUMPSYS,
        (section).args = "batterystats --proto"
    ];

    android.service.battery.BatteryServiceDumpProto battery = 3006 [
        (section).type = SECTION_DUMPSYS,
        (section).args = "battery --proto"
+28 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source 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.
 */

syntax = "proto3";

package android.service.batterystats;

option java_multiple_files = true;
option java_outer_classname = "BatteryStatsServiceProto";

import "frameworks/base/core/proto/android/os/batterystats.proto";

message BatteryStatsServiceDumpProto {
  android.os.BatteryStatsProto batterystats = 1;
}
Loading