incidentd: Dumping batterystats system data to proto.

Also a little code cleanup as I was going through to understand the
dumping code.

Bug: 65750808
Test: flash device and inspect incident.proto output
Change-Id: Ib850db408c98d6a96dc028296e96c75087258904
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 9881927..450ced4 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1911,6 +1911,13 @@
             long elapsedRealtimeUs, int which);
 
     /**
+     * Returns the {@link Timer} object that tracks the given screen brightness.
+     *
+     * {@hide}
+     */
+    public abstract Timer getScreenBrightnessTimer(int brightnessBin);
+
+    /**
      * Returns the time in microseconds that power save mode has been enabled while the device was
      * running on battery.
      *
@@ -2019,6 +2026,14 @@
             long elapsedRealtimeUs, int which);
 
     /**
+     * Returns the {@link Timer} object that tracks how much the phone has been trying to
+     * acquire a signal.
+     *
+     * {@hide}
+     */
+    public abstract Timer getPhoneSignalScanningTimer();
+
+    /**
      * Returns the number of times the phone has entered the given signal strength.
      *
      * {@hide}
@@ -2026,6 +2041,12 @@
     public abstract int getPhoneSignalStrengthCount(int strengthBin, int which);
 
     /**
+     * Return the {@link Timer} object used to track the given signal strength's duration and
+     * counts.
+     */
+    protected abstract Timer getPhoneSignalStrengthTimer(int strengthBin);
+
+    /**
      * Returns the time in microseconds that the mobile network has been active
      * (in a high power state).
      *
@@ -2108,6 +2129,11 @@
      */
     public abstract int getPhoneDataConnectionCount(int dataType, int which);
 
+    /**
+     * Returns the {@link Timer} object that tracks the phone's data connection type stats.
+     */
+    public abstract Timer getPhoneDataConnectionTimer(int dataType);
+
     public static final int WIFI_SUPPL_STATE_INVALID = 0;
     public static final int WIFI_SUPPL_STATE_DISCONNECTED = 1;
     public static final int WIFI_SUPPL_STATE_INTERFACE_DISABLED = 2;
@@ -2267,6 +2293,13 @@
     public abstract int getWifiStateCount(int wifiState, int which);
 
     /**
+     * Returns the {@link Timer} object that tracks the given WiFi state.
+     *
+     * {@hide}
+     */
+    public abstract Timer getWifiStateTimer(int wifiState);
+
+    /**
      * Returns the time in microseconds that the wifi supplicant has been
      * in a given state.
      *
@@ -2282,6 +2315,13 @@
      */
     public abstract int getWifiSupplStateCount(int state, int which);
 
+    /**
+     * Returns the {@link Timer} object that tracks the given wifi supplicant state.
+     *
+     * {@hide}
+     */
+    public abstract Timer getWifiSupplStateTimer(int state);
+
     public static final int NUM_WIFI_SIGNAL_STRENGTH_BINS = 5;
 
     /**
@@ -2301,6 +2341,13 @@
     public abstract int getWifiSignalStrengthCount(int strengthBin, int which);
 
     /**
+     * Returns the {@link Timer} object that tracks the given WIFI signal strength.
+     *
+     * {@hide}
+     */
+    public abstract Timer getWifiSignalStrengthTimer(int strengthBin);
+
+    /**
      * Returns the time in microseconds that the flashlight has been on while the device was
      * running on battery.
      *
@@ -2487,13 +2534,13 @@
     public abstract int getDischargeAmountScreenOffSinceCharge();
 
     /**
-     * Get the amount the battery has discharged while the screen was doze,
+     * Get the amount the battery has discharged while the screen was dozing,
      * since the last time power was unplugged.
      */
     public abstract int getDischargeAmountScreenDoze();
 
     /**
-     * Get the amount the battery has discharged while the screen was doze,
+     * Get the amount the battery has discharged while the screen was dozing,
      * since the last time the device was charged.
      */
     public abstract int getDischargeAmountScreenDozeSinceCharge();
@@ -2626,20 +2673,20 @@
      * micro-Ampere-hours. This will be non-zero only if the device's battery has
      * a coulomb counter.
      */
-    public abstract long getMahDischargeScreenOff(int which);
+    public abstract long getUahDischargeScreenOff(int which);
 
     /**
      * Return the amount of battery discharge while the screen was in doze mode, measured in
      * micro-Ampere-hours. This will be non-zero only if the device's battery has
      * a coulomb counter.
      */
-    public abstract long getMahDischargeScreenDoze(int which);
+    public abstract long getUahDischargeScreenDoze(int which);
 
     /**
      * Return the amount of battery discharge  measured in micro-Ampere-hours. This will be
      * non-zero only if the device's battery has a coulomb counter.
      */
-    public abstract long getMahDischarge(int which);
+    public abstract long getUahDischarge(int which);
 
     /**
      * Returns the estimated real battery capacity, which may be less than the capacity
@@ -2984,7 +3031,7 @@
             final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500)
                     / 1000;
             final int count = timer.getCountLocked(which);
-            if (totalTime != 0) {
+            if (totalTime != 0 || count != 0) {
                 dumpLine(pw, uid, category, type, totalTime, count);
             }
         }
@@ -3000,12 +3047,12 @@
      * @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) {
+                                        Timer timer, long rawRealtimeUs, int which) {
         if (timer == null) {
             return;
         }
         // Convert from microseconds to milliseconds with rounding
-        final long totalTimeMs = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+        final long totalTimeMs = (timer.getTotalTimeLocked(rawRealtimeUs, which) + 500) / 1000;
         final int count = timer.getCountLocked(which);
         if (totalTimeMs != 0 || count != 0) {
             final long token = proto.start(fieldId);
@@ -3191,13 +3238,13 @@
     /**
      * Checkin server version of dump to produce more compact, computer-readable log.
      *
-     * NOTE: all times are expressed in 'ms'.
+     * NOTE: all times are expressed in microseconds, unless specified otherwise.
      */
     public final void dumpCheckinLocked(Context context, PrintWriter pw, int which, int reqUid,
             boolean wifiOnly) {
         final long rawUptime = SystemClock.uptimeMillis() * 1000;
-        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
-        final long rawRealtimeMs = (rawRealtime + 500) / 1000;
+        final long rawRealtimeMs = SystemClock.elapsedRealtime();
+        final long rawRealtime = rawRealtimeMs * 1000;
         final long batteryUptime = getBatteryUptime(rawUptime);
         final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
         final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
@@ -3220,9 +3267,9 @@
                 rawRealtime, which);
         final int connChanges = getNumConnectivityChange(which);
         final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
