/*
 * 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.
 */

package com.android.server.am;

import android.os.BatteryStats;
import static android.os.BatteryStats.STATS_SINCE_CHARGED;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.health.HealthKeys;
import android.os.health.HealthStatsParceler;
import android.os.health.HealthStatsWriter;
import android.os.health.PackageHealthStats;
import android.os.health.ProcessHealthStats;
import android.os.health.PidHealthStats;
import android.os.health.ServiceHealthStats;
import android.os.health.TimerStat;
import android.os.health.UidHealthStats;
import android.util.SparseArray;

import java.util.Map;

public class HealthStatsBatteryStatsWriter {

    private final long mNowRealtimeMs;
    private final long mNowUptimeMs;

    public HealthStatsBatteryStatsWriter() {
        mNowRealtimeMs = SystemClock.elapsedRealtime();
        mNowUptimeMs = SystemClock.uptimeMillis();
    }

    /**
     * Writes the contents of a BatteryStats.Uid into a HealthStatsWriter.
     */
    @SuppressWarnings("deprecation")
    public void writeUid(HealthStatsWriter uidWriter, BatteryStats bs, BatteryStats.Uid uid) {
        int N;
        BatteryStats.Timer timer;
        SparseArray<? extends BatteryStats.Uid.Sensor> sensors;
        SparseArray<? extends BatteryStats.Uid.Pid> pids;
        BatteryStats.ControllerActivityCounter controller;
        long sum;

        //
        // It's a little odd for these first four to be here but it's not the end of the
        // world. It would be easy enough to duplicate them somewhere else if this API
        // grows.
        //

        // MEASUREMENT_REALTIME_BATTERY_MS
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_REALTIME_BATTERY_MS,
                bs.computeBatteryRealtime(mNowRealtimeMs*1000, STATS_SINCE_CHARGED)/1000);