-        final long dischargeCount = getMahDischarge(which);
-        final long dischargeScreenOffCount = getMahDischargeScreenOff(which);
-        final long dischargeScreenDozeCount = getMahDischargeScreenDoze(which);
+        final long dischargeCount = getUahDischarge(which);
+        final long dischargeScreenOffCount = getUahDischargeScreenOff(which);
+        final long dischargeScreenDozeCount = getUahDischargeScreenDoze(which);
 
         final StringBuilder sb = new StringBuilder(128);
 
@@ -3460,9 +3507,9 @@
                     BatteryStatsHelper.makemAh(helper.getComputedPower()),
                     BatteryStatsHelper.makemAh(helper.getMinDrainedPower()),
                     BatteryStatsHelper.makemAh(helper.getMaxDrainedPower()));
+            int uid = 0;
             for (int i=0; i<sippers.size(); i++) {
                 final BatterySipper bs = sippers.get(i);
-                int uid = 0;
                 String label;
                 switch (bs.drainType) {
                     case IDLE:
@@ -3503,6 +3550,9 @@
                     case CAMERA:
                         label = "camera";
                         break;
+                    case MEMORY:
+                        label = "memory";
+                        break;
                     default:
                         label = "???";
                 }
@@ -3523,6 +3573,7 @@
             dumpLine(pw, 0 /* uid */, category, GLOBAL_CPU_FREQ_DATA, sb.toString());
         }
 
+        // Dump stats per UID.
         for (int iu = 0; iu < NU; iu++) {
             final int uid = uidStats.keyAt(iu);
             if (reqUid >= 0 && uid != reqUid) {
@@ -4020,7 +4071,7 @@
             pw.println(sb.toString());
         }
 
-        final long dischargeCount = getMahDischarge(which);
+        final long dischargeCount = getUahDischarge(which);
         if (dischargeCount >= 0) {
             sb.setLength(0);
             sb.append(prefix);
@@ -4030,7 +4081,7 @@
             pw.println(sb.toString());
         }
 
-        final long dischargeScreenOffCount = getMahDischargeScreenOff(which);
+        final long dischargeScreenOffCount = getUahDischargeScreenOff(which);
         if (dischargeScreenOffCount >= 0) {
             sb.setLength(0);
             sb.append(prefix);
@@ -4040,7 +4091,7 @@
             pw.println(sb.toString());
         }
 
-        final long dischargeScreenDozeCount = getMahDischargeScreenDoze(which);
+        final long dischargeScreenDozeCount = getUahDischargeScreenDoze(which);
         if (dischargeScreenDozeCount >= 0) {
             sb.setLength(0);
             sb.append(prefix);
@@ -6038,6 +6089,61 @@
         return true;
     }
 
+    private static void dumpDurationSteps(ProtoOutputStream proto, long fieldId,
+            LevelStepTracker steps) {
+        if (steps == null) {
+            return;
+        }
+        int count = steps.mNumStepDurations;
+        long token;
+        for (int i = 0; i < count; ++i) {
+            token = proto.start(fieldId);
+            proto.write(SystemProto.BatteryLevelStep.DURATION_MS, steps.getDurationAt(i));
+            proto.write(SystemProto.BatteryLevelStep.LEVEL, steps.getLevelAt(i));
+
+            final long initMode = steps.getInitModeAt(i);
+            final long modMode = steps.getModModeAt(i);
+
+            int ds = SystemProto.BatteryLevelStep.DS_MIXED;
+            if ((modMode & STEP_LEVEL_MODE_SCREEN_STATE) == 0) {
+                switch ((int) (initMode & STEP_LEVEL_MODE_SCREEN_STATE) + 1) {
+                    case Display.STATE_OFF:
+                        ds = SystemProto.BatteryLevelStep.DS_OFF;
+                        break;
+                    case Display.STATE_ON:
+                        ds = SystemProto.BatteryLevelStep.DS_ON;
+                        break;
+                    case Display.STATE_DOZE:
+                        ds = SystemProto.BatteryLevelStep.DS_DOZE;
+                        break;
+                    case Display.STATE_DOZE_SUSPEND:
+                        ds = SystemProto.BatteryLevelStep.DS_DOZE_SUSPEND;
+                        break;
+                    default:
+                        ds = SystemProto.BatteryLevelStep.DS_ERROR;
+                        break;
+                }
+            }
+            proto.write(SystemProto.BatteryLevelStep.DISPLAY_STATE, ds);
+
+            int psm = SystemProto.BatteryLevelStep.PSM_MIXED;
+            if ((modMode & STEP_LEVEL_MODE_POWER_SAVE) == 0) {
+                psm = (initMode & STEP_LEVEL_MODE_POWER_SAVE) != 0
+                    ? SystemProto.BatteryLevelStep.PSM_ON : SystemProto.BatteryLevelStep.PSM_OFF;
+            }
+            proto.write(SystemProto.BatteryLevelStep.POWER_SAVE_MODE, psm);
+
+            int im = SystemProto.BatteryLevelStep.IM_MIXED;
+            if ((modMode & STEP_LEVEL_MODE_DEVICE_IDLE) == 0) {
+                im = (initMode & STEP_LEVEL_MODE_DEVICE_IDLE) != 0
+                    ? SystemProto.BatteryLevelStep.IM_ON : SystemProto.BatteryLevelStep.IM_OFF;
+            }
+            proto.write(SystemProto.BatteryLevelStep.IDLE_MODE, im);
+
+            proto.end(token);
+        }
+    }
+
     public static final int DUMP_CHARGED_ONLY = 1<<1;
     public static final int DUMP_DAILY_ONLY = 1<<2;
     public static final int DUMP_HISTORY_ONLY = 1<<3;
@@ -6463,7 +6569,7 @@
         }
     }
 