        // MEASUREMENT_UPTIME_BATTERY_MS
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_UPTIME_BATTERY_MS,
                bs.computeBatteryUptime(mNowUptimeMs*1000, STATS_SINCE_CHARGED)/1000);

        // MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS,
                bs.computeBatteryScreenOffRealtime(
                    mNowRealtimeMs*1000, STATS_SINCE_CHARGED)/1000);

        // MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS,
                bs.computeBatteryScreenOffUptime(mNowUptimeMs*1000, STATS_SINCE_CHARGED)/1000);

        //
        // Now on to the real per-uid stats...
        //

        for (final Map.Entry<String,? extends BatteryStats.Uid.Wakelock> entry:
                uid.getWakelockStats().entrySet()) {
            final String key = entry.getKey();
            final BatteryStats.Uid.Wakelock wakelock = entry.getValue();

            // TIMERS_WAKELOCKS_FULL
            timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_FULL);
            addTimers(uidWriter, UidHealthStats.TIMERS_WAKELOCKS_FULL, key, timer);

            // TIMERS_WAKELOCKS_PARTIAL
            timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL);
            addTimers(uidWriter, UidHealthStats.TIMERS_WAKELOCKS_PARTIAL, key, timer);
            
            // TIMERS_WAKELOCKS_WINDOW
            timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_WINDOW);
            addTimers(uidWriter, UidHealthStats.TIMERS_WAKELOCKS_WINDOW, key, timer);
            
            // TIMERS_WAKELOCKS_DRAW
            timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_DRAW);
            addTimers(uidWriter, UidHealthStats.TIMERS_WAKELOCKS_DRAW, key, timer);
        }
        
        // TIMERS_SYNCS
        for (final Map.Entry<String,? extends BatteryStats.Timer> entry:
                uid.getSyncStats().entrySet()) {
            addTimers(uidWriter, UidHealthStats.TIMERS_SYNCS, entry.getKey(), entry.getValue());
        }

        // TIMERS_JOBS
        for (final Map.Entry<String,? extends BatteryStats.Timer> entry:
                uid.getJobStats().entrySet()) {
            addTimers(uidWriter, UidHealthStats.TIMERS_JOBS, entry.getKey(), entry.getValue());
        }

        // TIMERS_SENSORS
        sensors = uid.getSensorStats();
        N = sensors.size();
        for (int i=0; i<N; i++) {
            int sensorId = sensors.keyAt(i);
            // Battery Stats stores the GPS sensors with a bogus key in this API. Pull it out
            // as a separate metric here so as to not expose that in the API.
            if (sensorId == BatteryStats.Uid.Sensor.GPS) {
                addTimer(uidWriter, UidHealthStats.TIMER_GPS_SENSOR,
                        sensors.valueAt(i).getSensorTime());
            } else {
                addTimers(uidWriter, UidHealthStats.TIMERS_SENSORS, Integer.toString(sensorId),
                        sensors.valueAt(i).getSensorTime());
            }
        }

        // STATS_PIDS
        pids = uid.getPidStats();
        N = pids.size();
        for (int i=0; i<N; i++) {
            final HealthStatsWriter writer = new HealthStatsWriter(PidHealthStats.CONSTANTS);
            writePid(writer, pids.valueAt(i));
            uidWriter.addStats(UidHealthStats.STATS_PIDS, Integer.toString(pids.keyAt(i)), writer);
        }

        // STATS_PROCESSES
        for (final Map.Entry<String,? extends BatteryStats.Uid.Proc> entry:
                uid.getProcessStats().entrySet()) {
            final HealthStatsWriter writer = new HealthStatsWriter(ProcessHealthStats.CONSTANTS);
            writeProc(writer, entry.getValue());
            uidWriter.addStats(UidHealthStats.STATS_PROCESSES, entry.getKey(), writer);
        }

        // STATS_PACKAGES
        for (final Map.Entry<String,? extends BatteryStats.Uid.Pkg> entry:
                uid.getPackageStats().entrySet()) {
            final HealthStatsWriter writer = new HealthStatsWriter(PackageHealthStats.CONSTANTS);
            writePkg(writer, entry.getValue());
            uidWriter.addStats(UidHealthStats.STATS_PACKAGES, entry.getKey(), writer);
        }

        controller = uid.getWifiControllerActivity();
        if (controller != null) {
            // MEASUREMENT_WIFI_IDLE_MS
            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_IDLE_MS,
                    controller.getIdleTimeCounter().getCountLocked(STATS_SINCE_CHARGED));
            // MEASUREMENT_WIFI_RX_MS
            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RX_MS,
                    controller.getRxTimeCounter().getCountLocked(STATS_SINCE_CHARGED));
            // MEASUREMENT_WIFI_TX_MS
            sum = 0;
            for (final BatteryStats.LongCounter counter: controller.getTxTimeCounters()) {
                sum += counter.getCountLocked(STATS_SINCE_CHARGED);
            }
            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_TX_MS, sum);
            // MEASUREMENT_WIFI_POWER_MAMS
            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_POWER_MAMS,
                    controller.getPowerCounter().getCountLocked(STATS_SINCE_CHARGED));
        }

        controller = uid.getBluetoothControllerActivity();
        if (controller != null) {
            // MEASUREMENT_BLUETOOTH_IDLE_MS
            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_IDLE_MS,
                    controller.getIdleTimeCounter().getCountLocked(STATS_SINCE_CHARGED));
            // MEASUREMENT_BLUETOOTH_RX_MS
            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_RX_MS,
                    controller.getRxTimeCounter().getCountLocked(STATS_SINCE_CHARGED));
            // MEASUREMENT_BLUETOOTH_TX_MS
            sum = 0;
            for (final BatteryStats.LongCounter counter: controller.getTxTimeCounters()) {
                sum += counter.getCountLocked(STATS_SINCE_CHARGED);
            }
            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_TX_MS, sum);
            // MEASUREMENT_BLUETOOTH_POWER_MAMS
            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_POWER_MAMS,
                    controller.getPowerCounter().getCountLocked(STATS_SINCE_CHARGED));
        }

        controller = uid.getModemControllerActivity();
        if (controller != null) {
            // MEASUREMENT_MOBILE_IDLE_MS
            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_IDLE_MS,
                    controller.getIdleTimeCounter().getCountLocked(STATS_SINCE_CHARGED));
            // MEASUREMENT_MOBILE_RX_MS
            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_RX_MS,
                    controller.getRxTimeCounter().getCountLocked(STATS_SINCE_CHARGED));
            // MEASUREMENT_MOBILE_TX_MS
            sum = 0;
            for (final BatteryStats.LongCounter counter: controller.getTxTimeCounters()) {
                sum += counter.getCountLocked(STATS_SINCE_CHARGED);
            }
            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_TX_MS, sum);
            // MEASUREMENT_MOBILE_POWER_MAMS
            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_POWER_MAMS,
                    controller.getPowerCounter().getCountLocked(STATS_SINCE_CHARGED));
        }

        // MEASUREMENT_WIFI_RUNNING_MS
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RUNNING_MS,
                uid.getWifiRunningTime(mNowRealtimeMs*1000, STATS_SINCE_CHARGED)/1000);

        // MEASUREMENT_WIFI_FULL_LOCK_MS
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_FULL_LOCK_MS,
                uid.getFullWifiLockTime(mNowRealtimeMs*1000, STATS_SINCE_CHARGED)/1000);

        // TIMER_WIFI_SCAN
        uidWriter.addTimer(UidHealthStats.TIMER_WIFI_SCAN,
                uid.getWifiScanCount(STATS_SINCE_CHARGED),
                uid.getWifiScanTime(mNowRealtimeMs*1000, STATS_SINCE_CHARGED)/1000);

        // MEASUREMENT_WIFI_MULTICAST_MS
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_MULTICAST_MS,
                uid.getWifiMulticastTime(mNowRealtimeMs*1000, STATS_SINCE_CHARGED)/1000);

        // TIMER_AUDIO
        addTimer(uidWriter, UidHealthStats.TIMER_AUDIO, uid.getAudioTurnedOnTimer());

        // TIMER_VIDEO
        addTimer(uidWriter, UidHealthStats.TIMER_VIDEO, uid.getVideoTurnedOnTimer());

        // TIMER_FLASHLIGHT
        addTimer(uidWriter, UidHealthStats.TIMER_FLASHLIGHT, uid.getFlashlightTurnedOnTimer());

        // TIMER_CAMERA
        addTimer(uidWriter, UidHealthStats.TIMER_CAMERA, uid.getCameraTurnedOnTimer());

        // TIMER_FOREGROUND_ACTIVITY
        addTimer(uidWriter, UidHealthStats.TIMER_FOREGROUND_ACTIVITY,
                uid.getForegroundActivityTimer());

        // TIMER_BLUETOOTH_SCAN
        addTimer(uidWriter, UidHealthStats.TIMER_BLUETOOTH_SCAN, uid.getBluetoothScanTimer());

        // TIMER_PROCESS_STATE_TOP_MS
        addTimer(uidWriter, UidHealthStats.TIMER_PROCESS_STATE_TOP_MS,
                uid.getProcessStateTimer(BatteryStats.Uid.PROCESS_STATE_TOP));

        // TIMER_PROCESS_STATE_FOREGROUND_SERVICE_MS
        addTimer(uidWriter, UidHealthStats.TIMER_PROCESS_STATE_FOREGROUND_SERVICE_MS,
                uid.getProcessStateTimer(BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE));

        // TIMER_PROCESS_STATE_TOP_SLEEPING_MS
        addTimer(uidWriter, UidHealthStats.TIMER_PROCESS_STATE_TOP_SLEEPING_MS,
                uid.getProcessStateTimer(BatteryStats.Uid.PROCESS_STATE_TOP_SLEEPING));

        // TIMER_PROCESS_STATE_FOREGROUND_MS
        addTimer(uidWriter, UidHealthStats.TIMER_PROCESS_STATE_FOREGROUND_MS,
                uid.getProcessStateTimer(BatteryStats.Uid.PROCESS_STATE_FOREGROUND));

        // TIMER_PROCESS_STATE_BACKGROUND_MS
        addTimer(uidWriter, UidHealthStats.TIMER_PROCESS_STATE_BACKGROUND_MS,
                uid.getProcessStateTimer(BatteryStats.Uid.PROCESS_STATE_BACKGROUND));

        // TIMER_PROCESS_STATE_CACHED_MS
        addTimer(uidWriter, UidHealthStats.TIMER_PROCESS_STATE_CACHED_MS,
                uid.getProcessStateTimer(BatteryStats.Uid.PROCESS_STATE_CACHED));

        // TIMER_VIBRATOR
        addTimer(uidWriter, UidHealthStats.TIMER_VIBRATOR, uid.getVibratorOnTimer());

        // MEASUREMENT_OTHER_USER_ACTIVITY_COUNT
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_OTHER_USER_ACTIVITY_COUNT,
                uid.getUserActivityCount(PowerManager.USER_ACTIVITY_EVENT_OTHER,
                    STATS_SINCE_CHARGED));

        // MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT,
                uid.getUserActivityCount(PowerManager.USER_ACTIVITY_EVENT_BUTTON,
                    STATS_SINCE_CHARGED));

        // MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT,
                uid.getUserActivityCount(PowerManager.USER_ACTIVITY_EVENT_TOUCH,
                    STATS_SINCE_CHARGED));

        // MEASUREMENT_MOBILE_RX_BYTES
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_RX_BYTES,
                uid.getNetworkActivityBytes(BatteryStats.NETWORK_MOBILE_RX_DATA,
                    STATS_SINCE_CHARGED));

        // MEASUREMENT_MOBILE_TX_BYTES
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_TX_BYTES,
                uid.getNetworkActivityBytes(BatteryStats.NETWORK_MOBILE_TX_DATA,
                    STATS_SINCE_CHARGED));

        // MEASUREMENT_WIFI_RX_BYTES
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RX_BYTES,
                uid.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_RX_DATA,
                    STATS_SINCE_CHARGED));

        // MEASUREMENT_WIFI_TX_BYTES
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_TX_BYTES,
                uid.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_TX_DATA,
                    STATS_SINCE_CHARGED));

        // MEASUREMENT_BLUETOOTH_RX_BYTES
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_RX_BYTES,
                uid.getNetworkActivityBytes(BatteryStats.NETWORK_BT_RX_DATA,
                    STATS_SINCE_CHARGED));

        // MEASUREMENT_BLUETOOTH_TX_BYTES
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_TX_BYTES,
                uid.getNetworkActivityBytes(BatteryStats.NETWORK_BT_TX_DATA,
                    STATS_SINCE_CHARGED));

        // MEASUREMENT_MOBILE_RX_PACKETS
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_RX_PACKETS,
                uid.getNetworkActivityPackets(BatteryStats.NETWORK_MOBILE_RX_DATA,
                    STATS_SINCE_CHARGED));

        // MEASUREMENT_MOBILE_TX_PACKETS
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_TX_PACKETS,
                uid.getNetworkActivityPackets(BatteryStats.NETWORK_MOBILE_TX_DATA,
                    STATS_SINCE_CHARGED));

        // MEASUREMENT_WIFI_RX_PACKETS
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RX_PACKETS,
                uid.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_RX_DATA,
                    STATS_SINCE_CHARGED));

        // MEASUREMENT_WIFI_TX_PACKETS
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_TX_PACKETS,
                uid.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_TX_DATA,
                    STATS_SINCE_CHARGED));

        // MEASUREMENT_BLUETOOTH_RX_PACKETS
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_RX_PACKETS,
                uid.getNetworkActivityPackets(BatteryStats.NETWORK_BT_RX_DATA,
                    STATS_SINCE_CHARGED));

        // MEASUREMENT_BLUETOOTH_TX_PACKETS
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_TX_PACKETS,
                uid.getNetworkActivityPackets(BatteryStats.NETWORK_BT_TX_DATA,
                    STATS_SINCE_CHARGED));

        // TIMER_MOBILE_RADIO_ACTIVE
        uidWriter.addTimer(UidHealthStats.TIMER_MOBILE_RADIO_ACTIVE,
                uid.getMobileRadioActiveCount(STATS_SINCE_CHARGED),
                uid.getMobileRadioActiveTime(STATS_SINCE_CHARGED));

        // MEASUREMENT_USER_CPU_TIME_MS
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_USER_CPU_TIME_MS,
                uid.getUserCpuTimeUs(STATS_SINCE_CHARGED)/1000);

        // MEASUREMENT_SYSTEM_CPU_TIME_MS
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_SYSTEM_CPU_TIME_MS,
                uid.getSystemCpuTimeUs(STATS_SINCE_CHARGED)/1000);

        // MEASUREMENT_CPU_POWER_MAMS
        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_CPU_POWER_MAMS, 0);
    }

    /**
     * Writes the contents of a BatteryStats.Uid.Pid into a HealthStatsWriter.
     */
    public void writePid(HealthStatsWriter pidWriter, BatteryStats.Uid.Pid pid) {
        if (pid == null) {
            return;
        }

        // MEASUREMENT_WAKE_NESTING_COUNT
        pidWriter.addMeasurement(PidHealthStats.MEASUREMENT_WAKE_NESTING_COUNT, pid.mWakeNesting);

        // MEASUREMENT_WAKE_SUM_MS
        pidWriter.addMeasurement(PidHealthStats.MEASUREMENT_WAKE_SUM_MS, pid.mWakeSumMs);

        // MEASUREMENT_WAKE_START_MS
        pidWriter.addMeasurement(PidHealthStats.MEASUREMENT_WAKE_SUM_MS, pid.mWakeStartMs);
    }

    /**
     * Writes the contents of a BatteryStats.Uid.Proc into a HealthStatsWriter.
     */
    public void writeProc(HealthStatsWriter procWriter, BatteryStats.Uid.Proc proc) {
        // MEASUREMENT_USER_TIME_MS
        procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_USER_TIME_MS,
                proc.getUserTime(STATS_SINCE_CHARGED));

        // MEASUREMENT_SYSTEM_TIME_MS
        procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_SYSTEM_TIME_MS,
                proc.getSystemTime(STATS_SINCE_CHARGED));

        // MEASUREMENT_STARTS_COUNT
        procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_STARTS_COUNT,
                proc.getStarts(STATS_SINCE_CHARGED));

        // MEASUREMENT_CRASHES_COUNT
        procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_CRASHES_COUNT,
                proc.getNumCrashes(STATS_SINCE_CHARGED));

        // MEASUREMENT_ANR_COUNT
        procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_ANR_COUNT,
                proc.getNumAnrs(STATS_SINCE_CHARGED));

        // MEASUREMENT_FOREGROUND_MS
        procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_FOREGROUND_MS,
                proc.getForegroundTime(STATS_SINCE_CHARGED));
    }

    /**
     * Writes the contents of a BatteryStats.Uid.Pkg into a HealthStatsWriter.
     */
    public void writePkg(HealthStatsWriter pkgWriter, BatteryStats.Uid.Pkg pkg) {
        // STATS_SERVICES
        for (final Map.Entry<String,? extends BatteryStats.Uid.Pkg.Serv> entry:
                pkg.getServiceStats().entrySet()) {
            final HealthStatsWriter writer = new HealthStatsWriter(ServiceHealthStats.CONSTANTS);
            writeServ(writer, entry.getValue());
            pkgWriter.addStats(PackageHealthStats.STATS_SERVICES, entry.getKey(), writer);
        }

        // MEASUREMENTS_WAKEUP_ALARMS_COUNT
        for (final Map.Entry<String,? extends BatteryStats.Counter> entry:
                pkg.getWakeupAlarmStats().entrySet()) {
            final BatteryStats.Counter counter = entry.getValue();
            if (counter != null) {
                pkgWriter.addMeasurements(PackageHealthStats.MEASUREMENTS_WAKEUP_ALARMS_COUNT,
                        entry.getKey(), counter.getCountLocked(STATS_SINCE_CHARGED));
            }
        }
    }

    /**
     * Writes the contents of a BatteryStats.Uid.Pkg.Serv into a HealthStatsWriter.
     */
    public void writeServ(HealthStatsWriter servWriter, BatteryStats.Uid.Pkg.Serv serv) {
        // MEASUREMENT_START_SERVICE_COUNT
        servWriter.addMeasurement(ServiceHealthStats.MEASUREMENT_START_SERVICE_COUNT,
                serv.getStarts(STATS_SINCE_CHARGED));

        // MEASUREMENT_LAUNCH_COUNT
        servWriter.addMeasurement(ServiceHealthStats.MEASUREMENT_LAUNCH_COUNT,
                serv.getLaunches(STATS_SINCE_CHARGED));
    }

    /**
     * Adds a BatteryStats.Timer into a HealthStatsWriter. Safe to pass a null timer.
     */
    private void addTimer(HealthStatsWriter writer, int key, BatteryStats.Timer timer) {
        if (timer != null) {
            writer.addTimer(key, timer.getCountLocked(STATS_SINCE_CHARGED),
                    timer.getTotalTimeLocked(mNowRealtimeMs*1000, STATS_SINCE_CHARGED) / 1000);
        }
    }

    /**
     * Adds a named BatteryStats.Timer into a HealthStatsWriter. Safe to pass a null timer.
     */
    private void addTimers(HealthStatsWriter writer, int key, String name,
            BatteryStats.Timer timer) {
        if (timer != null) {
            writer.addTimers(key, name, new TimerStat(timer.getCountLocked(STATS_SINCE_CHARGED),
                    timer.getTotalTimeLocked(mNowRealtimeMs*1000, STATS_SINCE_CHARGED) / 1000));
        }
    }
}