-    /** Dump batterystats data to a proto. @hide */
+    /** Dump #STATS_SINCE_CHARGED 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);
@@ -6485,10 +6591,376 @@
 
         if ((flags & (DUMP_HISTORY_ONLY | DUMP_DAILY_ONLY)) == 0) {
             // TODO: implement dumpProtoAppsLocked(proto, apps);
-            // TODO: implement dumpProtoSystemLocked(proto);
+            dumpProtoSystemLocked(context, proto, (flags & DUMP_DEVICE_WIFI_ONLY) != 0);
         }
 
         proto.end(bToken);
         proto.flush();
     }
+
+    private void dumpProtoSystemLocked(Context context, ProtoOutputStream proto, boolean wifiOnly) {
+        final long sToken = proto.start(BatteryStatsProto.SYSTEM);
+        final long rawUptimeUs = SystemClock.uptimeMillis() * 1000;
+        final long rawRealtimeMs = SystemClock.elapsedRealtime();
+        final long rawRealtimeUs = rawRealtimeMs * 1000;
+        final int which = STATS_SINCE_CHARGED;
+
+        // Battery data (BATTERY_DATA)
+        long token = proto.start(SystemProto.BATTERY);
+        proto.write(SystemProto.Battery.START_CLOCK_TIME_MS, getStartClockTime());
+        proto.write(SystemProto.Battery.START_COUNT, getStartCount());
+        proto.write(SystemProto.Battery.TOTAL_REALTIME_MS,
+                computeRealtime(rawRealtimeUs, which) / 1000);
+        proto.write(SystemProto.Battery.TOTAL_UPTIME_MS,
+                computeUptime(rawUptimeUs, which) / 1000);
+        proto.write(SystemProto.Battery.BATTERY_REALTIME_MS,
+                computeBatteryRealtime(rawRealtimeUs, which) / 1000);
+        proto.write(SystemProto.Battery.BATTERY_UPTIME_MS,
+                computeBatteryUptime(rawUptimeUs, which) / 1000);
+        proto.write(SystemProto.Battery.SCREEN_OFF_REALTIME_MS,
+                computeBatteryScreenOffRealtime(rawRealtimeUs, which) / 1000);
+        proto.write(SystemProto.Battery.SCREEN_OFF_UPTIME_MS,
+                computeBatteryScreenOffUptime(rawUptimeUs, which) / 1000);
+        proto.write(SystemProto.Battery.SCREEN_DOZE_DURATION_MS,
+                getScreenDozeTime(rawRealtimeUs, which) / 1000);
+        proto.write(SystemProto.Battery.ESTIMATED_BATTERY_CAPACITY_MAH,
+                getEstimatedBatteryCapacity());
+        proto.write(SystemProto.Battery.MIN_LEARNED_BATTERY_CAPACITY_UAH,
+                getMinLearnedBatteryCapacity());
+        proto.write(SystemProto.Battery.MAX_LEARNED_BATTERY_CAPACITY_UAH,
+                getMaxLearnedBatteryCapacity());
+        proto.end(token);
+
+        // Battery discharge (BATTERY_DISCHARGE_DATA)
+        token = proto.start(SystemProto.BATTERY_DISCHARGE);
+        proto.write(SystemProto.BatteryDischarge.LOWER_BOUND_SINCE_CHARGE,
+                getLowDischargeAmountSinceCharge());
+        proto.write(SystemProto.BatteryDischarge.UPPER_BOUND_SINCE_CHARGE,
+                getHighDischargeAmountSinceCharge());
+        proto.write(SystemProto.BatteryDischarge.SCREEN_ON_SINCE_CHARGE,
+                getDischargeAmountScreenOnSinceCharge());
+        proto.write(SystemProto.BatteryDischarge.SCREEN_OFF_SINCE_CHARGE,
+                getDischargeAmountScreenOffSinceCharge());
+        proto.write(SystemProto.BatteryDischarge.SCREEN_DOZE_SINCE_CHARGE,
+                getDischargeAmountScreenDozeSinceCharge());
+        proto.write(SystemProto.BatteryDischarge.TOTAL_MAH,
+                getUahDischarge(which) / 1000);
+        proto.write(SystemProto.BatteryDischarge.TOTAL_MAH_SCREEN_OFF,
+                getUahDischargeScreenOff(which) / 1000);
+        proto.write(SystemProto.BatteryDischarge.TOTAL_MAH_SCREEN_DOZE,
+                getUahDischargeScreenDoze(which) / 1000);
+        proto.end(token);
+
+        // Time remaining
+        long timeRemainingUs = computeChargeTimeRemaining(rawRealtimeUs);
+        if (timeRemainingUs >= 0) {
+            // Charge time remaining (CHARGE_TIME_REMAIN_DATA)
+            proto.write(SystemProto.CHARGE_TIME_REMAINING_MS, timeRemainingUs / 1000);
+        } else {
+            timeRemainingUs = computeBatteryTimeRemaining(rawRealtimeUs);
+            // Discharge time remaining (DISCHARGE_TIME_REMAIN_DATA)
+            if (timeRemainingUs >= 0) {
+                proto.write(SystemProto.DISCHARGE_TIME_REMAINING_MS, timeRemainingUs / 1000);
+            } else {
+                proto.write(SystemProto.DISCHARGE_TIME_REMAINING_MS, -1);
+            }
+        }
+
+        // Charge step (CHARGE_STEP_DATA)
+        dumpDurationSteps(proto, SystemProto.CHARGE_STEP, getChargeLevelStepTracker());
+
+        // Phone data connection (DATA_CONNECTION_TIME_DATA and DATA_CONNECTION_COUNT_DATA)
+        for (int i = 0; i < NUM_DATA_CONNECTION_TYPES; ++i) {
+            token = proto.start(SystemProto.DATA_CONNECTION);
+            proto.write(SystemProto.DataConnection.NAME, i);
+            dumpTimer(proto, SystemProto.DataConnection.TOTAL, getPhoneDataConnectionTimer(i),
+                    rawRealtimeUs, which);
+            proto.end(token);
+        }
+
+        // Discharge step (DISCHARGE_STEP_DATA)
+        dumpDurationSteps(proto, SystemProto.DISCHARGE_STEP, getDischargeLevelStepTracker());
+
+        // CPU frequencies (GLOBAL_CPU_FREQ_DATA)
+        final long[] cpuFreqs = getCpuFreqs();
+        if (cpuFreqs != null) {
+            for (long i : cpuFreqs) {
+                proto.write(SystemProto.CPU_FREQUENCY, i);
+            }
+        }
+
+        // Bluetooth controller (GLOBAL_BLUETOOTH_CONTROLLER_DATA)
+        dumpControllerActivityProto(proto, SystemProto.GLOBAL_BLUETOOTH_CONTROLLER,
+                getBluetoothControllerActivity(), which);
+
+        // Modem controller (GLOBAL_MODEM_CONTROLLER_DATA)
+        dumpControllerActivityProto(proto, SystemProto.GLOBAL_MODEM_CONTROLLER,
+                getModemControllerActivity(), which);
+
+        // Global network data (GLOBAL_NETWORK_DATA)
+        token = proto.start(SystemProto.GLOBAL_NETWORK);
+        proto.write(SystemProto.GlobalNetwork.MOBILE_BYTES_RX,
+                getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which));
+        proto.write(SystemProto.GlobalNetwork.MOBILE_BYTES_TX,
+                getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which));
+        proto.write(SystemProto.GlobalNetwork.MOBILE_PACKETS_RX,
+                getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which));
+        proto.write(SystemProto.GlobalNetwork.MOBILE_PACKETS_TX,
+                getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which));
+        proto.write(SystemProto.GlobalNetwork.WIFI_BYTES_RX,
+                getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which));
+        proto.write(SystemProto.GlobalNetwork.WIFI_BYTES_TX,
+                getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which));
+        proto.write(SystemProto.GlobalNetwork.WIFI_PACKETS_RX,
+                getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which));
+        proto.write(SystemProto.GlobalNetwork.WIFI_PACKETS_TX,
+                getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which));
+        proto.write(SystemProto.GlobalNetwork.BT_BYTES_RX,
+                getNetworkActivityBytes(NETWORK_BT_RX_DATA, which));
+        proto.write(SystemProto.GlobalNetwork.BT_BYTES_TX,
+                getNetworkActivityBytes(NETWORK_BT_TX_DATA, which));
+        proto.end(token);
+
+        // Wifi controller (GLOBAL_WIFI_CONTROLLER_DATA)
+        dumpControllerActivityProto(proto, SystemProto.GLOBAL_WIFI_CONTROLLER,
+                getWifiControllerActivity(), which);
+
+
+        // Global wifi (GLOBAL_WIFI_DATA)
+        token = proto.start(SystemProto.GLOBAL_WIFI);
+        proto.write(SystemProto.GlobalWifi.ON_DURATION_MS,
+                getWifiOnTime(rawRealtimeUs, which) / 1000);
+        proto.write(SystemProto.GlobalWifi.RUNNING_DURATION_MS,
+                getGlobalWifiRunningTime(rawRealtimeUs, which) / 1000);
+        proto.end(token);
+
+        // Kernel wakelock (KERNEL_WAKELOCK_DATA)
+        final Map<String, ? extends Timer> kernelWakelocks = getKernelWakelockStats();
+        for (Map.Entry<String, ? extends Timer> ent : kernelWakelocks.entrySet()) {
+            token = proto.start(SystemProto.KERNEL_WAKELOCK);
+            proto.write(SystemProto.KernelWakelock.NAME, ent.getKey());
+            dumpTimer(proto, SystemProto.KernelWakelock.TOTAL, ent.getValue(),
+                    rawRealtimeUs, which);
+            proto.end(token);
+        }
+
+        // Misc (MISC_DATA)
+        // Calculate wakelock times across all uids.
+        long fullWakeLockTimeTotalUs = 0;
+        long partialWakeLockTimeTotalUs = 0;
+
+        final SparseArray<? extends Uid> uidStats = getUidStats();
+        for (int iu = 0; iu < uidStats.size(); iu++) {
+            final Uid u = uidStats.valueAt(iu);
+
+            final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks =
+                    u.getWakelockStats();
+            for (int iw = wakelocks.size() - 1; iw >= 0; --iw) {
+                final Uid.Wakelock wl = wakelocks.valueAt(iw);
+
+                final Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
+                if (fullWakeTimer != null) {
+                    fullWakeLockTimeTotalUs += fullWakeTimer.getTotalTimeLocked(rawRealtimeUs,
+                            which);
+                }
+
+                final Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
+                if (partialWakeTimer != null) {
+                    partialWakeLockTimeTotalUs += partialWakeTimer.getTotalTimeLocked(
+                        rawRealtimeUs, which);
+                }
+            }
+        }
+        token = proto.start(SystemProto.MISC);
+        proto.write(SystemProto.Misc.SCREEN_ON_DURATION_MS,
+                getScreenOnTime(rawRealtimeUs, which) / 1000);
+        proto.write(SystemProto.Misc.PHONE_ON_DURATION_MS,
+                getPhoneOnTime(rawRealtimeUs, which) / 1000);
+        proto.write(SystemProto.Misc.FULL_WAKELOCK_TOTAL_DURATION_MS,
+                fullWakeLockTimeTotalUs / 1000);
+        proto.write(SystemProto.Misc.PARTIAL_WAKELOCK_TOTAL_DURATION_MS,
+                partialWakeLockTimeTotalUs / 1000);
+        proto.write(SystemProto.Misc.MOBILE_RADIO_ACTIVE_DURATION_MS,
+                getMobileRadioActiveTime(rawRealtimeUs, which) / 1000);
+        proto.write(SystemProto.Misc.MOBILE_RADIO_ACTIVE_ADJUSTED_TIME_MS,
+                getMobileRadioActiveAdjustedTime(which) / 1000);
+        proto.write(SystemProto.Misc.MOBILE_RADIO_ACTIVE_COUNT,
+                getMobileRadioActiveCount(which));
+        proto.write(SystemProto.Misc.MOBILE_RADIO_ACTIVE_UNKNOWN_DURATION_MS,
+                getMobileRadioActiveUnknownTime(which) / 1000);
+        proto.write(SystemProto.Misc.INTERACTIVE_DURATION_MS,
+                getInteractiveTime(rawRealtimeUs, which) / 1000);
+        proto.write(SystemProto.Misc.BATTERY_SAVER_MODE_ENABLED_DURATION_MS,
+                getPowerSaveModeEnabledTime(rawRealtimeUs, which) / 1000);
+        proto.write(SystemProto.Misc.NUM_CONNECTIVITY_CHANGES,
+                getNumConnectivityChange(which));
+        proto.write(SystemProto.Misc.DEEP_DOZE_ENABLED_DURATION_MS,
+                getDeviceIdleModeTime(DEVICE_IDLE_MODE_DEEP, rawRealtimeUs, which) / 1000);
+        proto.write(SystemProto.Misc.DEEP_DOZE_COUNT,
+                getDeviceIdleModeCount(DEVICE_IDLE_MODE_DEEP, which));
+        proto.write(SystemProto.Misc.DEEP_DOZE_IDLING_DURATION_MS,
+                getDeviceIdlingTime(DEVICE_IDLE_MODE_DEEP, rawRealtimeUs, which) / 1000);
+        proto.write(SystemProto.Misc.DEEP_DOZE_IDLING_COUNT,
+                getDeviceIdlingCount(DEVICE_IDLE_MODE_DEEP, which));
+        proto.write(SystemProto.Misc.LONGEST_DEEP_DOZE_DURATION_MS,
+                getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_DEEP));
+        proto.write(SystemProto.Misc.LIGHT_DOZE_ENABLED_DURATION_MS,
+                getDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT, rawRealtimeUs, which) / 1000);
+        proto.write(SystemProto.Misc.LIGHT_DOZE_COUNT,
+                getDeviceIdleModeCount(DEVICE_IDLE_MODE_LIGHT, which));
+        proto.write(SystemProto.Misc.LIGHT_DOZE_IDLING_DURATION_MS,
+                getDeviceIdlingTime(DEVICE_IDLE_MODE_LIGHT, rawRealtimeUs, which) / 1000);
+        proto.write(SystemProto.Misc.LIGHT_DOZE_IDLING_COUNT,
+                getDeviceIdlingCount(DEVICE_IDLE_MODE_LIGHT, which));
+        proto.write(SystemProto.Misc.LONGEST_LIGHT_DOZE_DURATION_MS,
+                getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT));
+        proto.end(token);
+
+        final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
+        helper.create(this);
+        helper.refreshStats(which, UserHandle.USER_ALL);
+
+        // Power use item (POWER_USE_ITEM_DATA)
+        final List<BatterySipper> sippers = helper.getUsageList();
+        if (sippers != null) {
+            for (int i = 0; i < sippers.size(); ++i) {
+                final BatterySipper bs = sippers.get(i);
+                int n = SystemProto.PowerUseItem.UNKNOWN_SIPPER;
+                int uid = 0;
+                switch (bs.drainType) {
+                    case IDLE:
+                        n = SystemProto.PowerUseItem.IDLE;
+                        break;
+                    case CELL:
+                        n = SystemProto.PowerUseItem.CELL;
+                        break;
+                    case PHONE:
+                        n = SystemProto.PowerUseItem.PHONE;
+                        break;
+                    case WIFI:
+                        n = SystemProto.PowerUseItem.WIFI;
+                        break;
+                    case BLUETOOTH:
+                        n = SystemProto.PowerUseItem.BLUETOOTH;
+                        break;
+                    case SCREEN:
+                        n = SystemProto.PowerUseItem.SCREEN;
+                        break;
+                    case FLASHLIGHT:
+                        n = SystemProto.PowerUseItem.FLASHLIGHT;
+                        break;
+                    case APP:
+                        // dumpProtoAppLocked will handle this.
+                        continue;
+                    case USER:
+                        n = SystemProto.PowerUseItem.USER;
+                        uid = UserHandle.getUid(bs.userId, 0);
+                        break;
+                    case UNACCOUNTED:
+                        n = SystemProto.PowerUseItem.UNACCOUNTED;
+                        break;
+                    case OVERCOUNTED:
+                        n = SystemProto.PowerUseItem.OVERCOUNTED;
+                        break;
+                    case CAMERA:
+                        n = SystemProto.PowerUseItem.CAMERA;
+                        break;
+                    case MEMORY:
+                        n = SystemProto.PowerUseItem.MEMORY;
+                        break;
+                }
+                token = proto.start(SystemProto.POWER_USE_ITEM);
+                proto.write(SystemProto.PowerUseItem.NAME, n);
+                proto.write(SystemProto.PowerUseItem.UID, uid);
+                proto.write(SystemProto.PowerUseItem.COMPUTED_POWER_MAH, bs.totalPowerMah);
+                proto.write(SystemProto.PowerUseItem.SHOULD_HIDE, bs.shouldHide);
+                proto.write(SystemProto.PowerUseItem.SCREEN_POWER_MAH, bs.screenPowerMah);
+                proto.write(SystemProto.PowerUseItem.PROPORTIONAL_SMEAR_MAH,
+                        bs.proportionalSmearMah);
+                proto.end(token);
+            }
+        }
+
+        // Power use summary (POWER_USE_SUMMARY_DATA)
+        token = proto.start(SystemProto.POWER_USE_SUMMARY);
+        proto.write(SystemProto.PowerUseSummary.BATTERY_CAPACITY_MAH,
+                helper.getPowerProfile().getBatteryCapacity());
+        proto.write(SystemProto.PowerUseSummary.COMPUTED_POWER_MAH, helper.getComputedPower());
+        proto.write(SystemProto.PowerUseSummary.MIN_DRAINED_POWER_MAH, helper.getMinDrainedPower());
+        proto.write(SystemProto.PowerUseSummary.MAX_DRAINED_POWER_MAH, helper.getMaxDrainedPower());
+        proto.end(token);
+
+        // RPM stats (RESOURCE_POWER_MANAGER_DATA)
+        final Map<String, ? extends Timer> rpmStats = getRpmStats();
+        final Map<String, ? extends Timer> screenOffRpmStats = getScreenOffRpmStats();
+        for (Map.Entry<String, ? extends Timer> ent : rpmStats.entrySet()) {
+            token = proto.start(SystemProto.RESOURCE_POWER_MANAGER);
+            proto.write(SystemProto.ResourcePowerManager.NAME, ent.getKey());
+            dumpTimer(proto, SystemProto.ResourcePowerManager.TOTAL,
+                    ent.getValue(), rawRealtimeUs, which);
+            dumpTimer(proto, SystemProto.ResourcePowerManager.SCREEN_OFF,
+                    screenOffRpmStats.get(ent.getKey()), rawRealtimeUs, which);
+            proto.end(token);
+        }
+
+        // Screen brightness (SCREEN_BRIGHTNESS_DATA)
+        for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; ++i) {
+            token = proto.start(SystemProto.SCREEN_BRIGHTNESS);
+            proto.write(SystemProto.ScreenBrightness.NAME, i);
+            dumpTimer(proto, SystemProto.ScreenBrightness.TOTAL, getScreenBrightnessTimer(i),
+                    rawRealtimeUs, which);
+            proto.end(token);
+        }
+
+        // Signal scanning time (SIGNAL_SCANNING_TIME_DATA)
+        dumpTimer(proto, SystemProto.SIGNAL_SCANNING, getPhoneSignalScanningTimer(), rawRealtimeUs,
+                which);
+
+        // Phone signal strength (SIGNAL_STRENGTH_TIME_DATA and SIGNAL_STRENGTH_COUNT_DATA)
+        for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; ++i) {
+            token = proto.start(SystemProto.PHONE_SIGNAL_STRENGTH);
+            proto.write(SystemProto.PhoneSignalStrength.NAME, i);
+            dumpTimer(proto, SystemProto.PhoneSignalStrength.TOTAL, getPhoneSignalStrengthTimer(i),
+                    rawRealtimeUs, which);
+            proto.end(token);
+        }
+
+        // Wakeup reasons (WAKEUP_REASON_DATA)
+        final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
+        for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) {
+            token = proto.start(SystemProto.WAKEUP_REASON);
+            proto.write(SystemProto.WakeupReason.NAME, ent.getKey());
+            dumpTimer(proto, SystemProto.WakeupReason.TOTAL, ent.getValue(), rawRealtimeUs, which);
+            proto.end(token);
+        }
+
+        // Wifi signal strength (WIFI_SIGNAL_STRENGTH_TIME_DATA and WIFI_SIGNAL_STRENGTH_COUNT_DATA)
+        for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; ++i) {
+            token = proto.start(SystemProto.WIFI_SIGNAL_STRENGTH);
+            proto.write(SystemProto.WifiSignalStrength.NAME, i);
+            dumpTimer(proto, SystemProto.WifiSignalStrength.TOTAL, getWifiSignalStrengthTimer(i),
+                    rawRealtimeUs, which);
+            proto.end(token);
+        }
+
+        // Wifi state (WIFI_STATE_TIME_DATA and WIFI_STATE_COUNT_DATA)
+        for (int i = 0; i < NUM_WIFI_STATES; ++i) {
+            token = proto.start(SystemProto.WIFI_STATE);
+            proto.write(SystemProto.WifiState.NAME, i);
+            dumpTimer(proto, SystemProto.WifiState.TOTAL, getWifiStateTimer(i),
+                    rawRealtimeUs, which);
+            proto.end(token);
+        }
+
+        // Wifi supplicant state (WIFI_SUPPL_STATE_TIME_DATA and WIFI_SUPPL_STATE_COUNT_DATA)
+        for (int i = 0; i < NUM_WIFI_SUPPL_STATES; ++i) {
+            token = proto.start(SystemProto.WIFI_SUPPLICANT_STATE);
+            proto.write(SystemProto.WifiSupplicantState.NAME, i);
+            dumpTimer(proto, SystemProto.WifiSupplicantState.TOTAL, getWifiSupplStateTimer(i),
+                    rawRealtimeUs, which);
+            proto.end(token);
+        }
+
+        proto.end(sToken);
+    }
 }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 36fd991..a978cb4 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -681,17 +681,17 @@
     }
 
     @Override
-    public long getMahDischarge(int which) {
+    public long getUahDischarge(int which) {
         return mDischargeCounter.getCountLocked(which);
     }
 
     @Override
-    public long getMahDischargeScreenOff(int which) {
+    public long getUahDischargeScreenOff(int which) {
         return mDischargeScreenOffCounter.getCountLocked(which);
     }
 
     @Override
-    public long getMahDischargeScreenDoze(int which) {
+    public long getUahDischargeScreenDoze(int which) {
         return mDischargeScreenDozeCounter.getCountLocked(which);
     }
 
@@ -5427,6 +5427,10 @@
                 elapsedRealtimeUs, which);
     }
 
+    @Override public Timer getScreenBrightnessTimer(int brightnessBin) {
+        return mScreenBrightnessTimer[brightnessBin];
+    }
+
     @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
         return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
     }
@@ -5520,10 +5524,18 @@
                 elapsedRealtimeUs, which);
     }
 
+    @Override public Timer getPhoneSignalScanningTimer() {
+        return mPhoneSignalScanningTimer;
+    }
+
     @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
         return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
     }
 
+    @Override public Timer getPhoneSignalStrengthTimer(int strengthBin) {
+        return mPhoneSignalStrengthsTimer[strengthBin];
+    }
+
     @Override public long getPhoneDataConnectionTime(int dataType,
             long elapsedRealtimeUs, int which) {
         return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
@@ -5534,6 +5546,10 @@
         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
     }
 
+    @Override public Timer getPhoneDataConnectionTimer(int dataType) {
+        return mPhoneDataConnectionsTimer[dataType];
+    }
+
     @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
         return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
     }
@@ -5572,6 +5588,10 @@
         return mWifiStateTimer[wifiState].getCountLocked(which);
     }
 
+    @Override public Timer getWifiStateTimer(int wifiState) {
+        return mWifiStateTimer[wifiState];
+    }
+
     @Override public long getWifiSupplStateTime(int state,
             long elapsedRealtimeUs, int which) {
         return mWifiSupplStateTimer[state].getTotalTimeLocked(
@@ -5582,6 +5602,10 @@
         return mWifiSupplStateTimer[state].getCountLocked(which);
     }
 
+    @Override public Timer getWifiSupplStateTimer(int state) {
+        return mWifiSupplStateTimer[state];
+    }
+
     @Override public long getWifiSignalStrengthTime(int strengthBin,
             long elapsedRealtimeUs, int which) {
         return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
@@ -5592,6 +5616,10 @@
         return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
     }
 
+    @Override public Timer getWifiSignalStrengthTimer(int strengthBin) {
+        return mWifiSignalStrengthsTimer[strengthBin];
+    }
+
     @Override
     public ControllerActivityCounter getBluetoothControllerActivity() {
         return mBluetoothActivity;
@@ -12791,7 +12819,7 @@
         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
         mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null,
                 mOnBatteryTimeBase, in);
-        mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null, 
+        mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
                 mOnBatteryTimeBase, in);
         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
diff --git a/core/proto/android/os/batterystats.proto b/core/proto/android/os/batterystats.proto
index 86e31d0..8d85038 100644
--- a/core/proto/android/os/batterystats.proto
+++ b/core/proto/android/os/batterystats.proto
@@ -20,6 +20,8 @@
 
 package android.os;
 
+import "frameworks/base/core/proto/android/telephony/signalstrength.proto";
+
 message BatteryStatsProto {
   int32 report_version = 1;
   int64 parcel_version = 2;
@@ -55,6 +57,383 @@
 }
 
 message SystemProto {
+  message Battery {
+    // Wall clock time when the data collection started.
+    // In case of device time manually reset by users:
+    //   start_clock_time_ms keeps the same value in the current collection
+    //   period and changes for later collection periods.
+    int64 start_clock_time_ms = 1;
+    // #times the device has been started since start_clock_time_millis.
+    int64 start_count = 2;
+    // Total realtime duration (= SINCE_UNPLUGGED battery_realtime_millis.)
+    int64 total_realtime_ms = 3;
+    int64 total_uptime_ms = 4;
+    // Realtime duration on battery.
+    int64 battery_realtime_ms = 5;
+    // Uptime duration (i.e., not suspend).
+    // Uptime is anytime the CPUs were on. The radio and Wifi chip
+    // can be running while the CPUs are off.
+    int64 battery_uptime_ms = 6;
+    // Total realtime duration measured with screen off or dozing.
+    int64 screen_off_realtime_ms = 7;
+    // Total uptime duration measured with screen off or dozing.
+    int64 screen_off_uptime_ms = 8;
+    // Total time the screen was dozing while the device was running on battery.
+    // For historical reasons, screen_doze_duration_msec is a subset of
+    // screen_off_realtime_msec.
+    int64 screen_doze_duration_ms = 9;
+    // The estimated real battery capacity, which may be less than the declared
+    // battery capacity (for example, because of battery aging). This field is
+    // less reliable than min(max)_learned_battery_capacity_uah, use those two
+    // fields whenever possible.
+    int64 estimated_battery_capacity_mah = 10;
+    // The minimum learned battery capacity in uAh.
+    int64 min_learned_battery_capacity_uah = 11;
+    // The maximum learned battery capacity in uAh.
+    int64 max_learned_battery_capacity_uah = 12;
+  };
+  Battery battery = 1;
+
+  message BatteryDischarge {
+    // Discharged battery percentage points since the stats were last reset
+    // after charging (lower bound approximation).
+    int32 lower_bound_since_charge = 1;
+    // Upper bound approximation.
+    int32 upper_bound_since_charge = 2;
+    // Discharged points while screen is on.
+    int32 screen_on_since_charge = 3;
+    // Discharged points while screen is off.
+    int32 screen_off_since_charge = 4;
+    // Discharged points while screen was dozing. For historical reasons,
+    // screen_doze_since_charge is a subset of screen_off_since_charge.
+    int32 screen_doze_since_charge = 5;
+    // Total amount of battery discharged in mAh. This will only be non-zero for
+    // devices that report battery discharge via a coulomb counter.
+    int64 total_mah = 6;
+    // Total amount of battery discharged while the screen was off in mAh.
+    // This will only be non-zero for devices that report battery discharge
+    // via a coulomb counter.
+    int64 total_mah_screen_off = 7;
+    // Total amount of battery discharged while the screen was dozing in mAh.
+    // This will only be non-zero for devices that report battery discharge
+    // via a coulomb counter. For historical reasons, total_mah_screen_doze is
+    // a subset of total_mah_screen_off.
+    int64 total_mah_screen_doze = 8;
+  };
+  BatteryDischarge battery_discharge = 2;
+
+  oneof time_remaining {
+    // Approximation for how much time remains until the battery is fully
+    // charged. The device will print -1 if there wasn't enough data to
+    // calculate an estimate, or if the battery is currently discharging.
+    int64 charge_time_remaining_ms = 3;
+    // Approximation for how much time remains until the battery is fully
+    // discharged. The device will print -1 if there wasn't enough data to
+    // calculate an estimate, or if the battery is currently charging.
+    int64 discharge_time_remaining_ms = 4;
+  }
+
+  // BatteryLevelStep tracks data for which conditions were continuously held for
+  // the entire duration. Field for which the conditions were not consistent
+  // for the entire duration should be marked MIXED.
+  message BatteryLevelStep {
+    // How long the battery was at the current level.
+    int64 duration_ms = 1;
+    // Battery level
+    int32 level = 2;
+
+    // State of the display. A special enum is used rather than
+    // DisplayProto.State because a MIXED value needs to be in the enum, and
+    // batterystats doesn't care about all of the different display states.
+    enum DisplayState {
+      DS_MIXED = 0;
+      DS_ON = 1;
+      DS_OFF = 2;
+      DS_DOZE = 3;
+      DS_DOZE_SUSPEND = 4;
+      // Any display state error that comes through should be sent to hackbod@.
+      DS_ERROR = 5;
+    }
+    // The state of the display for the entire battery level step. MIXED is used
+    // if there were multiple states for this step.
+    DisplayState display_state = 3;
+
+    // Indicates status in power save mode.
+    enum PowerSaveMode {
+      PSM_MIXED = 0;
+      PSM_ON = 1;
+      PSM_OFF = 2;
+    }
+    // Battery Saver mode for the entire battery level step. MIXED is used
+    // if there were multiple states for this step.
+    PowerSaveMode power_save_mode = 4;
+
+    // Indicates status in idle mode.
+    enum IdleMode {
+      IM_MIXED = 0;
+      IM_ON = 2;
+      IM_OFF = 3;
+    }
+    // Doze mode for the entire battery level step. MIXED is used if there were
+    // multiple states for this step.
+    IdleMode idle_mode = 5;
+  };
+  // Battery level steps when the device was charging.
+  repeated BatteryLevelStep charge_step = 5;
+  // Battery level steps when the device was discharging.
+  repeated BatteryLevelStep discharge_step = 6;
+
+  // All CPU frequencies of the device.
+  repeated int64 cpu_frequency = 7;
+
+  message DataConnection {
+    enum Name {
+      NONE = 0;
+      GPRS = 1;
+      EDGE = 2;
+      UMTS = 3;
+      CDMA = 4;
+      EVDO_0 = 5;
+      EVDO_A = 6;
+      ONE_X_RTT = 7; // 1xRTT.
+      HSDPA = 8;
+      HSUPA = 9;
+      HSPA = 10;
+      IDEN = 11;
+      EVDO_B = 12;
+      LTE = 13;
+      EHRPD = 14;
+      HSPAP = 15;
+      OTHER = 16;
+    };
+    Name name = 1;
+    TimerProto total = 2;
+  };
+  repeated DataConnection data_connection = 8;
+
+  ControllerActivityProto global_bluetooth_controller = 9;
+  ControllerActivityProto global_modem_controller = 10;
+  ControllerActivityProto global_wifi_controller = 11;
+
+  message GlobalNetwork {
+    // Total Bytes received on mobile connections.
+    int64 mobile_bytes_rx = 1;
+    // Total Bytes transmitted on mobile connections.
+    int64 mobile_bytes_tx = 2;
+    // Total Bytes received on wifi connections.
+    int64 wifi_bytes_rx = 3;
+    // Total Bytes transmitted on wifi connections.
+    int64 wifi_bytes_tx = 4;
+    // Total Packets received on mobile connections.
+    int64 mobile_packets_rx = 5;
+    // Total Packets transmitted on mobile connections.
+    int64 mobile_packets_tx = 6;
+    // Total Packets received on wifi connections.
+    int64 wifi_packets_rx = 7;
+    // Total Packets transmitted on wifi connections.
+    int64 wifi_packets_tx = 8;
+    // Total Bytes received on bluetooth connections.
+    int64 bt_bytes_rx = 9;
+    // Total Bytes transmitted on bluetooth connections.
+    int64 bt_bytes_tx = 10;
+  };
+  GlobalNetwork global_network = 12;
+
+  message GlobalWifi {
+    // The amount of time that wifi has been on while the device was running on
+    // battery.
+    int64 on_duration_ms = 1;
+    // The amount of time that wifi has been on and the driver has been in the
+    // running state while the device was running on battery.
+    int64 running_duration_ms = 2;
+  }
+  GlobalWifi global_wifi = 13;
+
+  // Kernel wakelock metrics are only recorded when the device is unplugged
+  // *and* the screen is off.
+  message KernelWakelock {
+    string name = 1;
+    // Kernel wakelock stats aren't apportioned across all kernel wakelocks (as
+    // app wakelocks stats are).
+    TimerProto total = 2;
+    // The kernel doesn't have the data to enable printing out current and max
+    // durations.
+  };
+  repeated KernelWakelock kernel_wakelock = 14;
+
+  message Misc {
+    int64 screen_on_duration_ms = 1;
+    int64 phone_on_duration_ms = 2;
+    int64 full_wakelock_total_duration_ms = 3;
+    // The total elapsed time that a partial wakelock was held. This duration
+    // does not double count wakelocks held at the same time.
+    int64 partial_wakelock_total_duration_ms = 4;
+    int64 mobile_radio_active_duration_ms = 5;
+    // The time that is the difference between the mobile radio time we saw
+    // based on the elapsed timestamp when going down vs. the given time stamp
+    // from the radio.
+    int64 mobile_radio_active_adjusted_time_ms = 6;
+    int32 mobile_radio_active_count = 7;
+    // The amount of time that the mobile network has been active (in a high
+    // power state) but not being able to blame on an app.
+    int32 mobile_radio_active_unknown_duration_ms = 8;
+    // Total amount of time the device was in the interactive state.
+    int64 interactive_duration_ms = 9;
+    int64 battery_saver_mode_enabled_duration_ms = 10;
+    int32 num_connectivity_changes = 11;
+    // Amount of time the device was in deep Doze.
+    int64 deep_doze_enabled_duration_ms = 12;
+    // How many times the device went into deep Doze mode.
+    int32 deep_doze_count = 13;
+    // Amount of time the device was idling in deep Doze. Idling time
+    // encompasses "doze" time and the maintenance windows that allow apps to
+    // operate.
+    int64 deep_doze_idling_duration_ms = 14;
+    // How many times the device idling for deep Doze mode.
+    int32 deep_doze_idling_count = 15;
+    int64 longest_deep_doze_duration_ms = 16;
+    // Amount of time the device was in Doze Light.
+    int64 light_doze_enabled_duration_ms = 17;
+    // How many times the device went into Doze Light mode.
+    int32 light_doze_count = 18;
+    // Amount of time the device was idling in Doze Light. Idling time
+    // encompasses "doze" time and the maintenance windows that allow apps to
+    // operate.
+    int64 light_doze_idling_duration_ms = 19;
+    // How many times the device idling for Doze Light mode.
+    int32 light_doze_idling_count = 20;
+    int64 longest_light_doze_duration_ms = 21;
+  }
+  Misc misc = 15;
+
+  message PhoneSignalStrength {
+    android.telephony.SignalStrengthProto.StrengthName name = 1;
+    TimerProto total = 2;
+  };
+  repeated PhoneSignalStrength phone_signal_strength = 16;
+
+  message PowerUseItem {
+    enum Sipper {
+      UNKNOWN_SIPPER = 0;
+      IDLE = 1;
+      CELL = 2;
+      PHONE = 3;
+      WIFI = 4;
+      BLUETOOTH = 5;
+      FLASHLIGHT = 6;
+      SCREEN = 7;
+      USER = 8;
+      UNACCOUNTED = 9;
+      OVERCOUNTED = 10;
+      CAMERA = 11;
+      MEMORY = 12;
+    };
+    Sipper name = 1;
+    // UID, only valid for the USER sipper.
+    int32 uid = 2;
+    // Estimated power use in mAh.
+    double computed_power_mah = 3;
+    // Starting in Oreo, Battery Settings has two modes to display the battery
+    // info. The first is "app usage list". In this mode, items with should_hide
+    // enabled are hidden.
+    bool should_hide = 4;
+    // Smeared power from screen usage. Screen usage power is split and smeared
+    // among apps, based on activity time.
+    double screen_power_mah = 5;
+    // Smeared power using proportional method. Power usage from hidden sippers
+    // is smeared to all apps proportionally (except for screen usage).
+    double proportional_smear_mah = 6;
+  };
+  repeated PowerUseItem power_use_item = 17;
+
+  message PowerUseSummary {
+    double battery_capacity_mah = 1;
+    double computed_power_mah = 2;
+    // Lower bound of actual power drained.
+    double min_drained_power_mah = 3;
+    // Upper bound of actual power drained.
+    double max_drained_power_mah = 4;
+  };
+  PowerUseSummary power_use_summary = 18;
+
+  message ResourcePowerManager {
+    string name = 1;
+    TimerProto total = 2;
+    TimerProto screen_off = 3;
+  }
+  ResourcePowerManager resource_power_manager = 19;
+
+  message ScreenBrightness {
+    enum Name {
+      DARK = 0; // Not screen-off.
+      DIM = 1;
+      MEDIUM = 2;
+      LIGHT = 3;
+      BRIGHT = 4;
+    };
+    Name name = 1;
+    TimerProto total = 2;
+  };
+  repeated ScreenBrightness screen_brightness = 20;
+
+  // Duration and number of times trying to acquire a signal
+  TimerProto signal_scanning = 21;
+
+  message WakeupReason {
+    string name = 1;
+    TimerProto total = 2;
+  };
+  repeated WakeupReason wakeup_reason = 22;
+
+  message WifiSignalStrength {
+    enum Name {
+      NONE = 0;
+      POOR = 1;
+      MODERATE = 2;
+      GOOD = 3;
+      GREAT = 4;
+    };
+    Name name = 1;
+    TimerProto total = 2;
+  };
+  repeated WifiSignalStrength wifi_signal_strength = 23;
+
+  message WifiState {
+    enum Name {
+      OFF = 0;
+      OFF_SCANNING = 1;
+      ON_NO_NETWORKS = 2;
+      ON_DISCONNECTED = 3;
+      ON_CONNECTED_STA = 4;
+      ON_CONNECTED_P2P = 5;
+      ON_CONNECTED_STA_P2P = 6;
+      SOFT_AP = 7;
+    };
+    Name name = 1;
+    TimerProto total = 2;
+  };
+  repeated WifiState wifi_state = 24;
+
+  message WifiSupplicantState {
+    enum Name {
+      INVALID = 0;
+      DISCONNECTED = 1;
+      INTERFACE_DISABLED = 2;
+      INACTIVE = 3;
+      SCANNING = 4;
+      AUTHENTICATING = 5;
+      ASSOCIATING = 6;
+      ASSOCIATED = 7;
+      FOUR_WAY_HANDSHAKE = 8;
+      GROUP_HANDSHAKE = 9;
+      COMPLETED = 10;
+      DORMANT = 11;
+      UNINITIALIZED = 12;
+    };
+    Name name = 1;
+    TimerProto total = 2;
+  };
+  repeated WifiSupplicantState wifi_supplicant_state = 25;
 }
 
 message TimerProto {
diff --git a/core/proto/android/telephony/signalstrength.proto b/core/proto/android/telephony/signalstrength.proto
new file mode 100644
index 0000000..ff230cb
--- /dev/null
+++ b/core/proto/android/telephony/signalstrength.proto
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 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_package = "android.telephony";
+option java_multiple_files = true;
+
+package android.telephony;
+
+/**
+ * An android.telephony.SignalStrength object.
+ */
+message SignalStrengthProto {
+  enum StrengthName {
+    SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
+    SIGNAL_STRENGTH_POOR = 1;
+    SIGNAL_STRENGTH_MODERATE = 2;
+    SIGNAL_STRENGTH_GOOD = 3;
+    SIGNAL_STRENGTH_GREAT = 4;
+  }
+}