Search in sources :

Example 71 with BatterySipper

use of com.android.internal.os.BatterySipper in project Resurrection_packages_apps_Settings by ResurrectionRemix.

the class BatteryUtils method smearScreenBatterySipper.

/**
 * Smear the screen on power usage among {@code sippers}, based on ratio of foreground activity
 * time.
 */
@VisibleForTesting
void smearScreenBatterySipper(List<BatterySipper> sippers, BatterySipper screenSipper) {
    long totalActivityTimeMs = 0;
    final SparseLongArray activityTimeArray = new SparseLongArray();
    for (int i = 0, size = sippers.size(); i < size; i++) {
        final BatteryStats.Uid uid = sippers.get(i).uidObj;
        if (uid != null) {
            final long timeMs = getProcessTimeMs(StatusType.SCREEN_USAGE, uid, BatteryStats.STATS_SINCE_CHARGED);
            activityTimeArray.put(uid.getUid(), timeMs);
            totalActivityTimeMs += timeMs;
        }
    }
    if (totalActivityTimeMs >= 10 * DateUtils.MINUTE_IN_MILLIS) {
        if (screenSipper == null) {
            Log.e(TAG, "screen sipper is null even when app screen time is not zero");
            return;
        }
        final double screenPowerMah = screenSipper.totalPowerMah;
        for (int i = 0, size = sippers.size(); i < size; i++) {
            final BatterySipper sipper = sippers.get(i);
            sipper.totalPowerMah += screenPowerMah * activityTimeArray.get(sipper.getUid(), 0) / totalActivityTimeMs;
        }
    }
}
Also used : BatterySipper(com.android.internal.os.BatterySipper) SparseLongArray(android.util.SparseLongArray) BatteryStats(android.os.BatteryStats) VisibleForTesting(androidx.annotation.VisibleForTesting)

Example 72 with BatterySipper

use of com.android.internal.os.BatterySipper in project Resurrection_packages_apps_Settings by ResurrectionRemix.

the class HighUsageDetector method detect.

@Override
public BatteryTip detect() {
    final long lastFullChargeTimeMs = mBatteryUtils.calculateLastFullChargeTime(mBatteryStatsHelper, System.currentTimeMillis());
    if (mPolicy.highUsageEnabled && mDischarging) {
        parseBatteryData();
        if (mDataParser.isDeviceHeavilyUsed() || mPolicy.testHighUsageTip) {
            final BatteryStats batteryStats = mBatteryStatsHelper.getStats();
            final List<BatterySipper> batterySippers = new ArrayList<>(mBatteryStatsHelper.getUsageList());
            final double totalPower = mBatteryStatsHelper.getTotalPower();
            final int dischargeAmount = batteryStats != null ? batteryStats.getDischargeAmount(BatteryStats.STATS_SINCE_CHARGED) : 0;
            Collections.sort(batterySippers, (sipper1, sipper2) -> Double.compare(sipper2.totalSmearedPowerMah, sipper1.totalSmearedPowerMah));
            for (BatterySipper batterySipper : batterySippers) {
                final double percent = mBatteryUtils.calculateBatteryPercent(batterySipper.totalSmearedPowerMah, totalPower, 0, dischargeAmount);
                if ((percent + 0.5f < 1f) || mBatteryUtils.shouldHideSipper(batterySipper)) {
                    // Don't show it if we should hide or usage percentage is lower than 1%
                    continue;
                }
                mHighUsageAppList.add(new AppInfo.Builder().setUid(batterySipper.getUid()).setPackageName(mBatteryUtils.getPackageName(batterySipper.getUid())).build());
                if (mHighUsageAppList.size() >= mPolicy.highUsageAppCount) {
                    break;
                }
            }
            // When in test mode, add an app if necessary
            if (mPolicy.testHighUsageTip && mHighUsageAppList.isEmpty()) {
                mHighUsageAppList.add(new AppInfo.Builder().setPackageName(SETTINGS_PACKAGE_NAME).setScreenOnTimeMs(TimeUnit.HOURS.toMillis(3)).build());
            }
        }
    }
    return new HighUsageTip(lastFullChargeTimeMs, mHighUsageAppList);
}
Also used : HighUsageTip(com.android.settings.fuelgauge.batterytip.tips.HighUsageTip) BatterySipper(com.android.internal.os.BatterySipper) ArrayList(java.util.ArrayList) BatteryStats(android.os.BatteryStats)

Example 73 with BatterySipper

use of com.android.internal.os.BatterySipper in project platform_frameworks_base by android.

the class BatteryStats method dumpCheckinLocked.

/**
     * Checkin server version of dump to produce more compact, computer-readable log.
     * 
     * NOTE: all times are expressed in 'ms'.
     */
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 batteryUptime = getBatteryUptime(rawUptime);
    final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
    final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
    final long whichBatteryScreenOffUptime = computeBatteryScreenOffUptime(rawUptime, which);
    final long whichBatteryScreenOffRealtime = computeBatteryScreenOffRealtime(rawRealtime, which);
    final long totalRealtime = computeRealtime(rawRealtime, which);
    final long totalUptime = computeUptime(rawUptime, which);
    final long screenOnTime = getScreenOnTime(rawRealtime, which);
    final long interactiveTime = getInteractiveTime(rawRealtime, which);
    final long powerSaveModeEnabledTime = getPowerSaveModeEnabledTime(rawRealtime, which);
    final long deviceIdleModeLightTime = getDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT, rawRealtime, which);
    final long deviceIdleModeFullTime = getDeviceIdleModeTime(DEVICE_IDLE_MODE_DEEP, rawRealtime, which);
    final long deviceLightIdlingTime = getDeviceIdlingTime(DEVICE_IDLE_MODE_LIGHT, rawRealtime, which);
    final long deviceIdlingTime = getDeviceIdlingTime(DEVICE_IDLE_MODE_DEEP, rawRealtime, which);
    final int connChanges = getNumConnectivityChange(which);
    final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
    final long dischargeCount = getDischargeCoulombCounter().getCountLocked(which);
    final long dischargeScreenOffCount = getDischargeScreenOffCoulombCounter().getCountLocked(which);
    final StringBuilder sb = new StringBuilder(128);
    final SparseArray<? extends Uid> uidStats = getUidStats();
    final int NU = uidStats.size();
    final String category = STAT_NAMES[which];
    // Dump "battery" stat
    dumpLine(pw, 0, /* uid */
    category, BATTERY_DATA, which == STATS_SINCE_CHARGED ? getStartCount() : "N/A", whichBatteryRealtime / 1000, whichBatteryUptime / 1000, totalRealtime / 1000, totalUptime / 1000, getStartClockTime(), whichBatteryScreenOffRealtime / 1000, whichBatteryScreenOffUptime / 1000, getEstimatedBatteryCapacity());
    // Calculate wakelock times across all uids.
    long fullWakeLockTimeTotal = 0;
    long partialWakeLockTimeTotal = 0;
    for (int iu = 0; iu < NU; 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) {
                fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(rawRealtime, which);
            }
            final Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
            if (partialWakeTimer != null) {
                partialWakeLockTimeTotal += partialWakeTimer.getTotalTimeLocked(rawRealtime, which);
            }
        }
    }
    // Dump network stats
    final long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
    final long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
    final long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
    final long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
    final long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
    final long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
    final long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
    final long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
    final long btRxTotalBytes = getNetworkActivityBytes(NETWORK_BT_RX_DATA, which);
    final long btTxTotalBytes = getNetworkActivityBytes(NETWORK_BT_TX_DATA, which);
    dumpLine(pw, 0, /* uid */
    category, GLOBAL_NETWORK_DATA, mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes, mobileRxTotalPackets, mobileTxTotalPackets, wifiRxTotalPackets, wifiTxTotalPackets, btRxTotalBytes, btTxTotalBytes);
    // Dump Modem controller stats
    dumpControllerActivityLine(pw, 0, /* uid */
    category, GLOBAL_MODEM_CONTROLLER_DATA, getModemControllerActivity(), which);
    // Dump Wifi controller stats
    final long wifiOnTime = getWifiOnTime(rawRealtime, which);
    final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
    dumpLine(pw, 0, /* uid */
    category, GLOBAL_WIFI_DATA, wifiOnTime / 1000, wifiRunningTime / 1000, /* legacy fields follow, keep at 0 */
    0, 0, 0);
    dumpControllerActivityLine(pw, 0, /* uid */
    category, GLOBAL_WIFI_CONTROLLER_DATA, getWifiControllerActivity(), which);
    // Dump Bluetooth controller stats
    dumpControllerActivityLine(pw, 0, /* uid */
    category, GLOBAL_BLUETOOTH_CONTROLLER_DATA, getBluetoothControllerActivity(), which);
    // Dump misc stats
    dumpLine(pw, 0, /* uid */
    category, MISC_DATA, screenOnTime / 1000, phoneOnTime / 1000, fullWakeLockTimeTotal / 1000, partialWakeLockTimeTotal / 1000, getMobileRadioActiveTime(rawRealtime, which) / 1000, getMobileRadioActiveAdjustedTime(which) / 1000, interactiveTime / 1000, powerSaveModeEnabledTime / 1000, connChanges, deviceIdleModeFullTime / 1000, getDeviceIdleModeCount(DEVICE_IDLE_MODE_DEEP, which), deviceIdlingTime / 1000, getDeviceIdlingCount(DEVICE_IDLE_MODE_DEEP, which), getMobileRadioActiveCount(which), getMobileRadioActiveUnknownTime(which) / 1000, deviceIdleModeLightTime / 1000, getDeviceIdleModeCount(DEVICE_IDLE_MODE_LIGHT, which), deviceLightIdlingTime / 1000, getDeviceIdlingCount(DEVICE_IDLE_MODE_LIGHT, which), getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT), getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_DEEP));
    // Dump screen brightness stats
    Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
    for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
        args[i] = getScreenBrightnessTime(i, rawRealtime, which) / 1000;
    }
    dumpLine(pw, 0, /* uid */
    category, SCREEN_BRIGHTNESS_DATA, args);
    // Dump signal strength stats
    args = new Object[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
    for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
        args[i] = getPhoneSignalStrengthTime(i, rawRealtime, which) / 1000;
    }
    dumpLine(pw, 0, /* uid */
    category, SIGNAL_STRENGTH_TIME_DATA, args);
    dumpLine(pw, 0, /* uid */
    category, SIGNAL_SCANNING_TIME_DATA, getPhoneSignalScanningTime(rawRealtime, which) / 1000);
    for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
        args[i] = getPhoneSignalStrengthCount(i, which);
    }
    dumpLine(pw, 0, /* uid */
    category, SIGNAL_STRENGTH_COUNT_DATA, args);
    // Dump network type stats
    args = new Object[NUM_DATA_CONNECTION_TYPES];
    for (int i = 0; i < NUM_DATA_CONNECTION_TYPES; i++) {
        args[i] = getPhoneDataConnectionTime(i, rawRealtime, which) / 1000;
    }
    dumpLine(pw, 0, /* uid */
    category, DATA_CONNECTION_TIME_DATA, args);
    for (int i = 0; i < NUM_DATA_CONNECTION_TYPES; i++) {
        args[i] = getPhoneDataConnectionCount(i, which);
    }
    dumpLine(pw, 0, /* uid */
    category, DATA_CONNECTION_COUNT_DATA, args);
    // Dump wifi state stats
    args = new Object[NUM_WIFI_STATES];
    for (int i = 0; i < NUM_WIFI_STATES; i++) {
        args[i] = getWifiStateTime(i, rawRealtime, which) / 1000;
    }
    dumpLine(pw, 0, /* uid */
    category, WIFI_STATE_TIME_DATA, args);
    for (int i = 0; i < NUM_WIFI_STATES; i++) {
        args[i] = getWifiStateCount(i, which);
    }
    dumpLine(pw, 0, /* uid */
    category, WIFI_STATE_COUNT_DATA, args);
    // Dump wifi suppl state stats
    args = new Object[NUM_WIFI_SUPPL_STATES];
    for (int i = 0; i < NUM_WIFI_SUPPL_STATES; i++) {
        args[i] = getWifiSupplStateTime(i, rawRealtime, which) / 1000;
    }
    dumpLine(pw, 0, /* uid */
    category, WIFI_SUPPL_STATE_TIME_DATA, args);
    for (int i = 0; i < NUM_WIFI_SUPPL_STATES; i++) {
        args[i] = getWifiSupplStateCount(i, which);
    }
    dumpLine(pw, 0, /* uid */
    category, WIFI_SUPPL_STATE_COUNT_DATA, args);
    // Dump wifi signal strength stats
    args = new Object[NUM_WIFI_SIGNAL_STRENGTH_BINS];
    for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
        args[i] = getWifiSignalStrengthTime(i, rawRealtime, which) / 1000;
    }
    dumpLine(pw, 0, /* uid */
    category, WIFI_SIGNAL_STRENGTH_TIME_DATA, args);
    for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
        args[i] = getWifiSignalStrengthCount(i, which);
    }
    dumpLine(pw, 0, /* uid */
    category, WIFI_SIGNAL_STRENGTH_COUNT_DATA, args);
    if (which == STATS_SINCE_UNPLUGGED) {
        dumpLine(pw, 0, /* uid */
        category, BATTERY_LEVEL_DATA, getDischargeStartLevel(), getDischargeCurrentLevel());
    }
    if (which == STATS_SINCE_UNPLUGGED) {
        dumpLine(pw, 0, /* uid */
        category, BATTERY_DISCHARGE_DATA, getDischargeStartLevel() - getDischargeCurrentLevel(), getDischargeStartLevel() - getDischargeCurrentLevel(), getDischargeAmountScreenOn(), getDischargeAmountScreenOff(), dischargeCount / 1000, dischargeScreenOffCount / 1000);
    } else {
        dumpLine(pw, 0, /* uid */
        category, BATTERY_DISCHARGE_DATA, getLowDischargeAmountSinceCharge(), getHighDischargeAmountSinceCharge(), getDischargeAmountScreenOnSinceCharge(), getDischargeAmountScreenOffSinceCharge(), dischargeCount / 1000, dischargeScreenOffCount / 1000);
    }
    if (reqUid < 0) {
        final Map<String, ? extends Timer> kernelWakelocks = getKernelWakelockStats();
        if (kernelWakelocks.size() > 0) {
            for (Map.Entry<String, ? extends Timer> ent : kernelWakelocks.entrySet()) {
                sb.setLength(0);
                printWakeLockCheckin(sb, ent.getValue(), rawRealtime, null, which, "");
                dumpLine(pw, 0, /* uid */
                category, KERNEL_WAKELOCK_DATA, ent.getKey(), sb.toString());
            }
        }
        final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
        if (wakeupReasons.size() > 0) {
            for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) {
                // Not doing the regular wake lock formatting to remain compatible
                // with the old checkin format.
                long totalTimeMicros = ent.getValue().getTotalTimeLocked(rawRealtime, which);
                int count = ent.getValue().getCountLocked(which);
                dumpLine(pw, 0, /* uid */
                category, WAKEUP_REASON_DATA, "\"" + ent.getKey() + "\"", (totalTimeMicros + 500) / 1000, count);
            }
        }
    }
    final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
    helper.create(this);
    helper.refreshStats(which, UserHandle.USER_ALL);
    final List<BatterySipper> sippers = helper.getUsageList();
    if (sippers != null && sippers.size() > 0) {
        dumpLine(pw, 0, /* uid */
        category, POWER_USE_SUMMARY_DATA, BatteryStatsHelper.makemAh(helper.getPowerProfile().getBatteryCapacity()), BatteryStatsHelper.makemAh(helper.getComputedPower()), BatteryStatsHelper.makemAh(helper.getMinDrainedPower()), BatteryStatsHelper.makemAh(helper.getMaxDrainedPower()));
        for (int i = 0; i < sippers.size(); i++) {
            final BatterySipper bs = sippers.get(i);
            int uid = 0;
            String label;
            switch(bs.drainType) {
                case IDLE:
                    label = "idle";
                    break;
                case CELL:
                    label = "cell";
                    break;
                case PHONE:
                    label = "phone";
                    break;
                case WIFI:
                    label = "wifi";
                    break;
                case BLUETOOTH:
                    label = "blue";
                    break;
                case SCREEN:
                    label = "scrn";
                    break;
                case FLASHLIGHT:
                    label = "flashlight";
                    break;
                case APP:
                    uid = bs.uidObj.getUid();
                    label = "uid";
                    break;
                case USER:
                    uid = UserHandle.getUid(bs.userId, 0);
                    label = "user";
                    break;
                case UNACCOUNTED:
                    label = "unacc";
                    break;
                case OVERCOUNTED:
                    label = "over";
                    break;
                case CAMERA:
                    label = "camera";
                    break;
                default:
                    label = "???";
            }
            dumpLine(pw, uid, category, POWER_USE_ITEM_DATA, label, BatteryStatsHelper.makemAh(bs.totalPowerMah));
        }
    }
    for (int iu = 0; iu < NU; iu++) {
        final int uid = uidStats.keyAt(iu);
        if (reqUid >= 0 && uid != reqUid) {
            continue;
        }
        final Uid u = uidStats.valueAt(iu);
        // Dump Network stats per uid, if any
        final long mobileBytesRx = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
        final long mobileBytesTx = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
        final long wifiBytesRx = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
        final long wifiBytesTx = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
        final long mobilePacketsRx = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
        final long mobilePacketsTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
        final long mobileActiveTime = u.getMobileRadioActiveTime(which);
        final int mobileActiveCount = u.getMobileRadioActiveCount(which);
        final long mobileWakeup = u.getMobileRadioApWakeupCount(which);
        final long wifiPacketsRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
        final long wifiPacketsTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
        final long wifiWakeup = u.getWifiRadioApWakeupCount(which);
        final long btBytesRx = u.getNetworkActivityBytes(NETWORK_BT_RX_DATA, which);
        final long btBytesTx = u.getNetworkActivityBytes(NETWORK_BT_TX_DATA, which);
        if (mobileBytesRx > 0 || mobileBytesTx > 0 || wifiBytesRx > 0 || wifiBytesTx > 0 || mobilePacketsRx > 0 || mobilePacketsTx > 0 || wifiPacketsRx > 0 || wifiPacketsTx > 0 || mobileActiveTime > 0 || mobileActiveCount > 0 || btBytesRx > 0 || btBytesTx > 0 || mobileWakeup > 0 || wifiWakeup > 0) {
            dumpLine(pw, uid, category, NETWORK_DATA, mobileBytesRx, mobileBytesTx, wifiBytesRx, wifiBytesTx, mobilePacketsRx, mobilePacketsTx, wifiPacketsRx, wifiPacketsTx, mobileActiveTime, mobileActiveCount, btBytesRx, btBytesTx, mobileWakeup, wifiWakeup);
        }
        // Dump modem controller data, per UID.
        dumpControllerActivityLine(pw, uid, category, MODEM_CONTROLLER_DATA, u.getModemControllerActivity(), which);
        // Dump Wifi controller data, per UID.
        final long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
        final long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
        final int wifiScanCount = u.getWifiScanCount(which);
        final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
        if (fullWifiLockOnTime != 0 || wifiScanTime != 0 || wifiScanCount != 0 || uidWifiRunningTime != 0) {
            dumpLine(pw, uid, category, WIFI_DATA, fullWifiLockOnTime, wifiScanTime, uidWifiRunningTime, wifiScanCount, /* legacy fields follow, keep at 0 */
            0, 0, 0);
        }
        dumpControllerActivityLine(pw, uid, category, WIFI_CONTROLLER_DATA, u.getWifiControllerActivity(), which);
        dumpTimer(pw, uid, category, BLUETOOTH_MISC_DATA, u.getBluetoothScanTimer(), rawRealtime, which);
        dumpControllerActivityLine(pw, uid, category, BLUETOOTH_CONTROLLER_DATA, u.getBluetoothControllerActivity(), which);
        if (u.hasUserActivity()) {
            args = new Object[Uid.NUM_USER_ACTIVITY_TYPES];
            boolean hasData = false;
            for (int i = 0; i < Uid.NUM_USER_ACTIVITY_TYPES; i++) {
                int val = u.getUserActivityCount(i, which);
                args[i] = val;
                if (val != 0)
                    hasData = true;
            }
            if (hasData) {
                dumpLine(pw, uid, /* uid */
                category, USER_ACTIVITY_DATA, args);
            }
        }
        final ArrayMap<String, ? extends Uid.Wakelock> wakelocks = u.getWakelockStats();
        for (int iw = wakelocks.size() - 1; iw >= 0; iw--) {
            final Uid.Wakelock wl = wakelocks.valueAt(iw);
            String linePrefix = "";
            sb.setLength(0);
            linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL), rawRealtime, "f", which, linePrefix);
            linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), rawRealtime, "p", which, linePrefix);
            linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime, "w", which, linePrefix);
            // Only log if we had at lease one wakelock...
            if (sb.length() > 0) {
                String name = wakelocks.keyAt(iw);
                if (name.indexOf(',') >= 0) {
                    name = name.replace(',', '_');
                }
                dumpLine(pw, uid, category, WAKELOCK_DATA, name, sb.toString());
            }
        }
        final ArrayMap<String, ? extends Timer> syncs = u.getSyncStats();
        for (int isy = syncs.size() - 1; isy >= 0; isy--) {
            final Timer timer = syncs.valueAt(isy);
            // Convert from microseconds to milliseconds with rounding
            final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
            final int count = timer.getCountLocked(which);
            if (totalTime != 0) {
                dumpLine(pw, uid, category, SYNC_DATA, syncs.keyAt(isy), totalTime, count);
            }
        }
        final ArrayMap<String, ? extends Timer> jobs = u.getJobStats();
        for (int ij = jobs.size() - 1; ij >= 0; ij--) {
            final Timer timer = jobs.valueAt(ij);
            // Convert from microseconds to milliseconds with rounding
            final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
            final int count = timer.getCountLocked(which);
            if (totalTime != 0) {
                dumpLine(pw, uid, category, JOB_DATA, jobs.keyAt(ij), totalTime, count);
            }
        }
        dumpTimer(pw, uid, category, FLASHLIGHT_DATA, u.getFlashlightTurnedOnTimer(), rawRealtime, which);
        dumpTimer(pw, uid, category, CAMERA_DATA, u.getCameraTurnedOnTimer(), rawRealtime, which);
        dumpTimer(pw, uid, category, VIDEO_DATA, u.getVideoTurnedOnTimer(), rawRealtime, which);
        dumpTimer(pw, uid, category, AUDIO_DATA, u.getAudioTurnedOnTimer(), rawRealtime, which);
        final SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
        final int NSE = sensors.size();
        for (int ise = 0; ise < NSE; ise++) {
            final Uid.Sensor se = sensors.valueAt(ise);
            final int sensorNumber = sensors.keyAt(ise);
            final Timer timer = se.getSensorTime();
            if (timer != null) {
                // Convert from microseconds to milliseconds with rounding
                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
                final int count = timer.getCountLocked(which);
                if (totalTime != 0) {
                    dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
                }
            }
        }
        dumpTimer(pw, uid, category, VIBRATOR_DATA, u.getVibratorOnTimer(), rawRealtime, which);
        dumpTimer(pw, uid, category, FOREGROUND_DATA, u.getForegroundActivityTimer(), rawRealtime, which);
        final Object[] stateTimes = new Object[Uid.NUM_PROCESS_STATE];
        long totalStateTime = 0;
        for (int ips = 0; ips < Uid.NUM_PROCESS_STATE; ips++) {
            final long time = u.getProcessStateTime(ips, rawRealtime, which);
            totalStateTime += time;
            stateTimes[ips] = (time + 500) / 1000;
        }
        if (totalStateTime > 0) {
            dumpLine(pw, uid, category, STATE_TIME_DATA, stateTimes);
        }
        final long userCpuTimeUs = u.getUserCpuTimeUs(which);
        final long systemCpuTimeUs = u.getSystemCpuTimeUs(which);
        final long powerCpuMaUs = u.getCpuPowerMaUs(which);
        if (userCpuTimeUs > 0 || systemCpuTimeUs > 0 || powerCpuMaUs > 0) {
            dumpLine(pw, uid, category, CPU_DATA, userCpuTimeUs / 1000, systemCpuTimeUs / 1000, powerCpuMaUs / 1000);
        }
        final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
        for (int ipr = processStats.size() - 1; ipr >= 0; ipr--) {
            final Uid.Proc ps = processStats.valueAt(ipr);
            final long userMillis = ps.getUserTime(which);
            final long systemMillis = ps.getSystemTime(which);
            final long foregroundMillis = ps.getForegroundTime(which);
            final int starts = ps.getStarts(which);
            final int numCrashes = ps.getNumCrashes(which);
            final int numAnrs = ps.getNumAnrs(which);
            if (userMillis != 0 || systemMillis != 0 || foregroundMillis != 0 || starts != 0 || numAnrs != 0 || numCrashes != 0) {
                dumpLine(pw, uid, category, PROCESS_DATA, processStats.keyAt(ipr), userMillis, systemMillis, foregroundMillis, starts, numAnrs, numCrashes);
            }
        }
        final ArrayMap<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
        for (int ipkg = packageStats.size() - 1; ipkg >= 0; ipkg--) {
            final Uid.Pkg ps = packageStats.valueAt(ipkg);
            int wakeups = 0;
            final ArrayMap<String, ? extends Counter> alarms = ps.getWakeupAlarmStats();
            for (int iwa = alarms.size() - 1; iwa >= 0; iwa--) {
                int count = alarms.valueAt(iwa).getCountLocked(which);
                wakeups += count;
                String name = alarms.keyAt(iwa).replace(',', '_');
                dumpLine(pw, uid, category, WAKEUP_ALARM_DATA, name, count);
            }
            final ArrayMap<String, ? extends Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
            for (int isvc = serviceStats.size() - 1; isvc >= 0; isvc--) {
                final BatteryStats.Uid.Pkg.Serv ss = serviceStats.valueAt(isvc);
                final long startTime = ss.getStartTime(batteryUptime, which);
                final int starts = ss.getStarts(which);
                final int launches = ss.getLaunches(which);
                if (startTime != 0 || starts != 0 || launches != 0) {
                    dumpLine(pw, uid, category, APK_DATA, // wakeup alarms
                    wakeups, // Apk
                    packageStats.keyAt(ipkg), // service
                    serviceStats.keyAt(isvc), // time spent started, in ms
                    startTime / 1000, starts, launches);
                }
            }
        }
    }
}
Also used : BatterySipper(com.android.internal.os.BatterySipper) HashMap(java.util.HashMap) Map(java.util.Map) ArrayMap(android.util.ArrayMap) BatteryStatsHelper(com.android.internal.os.BatteryStatsHelper)

Example 74 with BatterySipper

use of com.android.internal.os.BatterySipper in project android_frameworks_base by DirtyUnicorns.

the class BatteryStats method dumpLocked.

@SuppressWarnings("unused")
public final void dumpLocked(Context context, PrintWriter pw, String prefix, final int which, int reqUid, boolean wifiOnly) {
    final long rawUptime = SystemClock.uptimeMillis() * 1000;
    final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
    final long batteryUptime = getBatteryUptime(rawUptime);
    final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
    final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
    final long totalRealtime = computeRealtime(rawRealtime, which);
    final long totalUptime = computeUptime(rawUptime, which);
    final long whichBatteryScreenOffUptime = computeBatteryScreenOffUptime(rawUptime, which);
    final long whichBatteryScreenOffRealtime = computeBatteryScreenOffRealtime(rawRealtime, which);
    final long batteryTimeRemaining = computeBatteryTimeRemaining(rawRealtime);
    final long chargeTimeRemaining = computeChargeTimeRemaining(rawRealtime);
    final StringBuilder sb = new StringBuilder(128);
    final SparseArray<? extends Uid> uidStats = getUidStats();
    final int NU = uidStats.size();
    final int estimatedBatteryCapacity = getEstimatedBatteryCapacity();
    if (estimatedBatteryCapacity > 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Estimated battery capacity: ");
        sb.append(BatteryStatsHelper.makemAh(estimatedBatteryCapacity));
        sb.append(" mAh");
        pw.println(sb.toString());
    }
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Time on battery: ");
    formatTimeMs(sb, whichBatteryRealtime / 1000);
    sb.append("(");
    sb.append(formatRatioLocked(whichBatteryRealtime, totalRealtime));
    sb.append(") realtime, ");
    formatTimeMs(sb, whichBatteryUptime / 1000);
    sb.append("(");
    sb.append(formatRatioLocked(whichBatteryUptime, totalRealtime));
    sb.append(") uptime");
    pw.println(sb.toString());
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Time on battery screen off: ");
    formatTimeMs(sb, whichBatteryScreenOffRealtime / 1000);
    sb.append("(");
    sb.append(formatRatioLocked(whichBatteryScreenOffRealtime, totalRealtime));
    sb.append(") realtime, ");
    formatTimeMs(sb, whichBatteryScreenOffUptime / 1000);
    sb.append("(");
    sb.append(formatRatioLocked(whichBatteryScreenOffUptime, totalRealtime));
    sb.append(") uptime");
    pw.println(sb.toString());
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Total run time: ");
    formatTimeMs(sb, totalRealtime / 1000);
    sb.append("realtime, ");
    formatTimeMs(sb, totalUptime / 1000);
    sb.append("uptime");
    pw.println(sb.toString());
    if (batteryTimeRemaining >= 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Battery time remaining: ");
        formatTimeMs(sb, batteryTimeRemaining / 1000);
        pw.println(sb.toString());
    }
    if (chargeTimeRemaining >= 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Charge time remaining: ");
        formatTimeMs(sb, chargeTimeRemaining / 1000);
        pw.println(sb.toString());
    }
    final LongCounter dischargeCounter = getDischargeCoulombCounter();
    final long dischargeCount = dischargeCounter.getCountLocked(which);
    if (dischargeCount >= 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Discharge: ");
        sb.append(BatteryStatsHelper.makemAh(dischargeCount / 1000.0));
        sb.append(" mAh");
        pw.println(sb.toString());
    }
    final LongCounter dischargeScreenOffCounter = getDischargeScreenOffCoulombCounter();
    final long dischargeScreenOffCount = dischargeScreenOffCounter.getCountLocked(which);
    if (dischargeScreenOffCount >= 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Screen off discharge: ");
        sb.append(BatteryStatsHelper.makemAh(dischargeScreenOffCount / 1000.0));
        sb.append(" mAh");
        pw.println(sb.toString());
    }
    final long dischargeScreenOnCount = dischargeCount - dischargeScreenOffCount;
    if (dischargeScreenOnCount >= 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Screen on discharge: ");
        sb.append(BatteryStatsHelper.makemAh(dischargeScreenOnCount / 1000.0));
        sb.append(" mAh");
        pw.println(sb.toString());
    }
    pw.print("  Start clock time: ");
    pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss", getStartClockTime()).toString());
    final long screenOnTime = getScreenOnTime(rawRealtime, which);
    final long interactiveTime = getInteractiveTime(rawRealtime, which);
    final long powerSaveModeEnabledTime = getPowerSaveModeEnabledTime(rawRealtime, which);
    final long deviceIdleModeLightTime = getDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT, rawRealtime, which);
    final long deviceIdleModeFullTime = getDeviceIdleModeTime(DEVICE_IDLE_MODE_DEEP, rawRealtime, which);
    final long deviceLightIdlingTime = getDeviceIdlingTime(DEVICE_IDLE_MODE_LIGHT, rawRealtime, which);
    final long deviceIdlingTime = getDeviceIdlingTime(DEVICE_IDLE_MODE_DEEP, rawRealtime, which);
    final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
    final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
    final long wifiOnTime = getWifiOnTime(rawRealtime, which);
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Screen on: ");
    formatTimeMs(sb, screenOnTime / 1000);
    sb.append("(");
    sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime));
    sb.append(") ");
    sb.append(getScreenOnCount(which));
    sb.append("x, Interactive: ");
    formatTimeMs(sb, interactiveTime / 1000);
    sb.append("(");
    sb.append(formatRatioLocked(interactiveTime, whichBatteryRealtime));
    sb.append(")");
    pw.println(sb.toString());
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Screen brightnesses:");
    boolean didOne = false;
    for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
        final long time = getScreenBrightnessTime(i, rawRealtime, which);
        if (time == 0) {
            continue;
        }
        sb.append("\n    ");
        sb.append(prefix);
        didOne = true;
        sb.append(SCREEN_BRIGHTNESS_NAMES[i]);
        sb.append(" ");
        formatTimeMs(sb, time / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(time, screenOnTime));
        sb.append(")");
    }
    if (!didOne)
        sb.append(" (no activity)");
    pw.println(sb.toString());
    if (powerSaveModeEnabledTime != 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Power save mode enabled: ");
        formatTimeMs(sb, powerSaveModeEnabledTime / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(powerSaveModeEnabledTime, whichBatteryRealtime));
        sb.append(")");
        pw.println(sb.toString());
    }
    if (deviceLightIdlingTime != 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Device light idling: ");
        formatTimeMs(sb, deviceLightIdlingTime / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(deviceLightIdlingTime, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getDeviceIdlingCount(DEVICE_IDLE_MODE_LIGHT, which));
        sb.append("x");
        pw.println(sb.toString());
    }
    if (deviceIdleModeLightTime != 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Idle mode light time: ");
        formatTimeMs(sb, deviceIdleModeLightTime / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(deviceIdleModeLightTime, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getDeviceIdleModeCount(DEVICE_IDLE_MODE_LIGHT, which));
        sb.append("x");
        sb.append(" -- longest ");
        formatTimeMs(sb, getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT));
        pw.println(sb.toString());
    }
    if (deviceIdlingTime != 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Device full idling: ");
        formatTimeMs(sb, deviceIdlingTime / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(deviceIdlingTime, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getDeviceIdlingCount(DEVICE_IDLE_MODE_DEEP, which));
        sb.append("x");
        pw.println(sb.toString());
    }
    if (deviceIdleModeFullTime != 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Idle mode full time: ");
        formatTimeMs(sb, deviceIdleModeFullTime / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(deviceIdleModeFullTime, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getDeviceIdleModeCount(DEVICE_IDLE_MODE_DEEP, which));
        sb.append("x");
        sb.append(" -- longest ");
        formatTimeMs(sb, getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_DEEP));
        pw.println(sb.toString());
    }
    if (phoneOnTime != 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Active phone call: ");
        formatTimeMs(sb, phoneOnTime / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getPhoneOnCount(which));
        sb.append("x");
    }
    final int connChanges = getNumConnectivityChange(which);
    if (connChanges != 0) {
        pw.print(prefix);
        pw.print("  Connectivity changes: ");
        pw.println(connChanges);
    }
    // Calculate wakelock times across all uids.
    long fullWakeLockTimeTotalMicros = 0;
    long partialWakeLockTimeTotalMicros = 0;
    final ArrayList<TimerEntry> timers = new ArrayList<>();
    for (int iu = 0; iu < NU; 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) {
                fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked(rawRealtime, which);
            }
            final Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
            if (partialWakeTimer != null) {
                final long totalTimeMicros = partialWakeTimer.getTotalTimeLocked(rawRealtime, which);
                if (totalTimeMicros > 0) {
                    if (reqUid < 0) {
                        // Only show the ordered list of all wake
                        // locks if the caller is not asking for data
                        // about a specific uid.
                        timers.add(new TimerEntry(wakelocks.keyAt(iw), u.getUid(), partialWakeTimer, totalTimeMicros));
                    }
                    partialWakeLockTimeTotalMicros += totalTimeMicros;
                }
            }
        }
    }
    final long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
    final long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
    final long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
    final long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
    final long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
    final long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
    final long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
    final long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
    final long btRxTotalBytes = getNetworkActivityBytes(NETWORK_BT_RX_DATA, which);
    final long btTxTotalBytes = getNetworkActivityBytes(NETWORK_BT_TX_DATA, which);
    if (fullWakeLockTimeTotalMicros != 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Total full wakelock time: ");
        formatTimeMsNoSpace(sb, (fullWakeLockTimeTotalMicros + 500) / 1000);
        pw.println(sb.toString());
    }
    if (partialWakeLockTimeTotalMicros != 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Total partial wakelock time: ");
        formatTimeMsNoSpace(sb, (partialWakeLockTimeTotalMicros + 500) / 1000);
        pw.println(sb.toString());
    }
    pw.print(prefix);
    pw.print("  Mobile total received: ");
    pw.print(formatBytesLocked(mobileRxTotalBytes));
    pw.print(", sent: ");
    pw.print(formatBytesLocked(mobileTxTotalBytes));
    pw.print(" (packets received ");
    pw.print(mobileRxTotalPackets);
    pw.print(", sent ");
    pw.print(mobileTxTotalPackets);
    pw.println(")");
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Phone signal levels:");
    didOne = false;
    for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
        final long time = getPhoneSignalStrengthTime(i, rawRealtime, which);
        if (time == 0) {
            continue;
        }
        sb.append("\n    ");
        sb.append(prefix);
        didOne = true;
        sb.append(SignalStrength.SIGNAL_STRENGTH_NAMES[i]);
        sb.append(" ");
        formatTimeMs(sb, time / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(time, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getPhoneSignalStrengthCount(i, which));
        sb.append("x");
    }
    if (!didOne)
        sb.append(" (no activity)");
    pw.println(sb.toString());
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Signal scanning time: ");
    formatTimeMsNoSpace(sb, getPhoneSignalScanningTime(rawRealtime, which) / 1000);
    pw.println(sb.toString());
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Radio types:");
    didOne = false;
    for (int i = 0; i < NUM_DATA_CONNECTION_TYPES; i++) {
        final long time = getPhoneDataConnectionTime(i, rawRealtime, which);
        if (time == 0) {
            continue;
        }
        sb.append("\n    ");
        sb.append(prefix);
        didOne = true;
        sb.append(DATA_CONNECTION_NAMES[i]);
        sb.append(" ");
        formatTimeMs(sb, time / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(time, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getPhoneDataConnectionCount(i, which));
        sb.append("x");
    }
    if (!didOne)
        sb.append(" (no activity)");
    pw.println(sb.toString());
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Mobile radio active time: ");
    final long mobileActiveTime = getMobileRadioActiveTime(rawRealtime, which);
    formatTimeMs(sb, mobileActiveTime / 1000);
    sb.append("(");
    sb.append(formatRatioLocked(mobileActiveTime, whichBatteryRealtime));
    sb.append(") ");
    sb.append(getMobileRadioActiveCount(which));
    sb.append("x");
    pw.println(sb.toString());
    final long mobileActiveUnknownTime = getMobileRadioActiveUnknownTime(which);
    if (mobileActiveUnknownTime != 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Mobile radio active unknown time: ");
        formatTimeMs(sb, mobileActiveUnknownTime / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(mobileActiveUnknownTime, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getMobileRadioActiveUnknownCount(which));
        sb.append("x");
        pw.println(sb.toString());
    }
    final long mobileActiveAdjustedTime = getMobileRadioActiveAdjustedTime(which);
    if (mobileActiveAdjustedTime != 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Mobile radio active adjusted time: ");
        formatTimeMs(sb, mobileActiveAdjustedTime / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(mobileActiveAdjustedTime, whichBatteryRealtime));
        sb.append(")");
        pw.println(sb.toString());
    }
    printControllerActivity(pw, sb, prefix, "Radio", getModemControllerActivity(), which);
    pw.print(prefix);
    pw.print("  Wi-Fi total received: ");
    pw.print(formatBytesLocked(wifiRxTotalBytes));
    pw.print(", sent: ");
    pw.print(formatBytesLocked(wifiTxTotalBytes));
    pw.print(" (packets received ");
    pw.print(wifiRxTotalPackets);
    pw.print(", sent ");
    pw.print(wifiTxTotalPackets);
    pw.println(")");
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Wifi on: ");
    formatTimeMs(sb, wifiOnTime / 1000);
    sb.append("(");
    sb.append(formatRatioLocked(wifiOnTime, whichBatteryRealtime));
    sb.append("), Wifi running: ");
    formatTimeMs(sb, wifiRunningTime / 1000);
    sb.append("(");
    sb.append(formatRatioLocked(wifiRunningTime, whichBatteryRealtime));
    sb.append(")");
    pw.println(sb.toString());
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Wifi states:");
    didOne = false;
    for (int i = 0; i < NUM_WIFI_STATES; i++) {
        final long time = getWifiStateTime(i, rawRealtime, which);
        if (time == 0) {
            continue;
        }
        sb.append("\n    ");
        didOne = true;
        sb.append(WIFI_STATE_NAMES[i]);
        sb.append(" ");
        formatTimeMs(sb, time / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(time, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getWifiStateCount(i, which));
        sb.append("x");
    }
    if (!didOne)
        sb.append(" (no activity)");
    pw.println(sb.toString());
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Wifi supplicant states:");
    didOne = false;
    for (int i = 0; i < NUM_WIFI_SUPPL_STATES; i++) {
        final long time = getWifiSupplStateTime(i, rawRealtime, which);
        if (time == 0) {
            continue;
        }
        sb.append("\n    ");
        didOne = true;
        sb.append(WIFI_SUPPL_STATE_NAMES[i]);
        sb.append(" ");
        formatTimeMs(sb, time / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(time, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getWifiSupplStateCount(i, which));
        sb.append("x");
    }
    if (!didOne)
        sb.append(" (no activity)");
    pw.println(sb.toString());
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Wifi signal levels:");
    didOne = false;
    for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
        final long time = getWifiSignalStrengthTime(i, rawRealtime, which);
        if (time == 0) {
            continue;
        }
        sb.append("\n    ");
        sb.append(prefix);
        didOne = true;
        sb.append("level(");
        sb.append(i);
        sb.append(") ");
        formatTimeMs(sb, time / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(time, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getWifiSignalStrengthCount(i, which));
        sb.append("x");
    }
    if (!didOne)
        sb.append(" (no activity)");
    pw.println(sb.toString());
    printControllerActivity(pw, sb, prefix, "WiFi", getWifiControllerActivity(), which);
    pw.print(prefix);
    pw.print("  Bluetooth total received: ");
    pw.print(formatBytesLocked(btRxTotalBytes));
    pw.print(", sent: ");
    pw.println(formatBytesLocked(btTxTotalBytes));
    final long bluetoothScanTimeMs = getBluetoothScanTime(rawRealtime, which) / 1000;
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Bluetooth scan time: ");
    formatTimeMs(sb, bluetoothScanTimeMs);
    pw.println(sb.toString());
    printControllerActivity(pw, sb, prefix, "Bluetooth", getBluetoothControllerActivity(), which);
    pw.println();
    if (which == STATS_SINCE_UNPLUGGED) {
        if (getIsOnBattery()) {
            pw.print(prefix);
            pw.println("  Device is currently unplugged");
            pw.print(prefix);
            pw.print("    Discharge cycle start level: ");
            pw.println(getDischargeStartLevel());
            pw.print(prefix);
            pw.print("    Discharge cycle current level: ");
            pw.println(getDischargeCurrentLevel());
        } else {
            pw.print(prefix);
            pw.println("  Device is currently plugged into power");
            pw.print(prefix);
            pw.print("    Last discharge cycle start level: ");
            pw.println(getDischargeStartLevel());
            pw.print(prefix);
            pw.print("    Last discharge cycle end level: ");
            pw.println(getDischargeCurrentLevel());
        }
        pw.print(prefix);
        pw.print("    Amount discharged while screen on: ");
        pw.println(getDischargeAmountScreenOn());
        pw.print(prefix);
        pw.print("    Amount discharged while screen off: ");
        pw.println(getDischargeAmountScreenOff());
        pw.println(" ");
    } else {
        pw.print(prefix);
        pw.println("  Device battery use since last full charge");
        pw.print(prefix);
        pw.print("    Amount discharged (lower bound): ");
        pw.println(getLowDischargeAmountSinceCharge());
        pw.print(prefix);
        pw.print("    Amount discharged (upper bound): ");
        pw.println(getHighDischargeAmountSinceCharge());
        pw.print(prefix);
        pw.print("    Amount discharged while screen on: ");
        pw.println(getDischargeAmountScreenOnSinceCharge());
        pw.print(prefix);
        pw.print("    Amount discharged while screen off: ");
        pw.println(getDischargeAmountScreenOffSinceCharge());
        pw.println();
    }
    final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
    helper.create(this);
    helper.refreshStats(which, UserHandle.USER_ALL);
    List<BatterySipper> sippers = helper.getUsageList();
    if (sippers != null && sippers.size() > 0) {
        pw.print(prefix);
        pw.println("  Estimated power use (mAh):");
        pw.print(prefix);
        pw.print("    Capacity: ");
        printmAh(pw, helper.getPowerProfile().getBatteryCapacity());
        pw.print(", Computed drain: ");
        printmAh(pw, helper.getComputedPower());
        pw.print(", actual drain: ");
        printmAh(pw, helper.getMinDrainedPower());
        if (helper.getMinDrainedPower() != helper.getMaxDrainedPower()) {
            pw.print("-");
            printmAh(pw, helper.getMaxDrainedPower());
        }
        pw.println();
        for (int i = 0; i < sippers.size(); i++) {
            final BatterySipper bs = sippers.get(i);
            pw.print(prefix);
            switch(bs.drainType) {
                case IDLE:
                    pw.print("    Idle: ");
                    break;
                case CELL:
                    pw.print("    Cell standby: ");
                    break;
                case PHONE:
                    pw.print("    Phone calls: ");
                    break;
                case WIFI:
                    pw.print("    Wifi: ");
                    break;
                case BLUETOOTH:
                    pw.print("    Bluetooth: ");
                    break;
                case SCREEN:
                    pw.print("    Screen: ");
                    break;
                case FLASHLIGHT:
                    pw.print("    Flashlight: ");
                    break;
                case APP:
                    pw.print("    Uid ");
                    UserHandle.formatUid(pw, bs.uidObj.getUid());
                    pw.print(": ");
                    break;
                case USER:
                    pw.print("    User ");
                    pw.print(bs.userId);
                    pw.print(": ");
                    break;
                case UNACCOUNTED:
                    pw.print("    Unaccounted: ");
                    break;
                case OVERCOUNTED:
                    pw.print("    Over-counted: ");
                    break;
                case CAMERA:
                    pw.print("    Camera: ");
                    break;
                default:
                    pw.print("    ???: ");
                    break;
            }
            printmAh(pw, bs.totalPowerMah);
            if (bs.usagePowerMah != bs.totalPowerMah) {
                // If the usage (generic power) isn't the whole amount, we list out
                // what components are involved in the calculation.
                pw.print(" (");
                if (bs.usagePowerMah != 0) {
                    pw.print(" usage=");
                    printmAh(pw, bs.usagePowerMah);
                }
                if (bs.cpuPowerMah != 0) {
                    pw.print(" cpu=");
                    printmAh(pw, bs.cpuPowerMah);
                }
                if (bs.wakeLockPowerMah != 0) {
                    pw.print(" wake=");
                    printmAh(pw, bs.wakeLockPowerMah);
                }
                if (bs.mobileRadioPowerMah != 0) {
                    pw.print(" radio=");
                    printmAh(pw, bs.mobileRadioPowerMah);
                }
                if (bs.wifiPowerMah != 0) {
                    pw.print(" wifi=");
                    printmAh(pw, bs.wifiPowerMah);
                }
                if (bs.bluetoothPowerMah != 0) {
                    pw.print(" bt=");
                    printmAh(pw, bs.bluetoothPowerMah);
                }
                if (bs.gpsPowerMah != 0) {
                    pw.print(" gps=");
                    printmAh(pw, bs.gpsPowerMah);
                }
                if (bs.sensorPowerMah != 0) {
                    pw.print(" sensor=");
                    printmAh(pw, bs.sensorPowerMah);
                }
                if (bs.cameraPowerMah != 0) {
                    pw.print(" camera=");
                    printmAh(pw, bs.cameraPowerMah);
                }
                if (bs.flashlightPowerMah != 0) {
                    pw.print(" flash=");
                    printmAh(pw, bs.flashlightPowerMah);
                }
                pw.print(" )");
            }
            pw.println();
        }
        pw.println();
    }
    sippers = helper.getMobilemsppList();
    if (sippers != null && sippers.size() > 0) {
        pw.print(prefix);
        pw.println("  Per-app mobile ms per packet:");
        long totalTime = 0;
        for (int i = 0; i < sippers.size(); i++) {
            final BatterySipper bs = sippers.get(i);
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    Uid ");
            UserHandle.formatUid(sb, bs.uidObj.getUid());
            sb.append(": ");
            sb.append(BatteryStatsHelper.makemAh(bs.mobilemspp));
            sb.append(" (");
            sb.append(bs.mobileRxPackets + bs.mobileTxPackets);
            sb.append(" packets over ");
            formatTimeMsNoSpace(sb, bs.mobileActive);
            sb.append(") ");
            sb.append(bs.mobileActiveCount);
            sb.append("x");
            pw.println(sb.toString());
            totalTime += bs.mobileActive;
        }
        sb.setLength(0);
        sb.append(prefix);
        sb.append("    TOTAL TIME: ");
        formatTimeMs(sb, totalTime);
        sb.append("(");
        sb.append(formatRatioLocked(totalTime, whichBatteryRealtime));
        sb.append(")");
        pw.println(sb.toString());
        pw.println();
    }
    final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {

        @Override
        public int compare(TimerEntry lhs, TimerEntry rhs) {
            long lhsTime = lhs.mTime;
            long rhsTime = rhs.mTime;
            if (lhsTime < rhsTime) {
                return 1;
            }
            if (lhsTime > rhsTime) {
                return -1;
            }
            return 0;
        }
    };
    if (reqUid < 0) {
        final Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
        if (kernelWakelocks.size() > 0) {
            final ArrayList<TimerEntry> ktimers = new ArrayList<>();
            for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
                final BatteryStats.Timer timer = ent.getValue();
                final long totalTimeMillis = computeWakeLock(timer, rawRealtime, which);
                if (totalTimeMillis > 0) {
                    ktimers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
                }
            }
            if (ktimers.size() > 0) {
                Collections.sort(ktimers, timerComparator);
                pw.print(prefix);
                pw.println("  All kernel wake locks:");
                for (int i = 0; i < ktimers.size(); i++) {
                    final TimerEntry timer = ktimers.get(i);
                    String linePrefix = ": ";
                    sb.setLength(0);
                    sb.append(prefix);
                    sb.append("  Kernel Wake lock ");
                    sb.append(timer.mName);
                    linePrefix = printWakeLock(sb, timer.mTimer, rawRealtime, null, which, linePrefix);
                    if (!linePrefix.equals(": ")) {
                        sb.append(" realtime");
                        // Only print out wake locks that were held
                        pw.println(sb.toString());
                    }
                }
                pw.println();
            }
        }
        if (timers.size() > 0) {
            Collections.sort(timers, timerComparator);
            pw.print(prefix);
            pw.println("  All partial wake locks:");
            for (int i = 0; i < timers.size(); i++) {
                TimerEntry timer = timers.get(i);
                sb.setLength(0);
                sb.append("  Wake lock ");
                UserHandle.formatUid(sb, timer.mId);
                sb.append(" ");
                sb.append(timer.mName);
                printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": ");
                sb.append(" realtime");
                pw.println(sb.toString());
            }
            timers.clear();
            pw.println();
        }
        final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
        if (wakeupReasons.size() > 0) {
            pw.print(prefix);
            pw.println("  All wakeup reasons:");
            final ArrayList<TimerEntry> reasons = new ArrayList<>();
            for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) {
                final Timer timer = ent.getValue();
                reasons.add(new TimerEntry(ent.getKey(), 0, timer, timer.getCountLocked(which)));
            }
            Collections.sort(reasons, timerComparator);
            for (int i = 0; i < reasons.size(); i++) {
                TimerEntry timer = reasons.get(i);
                String linePrefix = ": ";
                sb.setLength(0);
                sb.append(prefix);
                sb.append("  Wakeup reason ");
                sb.append(timer.mName);
                printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": ");
                sb.append(" realtime");
                pw.println(sb.toString());
            }
            pw.println();
        }
    }
    for (int iu = 0; iu < NU; iu++) {
        final int uid = uidStats.keyAt(iu);
        if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) {
            continue;
        }
        final Uid u = uidStats.valueAt(iu);
        pw.print(prefix);
        pw.print("  ");
        UserHandle.formatUid(pw, uid);
        pw.println(":");
        boolean uidActivity = false;
        final long mobileRxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
        final long mobileTxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
        final long wifiRxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
        final long wifiTxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
        final long btRxBytes = u.getNetworkActivityBytes(NETWORK_BT_RX_DATA, which);
        final long btTxBytes = u.getNetworkActivityBytes(NETWORK_BT_TX_DATA, which);
        final long mobileRxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
        final long mobileTxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
        final long wifiRxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
        final long wifiTxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
        final long uidMobileActiveTime = u.getMobileRadioActiveTime(which);
        final int uidMobileActiveCount = u.getMobileRadioActiveCount(which);
        final long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
        final long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
        final int wifiScanCount = u.getWifiScanCount(which);
        final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
        final long mobileWakeup = u.getMobileRadioApWakeupCount(which);
        final long wifiWakeup = u.getWifiRadioApWakeupCount(which);
        if (mobileRxBytes > 0 || mobileTxBytes > 0 || mobileRxPackets > 0 || mobileTxPackets > 0) {
            pw.print(prefix);
            pw.print("    Mobile network: ");
            pw.print(formatBytesLocked(mobileRxBytes));
            pw.print(" received, ");
            pw.print(formatBytesLocked(mobileTxBytes));
            pw.print(" sent (packets ");
            pw.print(mobileRxPackets);
            pw.print(" received, ");
            pw.print(mobileTxPackets);
            pw.println(" sent)");
        }
        if (uidMobileActiveTime > 0 || uidMobileActiveCount > 0) {
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    Mobile radio active: ");
            formatTimeMs(sb, uidMobileActiveTime / 1000);
            sb.append("(");
            sb.append(formatRatioLocked(uidMobileActiveTime, mobileActiveTime));
            sb.append(") ");
            sb.append(uidMobileActiveCount);
            sb.append("x");
            long packets = mobileRxPackets + mobileTxPackets;
            if (packets == 0) {
                packets = 1;
            }
            sb.append(" @ ");
            sb.append(BatteryStatsHelper.makemAh(uidMobileActiveTime / 1000 / (double) packets));
            sb.append(" mspp");
            pw.println(sb.toString());
        }
        if (mobileWakeup > 0) {
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    Mobile radio AP wakeups: ");
            sb.append(mobileWakeup);
            pw.println(sb.toString());
        }
        printControllerActivityIfInteresting(pw, sb, prefix + "  ", "Modem", u.getModemControllerActivity(), which);
        if (wifiRxBytes > 0 || wifiTxBytes > 0 || wifiRxPackets > 0 || wifiTxPackets > 0) {
            pw.print(prefix);
            pw.print("    Wi-Fi network: ");
            pw.print(formatBytesLocked(wifiRxBytes));
            pw.print(" received, ");
            pw.print(formatBytesLocked(wifiTxBytes));
            pw.print(" sent (packets ");
            pw.print(wifiRxPackets);
            pw.print(" received, ");
            pw.print(wifiTxPackets);
            pw.println(" sent)");
        }
        if (fullWifiLockOnTime != 0 || wifiScanTime != 0 || wifiScanCount != 0 || uidWifiRunningTime != 0) {
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    Wifi Running: ");
            formatTimeMs(sb, uidWifiRunningTime / 1000);
            sb.append("(");
            sb.append(formatRatioLocked(uidWifiRunningTime, whichBatteryRealtime));
            sb.append(")\n");
            sb.append(prefix);
            sb.append("    Full Wifi Lock: ");
            formatTimeMs(sb, fullWifiLockOnTime / 1000);
            sb.append("(");
            sb.append(formatRatioLocked(fullWifiLockOnTime, whichBatteryRealtime));
            sb.append(")\n");
            sb.append(prefix);
            sb.append("    Wifi Scan: ");
            formatTimeMs(sb, wifiScanTime / 1000);
            sb.append("(");
            sb.append(formatRatioLocked(wifiScanTime, whichBatteryRealtime));
            sb.append(") ");
            sb.append(wifiScanCount);
            sb.append("x");
            pw.println(sb.toString());
        }
        if (wifiWakeup > 0) {
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    WiFi AP wakeups: ");
            sb.append(wifiWakeup);
            pw.println(sb.toString());
        }
        printControllerActivityIfInteresting(pw, sb, prefix + "  ", "WiFi", u.getWifiControllerActivity(), which);
        if (btRxBytes > 0 || btTxBytes > 0) {
            pw.print(prefix);
            pw.print("    Bluetooth network: ");
            pw.print(formatBytesLocked(btRxBytes));
            pw.print(" received, ");
            pw.print(formatBytesLocked(btTxBytes));
            pw.println(" sent");
        }
        uidActivity |= printTimer(pw, sb, u.getBluetoothScanTimer(), rawRealtime, which, prefix, "Bluetooth Scan");
        if (u.hasUserActivity()) {
            boolean hasData = false;
            for (int i = 0; i < Uid.NUM_USER_ACTIVITY_TYPES; i++) {
                final int val = u.getUserActivityCount(i, which);
                if (val != 0) {
                    if (!hasData) {
                        sb.setLength(0);
                        sb.append("    User activity: ");
                        hasData = true;
                    } else {
                        sb.append(", ");
                    }
                    sb.append(val);
                    sb.append(" ");
                    sb.append(Uid.USER_ACTIVITY_TYPES[i]);
                }
            }
            if (hasData) {
                pw.println(sb.toString());
            }
        }
        final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
        long totalFullWakelock = 0, totalPartialWakelock = 0, totalWindowWakelock = 0;
        long totalDrawWakelock = 0;
        int countWakelock = 0;
        for (int iw = wakelocks.size() - 1; iw >= 0; iw--) {
            final Uid.Wakelock wl = wakelocks.valueAt(iw);
            String linePrefix = ": ";
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    Wake lock ");
            sb.append(wakelocks.keyAt(iw));
            linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), rawRealtime, "full", which, linePrefix);
            linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), rawRealtime, "partial", which, linePrefix);
            linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime, "window", which, linePrefix);
            linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_DRAW), rawRealtime, "draw", which, linePrefix);
            sb.append(" realtime");
            pw.println(sb.toString());
            uidActivity = true;
            countWakelock++;
            totalFullWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL), rawRealtime, which);
            totalPartialWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL), rawRealtime, which);
            totalWindowWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime, which);
            totalDrawWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_DRAW), rawRealtime, which);
        }
        if (countWakelock > 1) {
            if (totalFullWakelock != 0 || totalPartialWakelock != 0 || totalWindowWakelock != 0) {
                sb.setLength(0);
                sb.append(prefix);
                sb.append("    TOTAL wake: ");
                boolean needComma = false;
                if (totalFullWakelock != 0) {
                    needComma = true;
                    formatTimeMs(sb, totalFullWakelock);
                    sb.append("full");
                }
                if (totalPartialWakelock != 0) {
                    if (needComma) {
                        sb.append(", ");
                    }
                    needComma = true;
                    formatTimeMs(sb, totalPartialWakelock);
                    sb.append("partial");
                }
                if (totalWindowWakelock != 0) {
                    if (needComma) {
                        sb.append(", ");
                    }
                    needComma = true;
                    formatTimeMs(sb, totalWindowWakelock);
                    sb.append("window");
                }
                if (totalDrawWakelock != 0) {
                    if (needComma) {
                        sb.append(",");
                    }
                    needComma = true;
                    formatTimeMs(sb, totalDrawWakelock);
                    sb.append("draw");
                }
                sb.append(" realtime");
                pw.println(sb.toString());
            }
        }
        final ArrayMap<String, ? extends Timer> syncs = u.getSyncStats();
        for (int isy = syncs.size() - 1; isy >= 0; isy--) {
            final Timer timer = syncs.valueAt(isy);
            // Convert from microseconds to milliseconds with rounding
            final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
            final int count = timer.getCountLocked(which);
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    Sync ");
            sb.append(syncs.keyAt(isy));
            sb.append(": ");
            if (totalTime != 0) {
                formatTimeMs(sb, totalTime);
                sb.append("realtime (");
                sb.append(count);
                sb.append(" times)");
            } else {
                sb.append("(not used)");
            }
            pw.println(sb.toString());
            uidActivity = true;
        }
        final ArrayMap<String, ? extends Timer> jobs = u.getJobStats();
        for (int ij = jobs.size() - 1; ij >= 0; ij--) {
            final Timer timer = jobs.valueAt(ij);
            // Convert from microseconds to milliseconds with rounding
            final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
            final int count = timer.getCountLocked(which);
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    Job ");
            sb.append(jobs.keyAt(ij));
            sb.append(": ");
            if (totalTime != 0) {
                formatTimeMs(sb, totalTime);
                sb.append("realtime (");
                sb.append(count);
                sb.append(" times)");
            } else {
                sb.append("(not used)");
            }
            pw.println(sb.toString());
            uidActivity = true;
        }
        uidActivity |= printTimer(pw, sb, u.getFlashlightTurnedOnTimer(), rawRealtime, which, prefix, "Flashlight");
        uidActivity |= printTimer(pw, sb, u.getCameraTurnedOnTimer(), rawRealtime, which, prefix, "Camera");
        uidActivity |= printTimer(pw, sb, u.getVideoTurnedOnTimer(), rawRealtime, which, prefix, "Video");
        uidActivity |= printTimer(pw, sb, u.getAudioTurnedOnTimer(), rawRealtime, which, prefix, "Audio");
        final SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
        final int NSE = sensors.size();
        for (int ise = 0; ise < NSE; ise++) {
            final Uid.Sensor se = sensors.valueAt(ise);
            final int sensorNumber = sensors.keyAt(ise);
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    Sensor ");
            int handle = se.getHandle();
            if (handle == Uid.Sensor.GPS) {
                sb.append("GPS");
            } else {
                sb.append(handle);
            }
            sb.append(": ");
            final Timer timer = se.getSensorTime();
            if (timer != null) {
                // Convert from microseconds to milliseconds with rounding
                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
                final int count = timer.getCountLocked(which);
                //timer.logState();
                if (totalTime != 0) {
                    formatTimeMs(sb, totalTime);
                    sb.append("realtime (");
                    sb.append(count);
                    sb.append(" times)");
                } else {
                    sb.append("(not used)");
                }
            } else {
                sb.append("(not used)");
            }
            pw.println(sb.toString());
            uidActivity = true;
        }
        uidActivity |= printTimer(pw, sb, u.getVibratorOnTimer(), rawRealtime, which, prefix, "Vibrator");
        uidActivity |= printTimer(pw, sb, u.getForegroundActivityTimer(), rawRealtime, which, prefix, "Foreground activities");
        long totalStateTime = 0;
        for (int ips = 0; ips < Uid.NUM_PROCESS_STATE; ips++) {
            long time = u.getProcessStateTime(ips, rawRealtime, which);
            if (time > 0) {
                totalStateTime += time;
                sb.setLength(0);
                sb.append(prefix);
                sb.append("    ");
                sb.append(Uid.PROCESS_STATE_NAMES[ips]);
                sb.append(" for: ");
                formatTimeMs(sb, (time + 500) / 1000);
                pw.println(sb.toString());
                uidActivity = true;
            }
        }
        if (totalStateTime > 0) {
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    Total running: ");
            formatTimeMs(sb, (totalStateTime + 500) / 1000);
            pw.println(sb.toString());
        }
        final long userCpuTimeUs = u.getUserCpuTimeUs(which);
        final long systemCpuTimeUs = u.getSystemCpuTimeUs(which);
        final long powerCpuMaUs = u.getCpuPowerMaUs(which);
        if (userCpuTimeUs > 0 || systemCpuTimeUs > 0 || powerCpuMaUs > 0) {
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    Total cpu time: u=");
            formatTimeMs(sb, userCpuTimeUs / 1000);
            sb.append("s=");
            formatTimeMs(sb, systemCpuTimeUs / 1000);
            sb.append("p=");
            printmAh(sb, powerCpuMaUs / (1000.0 * 1000.0 * 60.0 * 60.0));
            sb.append("mAh");
            pw.println(sb.toString());
        }
        final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
        for (int ipr = processStats.size() - 1; ipr >= 0; ipr--) {
            final Uid.Proc ps = processStats.valueAt(ipr);
            long userTime;
            long systemTime;
            long foregroundTime;
            int starts;
            int numExcessive;
            userTime = ps.getUserTime(which);
            systemTime = ps.getSystemTime(which);
            foregroundTime = ps.getForegroundTime(which);
            starts = ps.getStarts(which);
            final int numCrashes = ps.getNumCrashes(which);
            final int numAnrs = ps.getNumAnrs(which);
            numExcessive = which == STATS_SINCE_CHARGED ? ps.countExcessivePowers() : 0;
            if (userTime != 0 || systemTime != 0 || foregroundTime != 0 || starts != 0 || numExcessive != 0 || numCrashes != 0 || numAnrs != 0) {
                sb.setLength(0);
                sb.append(prefix);
                sb.append("    Proc ");
                sb.append(processStats.keyAt(ipr));
                sb.append(":\n");
                sb.append(prefix);
                sb.append("      CPU: ");
                formatTimeMs(sb, userTime);
                sb.append("usr + ");
                formatTimeMs(sb, systemTime);
                sb.append("krn ; ");
                formatTimeMs(sb, foregroundTime);
                sb.append("fg");
                if (starts != 0 || numCrashes != 0 || numAnrs != 0) {
                    sb.append("\n");
                    sb.append(prefix);
                    sb.append("      ");
                    boolean hasOne = false;
                    if (starts != 0) {
                        hasOne = true;
                        sb.append(starts);
                        sb.append(" starts");
                    }
                    if (numCrashes != 0) {
                        if (hasOne) {
                            sb.append(", ");
                        }
                        hasOne = true;
                        sb.append(numCrashes);
                        sb.append(" crashes");
                    }
                    if (numAnrs != 0) {
                        if (hasOne) {
                            sb.append(", ");
                        }
                        sb.append(numAnrs);
                        sb.append(" anrs");
                    }
                }
                pw.println(sb.toString());
                for (int e = 0; e < numExcessive; e++) {
                    Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e);
                    if (ew != null) {
                        pw.print(prefix);
                        pw.print("      * Killed for ");
                        if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) {
                            pw.print("wake lock");
                        } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) {
                            pw.print("cpu");
                        } else {
                            pw.print("unknown");
                        }
                        pw.print(" use: ");
                        TimeUtils.formatDuration(ew.usedTime, pw);
                        pw.print(" over ");
                        TimeUtils.formatDuration(ew.overTime, pw);
                        if (ew.overTime != 0) {
                            pw.print(" (");
                            pw.print((ew.usedTime * 100) / ew.overTime);
                            pw.println("%)");
                        }
                    }
                }
                uidActivity = true;
            }
        }
        final ArrayMap<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
        for (int ipkg = packageStats.size() - 1; ipkg >= 0; ipkg--) {
            pw.print(prefix);
            pw.print("    Apk ");
            pw.print(packageStats.keyAt(ipkg));
            pw.println(":");
            boolean apkActivity = false;
            final Uid.Pkg ps = packageStats.valueAt(ipkg);
            final ArrayMap<String, ? extends Counter> alarms = ps.getWakeupAlarmStats();
            for (int iwa = alarms.size() - 1; iwa >= 0; iwa--) {
                pw.print(prefix);
                pw.print("      Wakeup alarm ");
                pw.print(alarms.keyAt(iwa));
                pw.print(": ");
                pw.print(alarms.valueAt(iwa).getCountLocked(which));
                pw.println(" times");
                apkActivity = true;
            }
            final ArrayMap<String, ? extends Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
            for (int isvc = serviceStats.size() - 1; isvc >= 0; isvc--) {
                final BatteryStats.Uid.Pkg.Serv ss = serviceStats.valueAt(isvc);
                final long startTime = ss.getStartTime(batteryUptime, which);
                final int starts = ss.getStarts(which);
                final int launches = ss.getLaunches(which);
                if (startTime != 0 || starts != 0 || launches != 0) {
                    sb.setLength(0);
                    sb.append(prefix);
                    sb.append("      Service ");
                    sb.append(serviceStats.keyAt(isvc));
                    sb.append(":\n");
                    sb.append(prefix);
                    sb.append("        Created for: ");
                    formatTimeMs(sb, startTime / 1000);
                    sb.append("uptime\n");
                    sb.append(prefix);
                    sb.append("        Starts: ");
                    sb.append(starts);
                    sb.append(", launches: ");
                    sb.append(launches);
                    pw.println(sb.toString());
                    apkActivity = true;
                }
            }
            if (!apkActivity) {
                pw.print(prefix);
                pw.println("      (nothing executed)");
            }
            uidActivity = true;
        }
        if (!uidActivity) {
            pw.print(prefix);
            pw.println("    (nothing executed)");
        }
    }
}
Also used : ArrayList(java.util.ArrayList) Comparator(java.util.Comparator) BatterySipper(com.android.internal.os.BatterySipper) BatteryStatsHelper(com.android.internal.os.BatteryStatsHelper) HashMap(java.util.HashMap) Map(java.util.Map) ArrayMap(android.util.ArrayMap)

Example 75 with BatterySipper

use of com.android.internal.os.BatterySipper in project android_frameworks_base by AOSPA.

the class BatteryStats method dumpLocked.

@SuppressWarnings("unused")
public final void dumpLocked(Context context, PrintWriter pw, String prefix, final int which, int reqUid, boolean wifiOnly) {
    final long rawUptime = SystemClock.uptimeMillis() * 1000;
    final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
    final long batteryUptime = getBatteryUptime(rawUptime);
    final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
    final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
    final long totalRealtime = computeRealtime(rawRealtime, which);
    final long totalUptime = computeUptime(rawUptime, which);
    final long whichBatteryScreenOffUptime = computeBatteryScreenOffUptime(rawUptime, which);
    final long whichBatteryScreenOffRealtime = computeBatteryScreenOffRealtime(rawRealtime, which);
    final long batteryTimeRemaining = computeBatteryTimeRemaining(rawRealtime);
    final long chargeTimeRemaining = computeChargeTimeRemaining(rawRealtime);
    final StringBuilder sb = new StringBuilder(128);
    final SparseArray<? extends Uid> uidStats = getUidStats();
    final int NU = uidStats.size();
    final int estimatedBatteryCapacity = getEstimatedBatteryCapacity();
    if (estimatedBatteryCapacity > 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Estimated battery capacity: ");
        sb.append(BatteryStatsHelper.makemAh(estimatedBatteryCapacity));
        sb.append(" mAh");
        pw.println(sb.toString());
    }
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Time on battery: ");
    formatTimeMs(sb, whichBatteryRealtime / 1000);
    sb.append("(");
    sb.append(formatRatioLocked(whichBatteryRealtime, totalRealtime));
    sb.append(") realtime, ");
    formatTimeMs(sb, whichBatteryUptime / 1000);
    sb.append("(");
    sb.append(formatRatioLocked(whichBatteryUptime, totalRealtime));
    sb.append(") uptime");
    pw.println(sb.toString());
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Time on battery screen off: ");
    formatTimeMs(sb, whichBatteryScreenOffRealtime / 1000);
    sb.append("(");
    sb.append(formatRatioLocked(whichBatteryScreenOffRealtime, totalRealtime));
    sb.append(") realtime, ");
    formatTimeMs(sb, whichBatteryScreenOffUptime / 1000);
    sb.append("(");
    sb.append(formatRatioLocked(whichBatteryScreenOffUptime, totalRealtime));
    sb.append(") uptime");
    pw.println(sb.toString());
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Total run time: ");
    formatTimeMs(sb, totalRealtime / 1000);
    sb.append("realtime, ");
    formatTimeMs(sb, totalUptime / 1000);
    sb.append("uptime");
    pw.println(sb.toString());
    if (batteryTimeRemaining >= 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Battery time remaining: ");
        formatTimeMs(sb, batteryTimeRemaining / 1000);
        pw.println(sb.toString());
    }
    if (chargeTimeRemaining >= 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Charge time remaining: ");
        formatTimeMs(sb, chargeTimeRemaining / 1000);
        pw.println(sb.toString());
    }
    final LongCounter dischargeCounter = getDischargeCoulombCounter();
    final long dischargeCount = dischargeCounter.getCountLocked(which);
    if (dischargeCount >= 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Discharge: ");
        sb.append(BatteryStatsHelper.makemAh(dischargeCount / 1000.0));
        sb.append(" mAh");
        pw.println(sb.toString());
    }
    final LongCounter dischargeScreenOffCounter = getDischargeScreenOffCoulombCounter();
    final long dischargeScreenOffCount = dischargeScreenOffCounter.getCountLocked(which);
    if (dischargeScreenOffCount >= 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Screen off discharge: ");
        sb.append(BatteryStatsHelper.makemAh(dischargeScreenOffCount / 1000.0));
        sb.append(" mAh");
        pw.println(sb.toString());
    }
    final long dischargeScreenOnCount = dischargeCount - dischargeScreenOffCount;
    if (dischargeScreenOnCount >= 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Screen on discharge: ");
        sb.append(BatteryStatsHelper.makemAh(dischargeScreenOnCount / 1000.0));
        sb.append(" mAh");
        pw.println(sb.toString());
    }
    pw.print("  Start clock time: ");
    pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss", getStartClockTime()).toString());
    final long screenOnTime = getScreenOnTime(rawRealtime, which);
    final long interactiveTime = getInteractiveTime(rawRealtime, which);
    final long powerSaveModeEnabledTime = getPowerSaveModeEnabledTime(rawRealtime, which);
    final long deviceIdleModeLightTime = getDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT, rawRealtime, which);
    final long deviceIdleModeFullTime = getDeviceIdleModeTime(DEVICE_IDLE_MODE_DEEP, rawRealtime, which);
    final long deviceLightIdlingTime = getDeviceIdlingTime(DEVICE_IDLE_MODE_LIGHT, rawRealtime, which);
    final long deviceIdlingTime = getDeviceIdlingTime(DEVICE_IDLE_MODE_DEEP, rawRealtime, which);
    final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
    final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
    final long wifiOnTime = getWifiOnTime(rawRealtime, which);
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Screen on: ");
    formatTimeMs(sb, screenOnTime / 1000);
    sb.append("(");
    sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime));
    sb.append(") ");
    sb.append(getScreenOnCount(which));
    sb.append("x, Interactive: ");
    formatTimeMs(sb, interactiveTime / 1000);
    sb.append("(");
    sb.append(formatRatioLocked(interactiveTime, whichBatteryRealtime));
    sb.append(")");
    pw.println(sb.toString());
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Screen brightnesses:");
    boolean didOne = false;
    for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
        final long time = getScreenBrightnessTime(i, rawRealtime, which);
        if (time == 0) {
            continue;
        }
        sb.append("\n    ");
        sb.append(prefix);
        didOne = true;
        sb.append(SCREEN_BRIGHTNESS_NAMES[i]);
        sb.append(" ");
        formatTimeMs(sb, time / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(time, screenOnTime));
        sb.append(")");
    }
    if (!didOne)
        sb.append(" (no activity)");
    pw.println(sb.toString());
    if (powerSaveModeEnabledTime != 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Power save mode enabled: ");
        formatTimeMs(sb, powerSaveModeEnabledTime / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(powerSaveModeEnabledTime, whichBatteryRealtime));
        sb.append(")");
        pw.println(sb.toString());
    }
    if (deviceLightIdlingTime != 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Device light idling: ");
        formatTimeMs(sb, deviceLightIdlingTime / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(deviceLightIdlingTime, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getDeviceIdlingCount(DEVICE_IDLE_MODE_LIGHT, which));
        sb.append("x");
        pw.println(sb.toString());
    }
    if (deviceIdleModeLightTime != 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Idle mode light time: ");
        formatTimeMs(sb, deviceIdleModeLightTime / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(deviceIdleModeLightTime, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getDeviceIdleModeCount(DEVICE_IDLE_MODE_LIGHT, which));
        sb.append("x");
        sb.append(" -- longest ");
        formatTimeMs(sb, getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT));
        pw.println(sb.toString());
    }
    if (deviceIdlingTime != 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Device full idling: ");
        formatTimeMs(sb, deviceIdlingTime / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(deviceIdlingTime, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getDeviceIdlingCount(DEVICE_IDLE_MODE_DEEP, which));
        sb.append("x");
        pw.println(sb.toString());
    }
    if (deviceIdleModeFullTime != 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Idle mode full time: ");
        formatTimeMs(sb, deviceIdleModeFullTime / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(deviceIdleModeFullTime, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getDeviceIdleModeCount(DEVICE_IDLE_MODE_DEEP, which));
        sb.append("x");
        sb.append(" -- longest ");
        formatTimeMs(sb, getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_DEEP));
        pw.println(sb.toString());
    }
    if (phoneOnTime != 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Active phone call: ");
        formatTimeMs(sb, phoneOnTime / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getPhoneOnCount(which));
        sb.append("x");
    }
    final int connChanges = getNumConnectivityChange(which);
    if (connChanges != 0) {
        pw.print(prefix);
        pw.print("  Connectivity changes: ");
        pw.println(connChanges);
    }
    // Calculate wakelock times across all uids.
    long fullWakeLockTimeTotalMicros = 0;
    long partialWakeLockTimeTotalMicros = 0;
    final ArrayList<TimerEntry> timers = new ArrayList<>();
    for (int iu = 0; iu < NU; 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) {
                fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked(rawRealtime, which);
            }
            final Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
            if (partialWakeTimer != null) {
                final long totalTimeMicros = partialWakeTimer.getTotalTimeLocked(rawRealtime, which);
                if (totalTimeMicros > 0) {
                    if (reqUid < 0) {
                        // Only show the ordered list of all wake
                        // locks if the caller is not asking for data
                        // about a specific uid.
                        timers.add(new TimerEntry(wakelocks.keyAt(iw), u.getUid(), partialWakeTimer, totalTimeMicros));
                    }
                    partialWakeLockTimeTotalMicros += totalTimeMicros;
                }
            }
        }
    }
    final long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
    final long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
    final long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
    final long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
    final long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
    final long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
    final long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
    final long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
    final long btRxTotalBytes = getNetworkActivityBytes(NETWORK_BT_RX_DATA, which);
    final long btTxTotalBytes = getNetworkActivityBytes(NETWORK_BT_TX_DATA, which);
    if (fullWakeLockTimeTotalMicros != 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Total full wakelock time: ");
        formatTimeMsNoSpace(sb, (fullWakeLockTimeTotalMicros + 500) / 1000);
        pw.println(sb.toString());
    }
    if (partialWakeLockTimeTotalMicros != 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Total partial wakelock time: ");
        formatTimeMsNoSpace(sb, (partialWakeLockTimeTotalMicros + 500) / 1000);
        pw.println(sb.toString());
    }
    pw.print(prefix);
    pw.print("  Mobile total received: ");
    pw.print(formatBytesLocked(mobileRxTotalBytes));
    pw.print(", sent: ");
    pw.print(formatBytesLocked(mobileTxTotalBytes));
    pw.print(" (packets received ");
    pw.print(mobileRxTotalPackets);
    pw.print(", sent ");
    pw.print(mobileTxTotalPackets);
    pw.println(")");
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Phone signal levels:");
    didOne = false;
    for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
        final long time = getPhoneSignalStrengthTime(i, rawRealtime, which);
        if (time == 0) {
            continue;
        }
        sb.append("\n    ");
        sb.append(prefix);
        didOne = true;
        sb.append(SignalStrength.SIGNAL_STRENGTH_NAMES[i]);
        sb.append(" ");
        formatTimeMs(sb, time / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(time, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getPhoneSignalStrengthCount(i, which));
        sb.append("x");
    }
    if (!didOne)
        sb.append(" (no activity)");
    pw.println(sb.toString());
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Signal scanning time: ");
    formatTimeMsNoSpace(sb, getPhoneSignalScanningTime(rawRealtime, which) / 1000);
    pw.println(sb.toString());
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Radio types:");
    didOne = false;
    for (int i = 0; i < NUM_DATA_CONNECTION_TYPES; i++) {
        final long time = getPhoneDataConnectionTime(i, rawRealtime, which);
        if (time == 0) {
            continue;
        }
        sb.append("\n    ");
        sb.append(prefix);
        didOne = true;
        sb.append(DATA_CONNECTION_NAMES[i]);
        sb.append(" ");
        formatTimeMs(sb, time / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(time, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getPhoneDataConnectionCount(i, which));
        sb.append("x");
    }
    if (!didOne)
        sb.append(" (no activity)");
    pw.println(sb.toString());
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Mobile radio active time: ");
    final long mobileActiveTime = getMobileRadioActiveTime(rawRealtime, which);
    formatTimeMs(sb, mobileActiveTime / 1000);
    sb.append("(");
    sb.append(formatRatioLocked(mobileActiveTime, whichBatteryRealtime));
    sb.append(") ");
    sb.append(getMobileRadioActiveCount(which));
    sb.append("x");
    pw.println(sb.toString());
    final long mobileActiveUnknownTime = getMobileRadioActiveUnknownTime(which);
    if (mobileActiveUnknownTime != 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Mobile radio active unknown time: ");
        formatTimeMs(sb, mobileActiveUnknownTime / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(mobileActiveUnknownTime, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getMobileRadioActiveUnknownCount(which));
        sb.append("x");
        pw.println(sb.toString());
    }
    final long mobileActiveAdjustedTime = getMobileRadioActiveAdjustedTime(which);
    if (mobileActiveAdjustedTime != 0) {
        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Mobile radio active adjusted time: ");
        formatTimeMs(sb, mobileActiveAdjustedTime / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(mobileActiveAdjustedTime, whichBatteryRealtime));
        sb.append(")");
        pw.println(sb.toString());
    }
    printControllerActivity(pw, sb, prefix, "Radio", getModemControllerActivity(), which);
    pw.print(prefix);
    pw.print("  Wi-Fi total received: ");
    pw.print(formatBytesLocked(wifiRxTotalBytes));
    pw.print(", sent: ");
    pw.print(formatBytesLocked(wifiTxTotalBytes));
    pw.print(" (packets received ");
    pw.print(wifiRxTotalPackets);
    pw.print(", sent ");
    pw.print(wifiTxTotalPackets);
    pw.println(")");
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Wifi on: ");
    formatTimeMs(sb, wifiOnTime / 1000);
    sb.append("(");
    sb.append(formatRatioLocked(wifiOnTime, whichBatteryRealtime));
    sb.append("), Wifi running: ");
    formatTimeMs(sb, wifiRunningTime / 1000);
    sb.append("(");
    sb.append(formatRatioLocked(wifiRunningTime, whichBatteryRealtime));
    sb.append(")");
    pw.println(sb.toString());
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Wifi states:");
    didOne = false;
    for (int i = 0; i < NUM_WIFI_STATES; i++) {
        final long time = getWifiStateTime(i, rawRealtime, which);
        if (time == 0) {
            continue;
        }
        sb.append("\n    ");
        didOne = true;
        sb.append(WIFI_STATE_NAMES[i]);
        sb.append(" ");
        formatTimeMs(sb, time / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(time, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getWifiStateCount(i, which));
        sb.append("x");
    }
    if (!didOne)
        sb.append(" (no activity)");
    pw.println(sb.toString());
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Wifi supplicant states:");
    didOne = false;
    for (int i = 0; i < NUM_WIFI_SUPPL_STATES; i++) {
        final long time = getWifiSupplStateTime(i, rawRealtime, which);
        if (time == 0) {
            continue;
        }
        sb.append("\n    ");
        didOne = true;
        sb.append(WIFI_SUPPL_STATE_NAMES[i]);
        sb.append(" ");
        formatTimeMs(sb, time / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(time, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getWifiSupplStateCount(i, which));
        sb.append("x");
    }
    if (!didOne)
        sb.append(" (no activity)");
    pw.println(sb.toString());
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Wifi signal levels:");
    didOne = false;
    for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
        final long time = getWifiSignalStrengthTime(i, rawRealtime, which);
        if (time == 0) {
            continue;
        }
        sb.append("\n    ");
        sb.append(prefix);
        didOne = true;
        sb.append("level(");
        sb.append(i);
        sb.append(") ");
        formatTimeMs(sb, time / 1000);
        sb.append("(");
        sb.append(formatRatioLocked(time, whichBatteryRealtime));
        sb.append(") ");
        sb.append(getWifiSignalStrengthCount(i, which));
        sb.append("x");
    }
    if (!didOne)
        sb.append(" (no activity)");
    pw.println(sb.toString());
    printControllerActivity(pw, sb, prefix, "WiFi", getWifiControllerActivity(), which);
    pw.print(prefix);
    pw.print("  Bluetooth total received: ");
    pw.print(formatBytesLocked(btRxTotalBytes));
    pw.print(", sent: ");
    pw.println(formatBytesLocked(btTxTotalBytes));
    final long bluetoothScanTimeMs = getBluetoothScanTime(rawRealtime, which) / 1000;
    sb.setLength(0);
    sb.append(prefix);
    sb.append("  Bluetooth scan time: ");
    formatTimeMs(sb, bluetoothScanTimeMs);
    pw.println(sb.toString());
    printControllerActivity(pw, sb, prefix, "Bluetooth", getBluetoothControllerActivity(), which);
    pw.println();
    if (which == STATS_SINCE_UNPLUGGED) {
        if (getIsOnBattery()) {
            pw.print(prefix);
            pw.println("  Device is currently unplugged");
            pw.print(prefix);
            pw.print("    Discharge cycle start level: ");
            pw.println(getDischargeStartLevel());
            pw.print(prefix);
            pw.print("    Discharge cycle current level: ");
            pw.println(getDischargeCurrentLevel());
        } else {
            pw.print(prefix);
            pw.println("  Device is currently plugged into power");
            pw.print(prefix);
            pw.print("    Last discharge cycle start level: ");
            pw.println(getDischargeStartLevel());
            pw.print(prefix);
            pw.print("    Last discharge cycle end level: ");
            pw.println(getDischargeCurrentLevel());
        }
        pw.print(prefix);
        pw.print("    Amount discharged while screen on: ");
        pw.println(getDischargeAmountScreenOn());
        pw.print(prefix);
        pw.print("    Amount discharged while screen off: ");
        pw.println(getDischargeAmountScreenOff());
        pw.println(" ");
    } else {
        pw.print(prefix);
        pw.println("  Device battery use since last full charge");
        pw.print(prefix);
        pw.print("    Amount discharged (lower bound): ");
        pw.println(getLowDischargeAmountSinceCharge());
        pw.print(prefix);
        pw.print("    Amount discharged (upper bound): ");
        pw.println(getHighDischargeAmountSinceCharge());
        pw.print(prefix);
        pw.print("    Amount discharged while screen on: ");
        pw.println(getDischargeAmountScreenOnSinceCharge());
        pw.print(prefix);
        pw.print("    Amount discharged while screen off: ");
        pw.println(getDischargeAmountScreenOffSinceCharge());
        pw.println();
    }
    final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
    helper.create(this);
    helper.refreshStats(which, UserHandle.USER_ALL);
    List<BatterySipper> sippers = helper.getUsageList();
    if (sippers != null && sippers.size() > 0) {
        pw.print(prefix);
        pw.println("  Estimated power use (mAh):");
        pw.print(prefix);
        pw.print("    Capacity: ");
        printmAh(pw, helper.getPowerProfile().getBatteryCapacity());
        pw.print(", Computed drain: ");
        printmAh(pw, helper.getComputedPower());
        pw.print(", actual drain: ");
        printmAh(pw, helper.getMinDrainedPower());
        if (helper.getMinDrainedPower() != helper.getMaxDrainedPower()) {
            pw.print("-");
            printmAh(pw, helper.getMaxDrainedPower());
        }
        pw.println();
        for (int i = 0; i < sippers.size(); i++) {
            final BatterySipper bs = sippers.get(i);
            pw.print(prefix);
            switch(bs.drainType) {
                case IDLE:
                    pw.print("    Idle: ");
                    break;
                case CELL:
                    pw.print("    Cell standby: ");
                    break;
                case PHONE:
                    pw.print("    Phone calls: ");
                    break;
                case WIFI:
                    pw.print("    Wifi: ");
                    break;
                case BLUETOOTH:
                    pw.print("    Bluetooth: ");
                    break;
                case SCREEN:
                    pw.print("    Screen: ");
                    break;
                case FLASHLIGHT:
                    pw.print("    Flashlight: ");
                    break;
                case APP:
                    pw.print("    Uid ");
                    UserHandle.formatUid(pw, bs.uidObj.getUid());
                    pw.print(": ");
                    break;
                case USER:
                    pw.print("    User ");
                    pw.print(bs.userId);
                    pw.print(": ");
                    break;
                case UNACCOUNTED:
                    pw.print("    Unaccounted: ");
                    break;
                case OVERCOUNTED:
                    pw.print("    Over-counted: ");
                    break;
                case CAMERA:
                    pw.print("    Camera: ");
                    break;
                default:
                    pw.print("    ???: ");
                    break;
            }
            printmAh(pw, bs.totalPowerMah);
            if (bs.usagePowerMah != bs.totalPowerMah) {
                // If the usage (generic power) isn't the whole amount, we list out
                // what components are involved in the calculation.
                pw.print(" (");
                if (bs.usagePowerMah != 0) {
                    pw.print(" usage=");
                    printmAh(pw, bs.usagePowerMah);
                }
                if (bs.cpuPowerMah != 0) {
                    pw.print(" cpu=");
                    printmAh(pw, bs.cpuPowerMah);
                }
                if (bs.wakeLockPowerMah != 0) {
                    pw.print(" wake=");
                    printmAh(pw, bs.wakeLockPowerMah);
                }
                if (bs.mobileRadioPowerMah != 0) {
                    pw.print(" radio=");
                    printmAh(pw, bs.mobileRadioPowerMah);
                }
                if (bs.wifiPowerMah != 0) {
                    pw.print(" wifi=");
                    printmAh(pw, bs.wifiPowerMah);
                }
                if (bs.bluetoothPowerMah != 0) {
                    pw.print(" bt=");
                    printmAh(pw, bs.bluetoothPowerMah);
                }
                if (bs.gpsPowerMah != 0) {
                    pw.print(" gps=");
                    printmAh(pw, bs.gpsPowerMah);
                }
                if (bs.sensorPowerMah != 0) {
                    pw.print(" sensor=");
                    printmAh(pw, bs.sensorPowerMah);
                }
                if (bs.cameraPowerMah != 0) {
                    pw.print(" camera=");
                    printmAh(pw, bs.cameraPowerMah);
                }
                if (bs.flashlightPowerMah != 0) {
                    pw.print(" flash=");
                    printmAh(pw, bs.flashlightPowerMah);
                }
                pw.print(" )");
            }
            pw.println();
        }
        pw.println();
    }
    sippers = helper.getMobilemsppList();
    if (sippers != null && sippers.size() > 0) {
        pw.print(prefix);
        pw.println("  Per-app mobile ms per packet:");
        long totalTime = 0;
        for (int i = 0; i < sippers.size(); i++) {
            final BatterySipper bs = sippers.get(i);
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    Uid ");
            UserHandle.formatUid(sb, bs.uidObj.getUid());
            sb.append(": ");
            sb.append(BatteryStatsHelper.makemAh(bs.mobilemspp));
            sb.append(" (");
            sb.append(bs.mobileRxPackets + bs.mobileTxPackets);
            sb.append(" packets over ");
            formatTimeMsNoSpace(sb, bs.mobileActive);
            sb.append(") ");
            sb.append(bs.mobileActiveCount);
            sb.append("x");
            pw.println(sb.toString());
            totalTime += bs.mobileActive;
        }
        sb.setLength(0);
        sb.append(prefix);
        sb.append("    TOTAL TIME: ");
        formatTimeMs(sb, totalTime);
        sb.append("(");
        sb.append(formatRatioLocked(totalTime, whichBatteryRealtime));
        sb.append(")");
        pw.println(sb.toString());
        pw.println();
    }
    final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {

        @Override
        public int compare(TimerEntry lhs, TimerEntry rhs) {
            long lhsTime = lhs.mTime;
            long rhsTime = rhs.mTime;
            if (lhsTime < rhsTime) {
                return 1;
            }
            if (lhsTime > rhsTime) {
                return -1;
            }
            return 0;
        }
    };
    if (reqUid < 0) {
        final Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
        if (kernelWakelocks.size() > 0) {
            final ArrayList<TimerEntry> ktimers = new ArrayList<>();
            for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
                final BatteryStats.Timer timer = ent.getValue();
                final long totalTimeMillis = computeWakeLock(timer, rawRealtime, which);
                if (totalTimeMillis > 0) {
                    ktimers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
                }
            }
            if (ktimers.size() > 0) {
                Collections.sort(ktimers, timerComparator);
                pw.print(prefix);
                pw.println("  All kernel wake locks:");
                for (int i = 0; i < ktimers.size(); i++) {
                    final TimerEntry timer = ktimers.get(i);
                    String linePrefix = ": ";
                    sb.setLength(0);
                    sb.append(prefix);
                    sb.append("  Kernel Wake lock ");
                    sb.append(timer.mName);
                    linePrefix = printWakeLock(sb, timer.mTimer, rawRealtime, null, which, linePrefix);
                    if (!linePrefix.equals(": ")) {
                        sb.append(" realtime");
                        // Only print out wake locks that were held
                        pw.println(sb.toString());
                    }
                }
                pw.println();
            }
        }
        if (timers.size() > 0) {
            Collections.sort(timers, timerComparator);
            pw.print(prefix);
            pw.println("  All partial wake locks:");
            for (int i = 0; i < timers.size(); i++) {
                TimerEntry timer = timers.get(i);
                sb.setLength(0);
                sb.append("  Wake lock ");
                UserHandle.formatUid(sb, timer.mId);
                sb.append(" ");
                sb.append(timer.mName);
                printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": ");
                sb.append(" realtime");
                pw.println(sb.toString());
            }
            timers.clear();
            pw.println();
        }
        final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
        if (wakeupReasons.size() > 0) {
            pw.print(prefix);
            pw.println("  All wakeup reasons:");
            final ArrayList<TimerEntry> reasons = new ArrayList<>();
            for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) {
                final Timer timer = ent.getValue();
                reasons.add(new TimerEntry(ent.getKey(), 0, timer, timer.getCountLocked(which)));
            }
            Collections.sort(reasons, timerComparator);
            for (int i = 0; i < reasons.size(); i++) {
                TimerEntry timer = reasons.get(i);
                String linePrefix = ": ";
                sb.setLength(0);
                sb.append(prefix);
                sb.append("  Wakeup reason ");
                sb.append(timer.mName);
                printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": ");
                sb.append(" realtime");
                pw.println(sb.toString());
            }
            pw.println();
        }
    }
    for (int iu = 0; iu < NU; iu++) {
        final int uid = uidStats.keyAt(iu);
        if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) {
            continue;
        }
        final Uid u = uidStats.valueAt(iu);
        pw.print(prefix);
        pw.print("  ");
        UserHandle.formatUid(pw, uid);
        pw.println(":");
        boolean uidActivity = false;
        final long mobileRxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
        final long mobileTxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
        final long wifiRxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
        final long wifiTxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
        final long btRxBytes = u.getNetworkActivityBytes(NETWORK_BT_RX_DATA, which);
        final long btTxBytes = u.getNetworkActivityBytes(NETWORK_BT_TX_DATA, which);
        final long mobileRxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
        final long mobileTxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
        final long wifiRxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
        final long wifiTxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
        final long uidMobileActiveTime = u.getMobileRadioActiveTime(which);
        final int uidMobileActiveCount = u.getMobileRadioActiveCount(which);
        final long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
        final long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
        final int wifiScanCount = u.getWifiScanCount(which);
        final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
        final long mobileWakeup = u.getMobileRadioApWakeupCount(which);
        final long wifiWakeup = u.getWifiRadioApWakeupCount(which);
        if (mobileRxBytes > 0 || mobileTxBytes > 0 || mobileRxPackets > 0 || mobileTxPackets > 0) {
            pw.print(prefix);
            pw.print("    Mobile network: ");
            pw.print(formatBytesLocked(mobileRxBytes));
            pw.print(" received, ");
            pw.print(formatBytesLocked(mobileTxBytes));
            pw.print(" sent (packets ");
            pw.print(mobileRxPackets);
            pw.print(" received, ");
            pw.print(mobileTxPackets);
            pw.println(" sent)");
        }
        if (uidMobileActiveTime > 0 || uidMobileActiveCount > 0) {
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    Mobile radio active: ");
            formatTimeMs(sb, uidMobileActiveTime / 1000);
            sb.append("(");
            sb.append(formatRatioLocked(uidMobileActiveTime, mobileActiveTime));
            sb.append(") ");
            sb.append(uidMobileActiveCount);
            sb.append("x");
            long packets = mobileRxPackets + mobileTxPackets;
            if (packets == 0) {
                packets = 1;
            }
            sb.append(" @ ");
            sb.append(BatteryStatsHelper.makemAh(uidMobileActiveTime / 1000 / (double) packets));
            sb.append(" mspp");
            pw.println(sb.toString());
        }
        if (mobileWakeup > 0) {
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    Mobile radio AP wakeups: ");
            sb.append(mobileWakeup);
            pw.println(sb.toString());
        }
        printControllerActivityIfInteresting(pw, sb, prefix + "  ", "Modem", u.getModemControllerActivity(), which);
        if (wifiRxBytes > 0 || wifiTxBytes > 0 || wifiRxPackets > 0 || wifiTxPackets > 0) {
            pw.print(prefix);
            pw.print("    Wi-Fi network: ");
            pw.print(formatBytesLocked(wifiRxBytes));
            pw.print(" received, ");
            pw.print(formatBytesLocked(wifiTxBytes));
            pw.print(" sent (packets ");
            pw.print(wifiRxPackets);
            pw.print(" received, ");
            pw.print(wifiTxPackets);
            pw.println(" sent)");
        }
        if (fullWifiLockOnTime != 0 || wifiScanTime != 0 || wifiScanCount != 0 || uidWifiRunningTime != 0) {
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    Wifi Running: ");
            formatTimeMs(sb, uidWifiRunningTime / 1000);
            sb.append("(");
            sb.append(formatRatioLocked(uidWifiRunningTime, whichBatteryRealtime));
            sb.append(")\n");
            sb.append(prefix);
            sb.append("    Full Wifi Lock: ");
            formatTimeMs(sb, fullWifiLockOnTime / 1000);
            sb.append("(");
            sb.append(formatRatioLocked(fullWifiLockOnTime, whichBatteryRealtime));
            sb.append(")\n");
            sb.append(prefix);
            sb.append("    Wifi Scan: ");
            formatTimeMs(sb, wifiScanTime / 1000);
            sb.append("(");
            sb.append(formatRatioLocked(wifiScanTime, whichBatteryRealtime));
            sb.append(") ");
            sb.append(wifiScanCount);
            sb.append("x");
            pw.println(sb.toString());
        }
        if (wifiWakeup > 0) {
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    WiFi AP wakeups: ");
            sb.append(wifiWakeup);
            pw.println(sb.toString());
        }
        printControllerActivityIfInteresting(pw, sb, prefix + "  ", "WiFi", u.getWifiControllerActivity(), which);
        if (btRxBytes > 0 || btTxBytes > 0) {
            pw.print(prefix);
            pw.print("    Bluetooth network: ");
            pw.print(formatBytesLocked(btRxBytes));
            pw.print(" received, ");
            pw.print(formatBytesLocked(btTxBytes));
            pw.println(" sent");
        }
        uidActivity |= printTimer(pw, sb, u.getBluetoothScanTimer(), rawRealtime, which, prefix, "Bluetooth Scan");
        if (u.hasUserActivity()) {
            boolean hasData = false;
            for (int i = 0; i < Uid.NUM_USER_ACTIVITY_TYPES; i++) {
                final int val = u.getUserActivityCount(i, which);
                if (val != 0) {
                    if (!hasData) {
                        sb.setLength(0);
                        sb.append("    User activity: ");
                        hasData = true;
                    } else {
                        sb.append(", ");
                    }
                    sb.append(val);
                    sb.append(" ");
                    sb.append(Uid.USER_ACTIVITY_TYPES[i]);
                }
            }
            if (hasData) {
                pw.println(sb.toString());
            }
        }
        final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
        long totalFullWakelock = 0, totalPartialWakelock = 0, totalWindowWakelock = 0;
        long totalDrawWakelock = 0;
        int countWakelock = 0;
        for (int iw = wakelocks.size() - 1; iw >= 0; iw--) {
            final Uid.Wakelock wl = wakelocks.valueAt(iw);
            String linePrefix = ": ";
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    Wake lock ");
            sb.append(wakelocks.keyAt(iw));
            linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), rawRealtime, "full", which, linePrefix);
            linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), rawRealtime, "partial", which, linePrefix);
            linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime, "window", which, linePrefix);
            linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_DRAW), rawRealtime, "draw", which, linePrefix);
            sb.append(" realtime");
            pw.println(sb.toString());
            uidActivity = true;
            countWakelock++;
            totalFullWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL), rawRealtime, which);
            totalPartialWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL), rawRealtime, which);
            totalWindowWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime, which);
            totalDrawWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_DRAW), rawRealtime, which);
        }
        if (countWakelock > 1) {
            if (totalFullWakelock != 0 || totalPartialWakelock != 0 || totalWindowWakelock != 0) {
                sb.setLength(0);
                sb.append(prefix);
                sb.append("    TOTAL wake: ");
                boolean needComma = false;
                if (totalFullWakelock != 0) {
                    needComma = true;
                    formatTimeMs(sb, totalFullWakelock);
                    sb.append("full");
                }
                if (totalPartialWakelock != 0) {
                    if (needComma) {
                        sb.append(", ");
                    }
                    needComma = true;
                    formatTimeMs(sb, totalPartialWakelock);
                    sb.append("partial");
                }
                if (totalWindowWakelock != 0) {
                    if (needComma) {
                        sb.append(", ");
                    }
                    needComma = true;
                    formatTimeMs(sb, totalWindowWakelock);
                    sb.append("window");
                }
                if (totalDrawWakelock != 0) {
                    if (needComma) {
                        sb.append(",");
                    }
                    needComma = true;
                    formatTimeMs(sb, totalDrawWakelock);
                    sb.append("draw");
                }
                sb.append(" realtime");
                pw.println(sb.toString());
            }
        }
        final ArrayMap<String, ? extends Timer> syncs = u.getSyncStats();
        for (int isy = syncs.size() - 1; isy >= 0; isy--) {
            final Timer timer = syncs.valueAt(isy);
            // Convert from microseconds to milliseconds with rounding
            final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
            final int count = timer.getCountLocked(which);
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    Sync ");
            sb.append(syncs.keyAt(isy));
            sb.append(": ");
            if (totalTime != 0) {
                formatTimeMs(sb, totalTime);
                sb.append("realtime (");
                sb.append(count);
                sb.append(" times)");
            } else {
                sb.append("(not used)");
            }
            pw.println(sb.toString());
            uidActivity = true;
        }
        final ArrayMap<String, ? extends Timer> jobs = u.getJobStats();
        for (int ij = jobs.size() - 1; ij >= 0; ij--) {
            final Timer timer = jobs.valueAt(ij);
            // Convert from microseconds to milliseconds with rounding
            final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
            final int count = timer.getCountLocked(which);
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    Job ");
            sb.append(jobs.keyAt(ij));
            sb.append(": ");
            if (totalTime != 0) {
                formatTimeMs(sb, totalTime);
                sb.append("realtime (");
                sb.append(count);
                sb.append(" times)");
            } else {
                sb.append("(not used)");
            }
            pw.println(sb.toString());
            uidActivity = true;
        }
        uidActivity |= printTimer(pw, sb, u.getFlashlightTurnedOnTimer(), rawRealtime, which, prefix, "Flashlight");
        uidActivity |= printTimer(pw, sb, u.getCameraTurnedOnTimer(), rawRealtime, which, prefix, "Camera");
        uidActivity |= printTimer(pw, sb, u.getVideoTurnedOnTimer(), rawRealtime, which, prefix, "Video");
        uidActivity |= printTimer(pw, sb, u.getAudioTurnedOnTimer(), rawRealtime, which, prefix, "Audio");
        final SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
        final int NSE = sensors.size();
        for (int ise = 0; ise < NSE; ise++) {
            final Uid.Sensor se = sensors.valueAt(ise);
            final int sensorNumber = sensors.keyAt(ise);
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    Sensor ");
            int handle = se.getHandle();
            if (handle == Uid.Sensor.GPS) {
                sb.append("GPS");
            } else {
                sb.append(handle);
            }
            sb.append(": ");
            final Timer timer = se.getSensorTime();
            if (timer != null) {
                // Convert from microseconds to milliseconds with rounding
                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
                final int count = timer.getCountLocked(which);
                //timer.logState();
                if (totalTime != 0) {
                    formatTimeMs(sb, totalTime);
                    sb.append("realtime (");
                    sb.append(count);
                    sb.append(" times)");
                } else {
                    sb.append("(not used)");
                }
            } else {
                sb.append("(not used)");
            }
            pw.println(sb.toString());
            uidActivity = true;
        }
        uidActivity |= printTimer(pw, sb, u.getVibratorOnTimer(), rawRealtime, which, prefix, "Vibrator");
        uidActivity |= printTimer(pw, sb, u.getForegroundActivityTimer(), rawRealtime, which, prefix, "Foreground activities");
        long totalStateTime = 0;
        for (int ips = 0; ips < Uid.NUM_PROCESS_STATE; ips++) {
            long time = u.getProcessStateTime(ips, rawRealtime, which);
            if (time > 0) {
                totalStateTime += time;
                sb.setLength(0);
                sb.append(prefix);
                sb.append("    ");
                sb.append(Uid.PROCESS_STATE_NAMES[ips]);
                sb.append(" for: ");
                formatTimeMs(sb, (time + 500) / 1000);
                pw.println(sb.toString());
                uidActivity = true;
            }
        }
        if (totalStateTime > 0) {
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    Total running: ");
            formatTimeMs(sb, (totalStateTime + 500) / 1000);
            pw.println(sb.toString());
        }
        final long userCpuTimeUs = u.getUserCpuTimeUs(which);
        final long systemCpuTimeUs = u.getSystemCpuTimeUs(which);
        final long powerCpuMaUs = u.getCpuPowerMaUs(which);
        if (userCpuTimeUs > 0 || systemCpuTimeUs > 0 || powerCpuMaUs > 0) {
            sb.setLength(0);
            sb.append(prefix);
            sb.append("    Total cpu time: u=");
            formatTimeMs(sb, userCpuTimeUs / 1000);
            sb.append("s=");
            formatTimeMs(sb, systemCpuTimeUs / 1000);
            sb.append("p=");
            printmAh(sb, powerCpuMaUs / (1000.0 * 1000.0 * 60.0 * 60.0));
            sb.append("mAh");
            pw.println(sb.toString());
        }
        final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
        for (int ipr = processStats.size() - 1; ipr >= 0; ipr--) {
            final Uid.Proc ps = processStats.valueAt(ipr);
            long userTime;
            long systemTime;
            long foregroundTime;
            int starts;
            int numExcessive;
            userTime = ps.getUserTime(which);
            systemTime = ps.getSystemTime(which);
            foregroundTime = ps.getForegroundTime(which);
            starts = ps.getStarts(which);
            final int numCrashes = ps.getNumCrashes(which);
            final int numAnrs = ps.getNumAnrs(which);
            numExcessive = which == STATS_SINCE_CHARGED ? ps.countExcessivePowers() : 0;
            if (userTime != 0 || systemTime != 0 || foregroundTime != 0 || starts != 0 || numExcessive != 0 || numCrashes != 0 || numAnrs != 0) {
                sb.setLength(0);
                sb.append(prefix);
                sb.append("    Proc ");
                sb.append(processStats.keyAt(ipr));
                sb.append(":\n");
                sb.append(prefix);
                sb.append("      CPU: ");
                formatTimeMs(sb, userTime);
                sb.append("usr + ");
                formatTimeMs(sb, systemTime);
                sb.append("krn ; ");
                formatTimeMs(sb, foregroundTime);
                sb.append("fg");
                if (starts != 0 || numCrashes != 0 || numAnrs != 0) {
                    sb.append("\n");
                    sb.append(prefix);
                    sb.append("      ");
                    boolean hasOne = false;
                    if (starts != 0) {
                        hasOne = true;
                        sb.append(starts);
                        sb.append(" starts");
                    }
                    if (numCrashes != 0) {
                        if (hasOne) {
                            sb.append(", ");
                        }
                        hasOne = true;
                        sb.append(numCrashes);
                        sb.append(" crashes");
                    }
                    if (numAnrs != 0) {
                        if (hasOne) {
                            sb.append(", ");
                        }
                        sb.append(numAnrs);
                        sb.append(" anrs");
                    }
                }
                pw.println(sb.toString());
                for (int e = 0; e < numExcessive; e++) {
                    Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e);
                    if (ew != null) {
                        pw.print(prefix);
                        pw.print("      * Killed for ");
                        if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) {
                            pw.print("wake lock");
                        } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) {
                            pw.print("cpu");
                        } else {
                            pw.print("unknown");
                        }
                        pw.print(" use: ");
                        TimeUtils.formatDuration(ew.usedTime, pw);
                        pw.print(" over ");
                        TimeUtils.formatDuration(ew.overTime, pw);
                        if (ew.overTime != 0) {
                            pw.print(" (");
                            pw.print((ew.usedTime * 100) / ew.overTime);
                            pw.println("%)");
                        }
                    }
                }
                uidActivity = true;
            }
        }
        final ArrayMap<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
        for (int ipkg = packageStats.size() - 1; ipkg >= 0; ipkg--) {
            pw.print(prefix);
            pw.print("    Apk ");
            pw.print(packageStats.keyAt(ipkg));
            pw.println(":");
            boolean apkActivity = false;
            final Uid.Pkg ps = packageStats.valueAt(ipkg);
            final ArrayMap<String, ? extends Counter> alarms = ps.getWakeupAlarmStats();
            for (int iwa = alarms.size() - 1; iwa >= 0; iwa--) {
                pw.print(prefix);
                pw.print("      Wakeup alarm ");
                pw.print(alarms.keyAt(iwa));
                pw.print(": ");
                pw.print(alarms.valueAt(iwa).getCountLocked(which));
                pw.println(" times");
                apkActivity = true;
            }
            final ArrayMap<String, ? extends Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
            for (int isvc = serviceStats.size() - 1; isvc >= 0; isvc--) {
                final BatteryStats.Uid.Pkg.Serv ss = serviceStats.valueAt(isvc);
                final long startTime = ss.getStartTime(batteryUptime, which);
                final int starts = ss.getStarts(which);
                final int launches = ss.getLaunches(which);
                if (startTime != 0 || starts != 0 || launches != 0) {
                    sb.setLength(0);
                    sb.append(prefix);
                    sb.append("      Service ");
                    sb.append(serviceStats.keyAt(isvc));
                    sb.append(":\n");
                    sb.append(prefix);
                    sb.append("        Created for: ");
                    formatTimeMs(sb, startTime / 1000);
                    sb.append("uptime\n");
                    sb.append(prefix);
                    sb.append("        Starts: ");
                    sb.append(starts);
                    sb.append(", launches: ");
                    sb.append(launches);
                    pw.println(sb.toString());
                    apkActivity = true;
                }
            }
            if (!apkActivity) {
                pw.print(prefix);
                pw.println("      (nothing executed)");
            }
            uidActivity = true;
        }
        if (!uidActivity) {
            pw.print(prefix);
            pw.println("    (nothing executed)");
        }
    }
}
Also used : ArrayList(java.util.ArrayList) Comparator(java.util.Comparator) BatterySipper(com.android.internal.os.BatterySipper) BatteryStatsHelper(com.android.internal.os.BatteryStatsHelper) HashMap(java.util.HashMap) Map(java.util.Map) ArrayMap(android.util.ArrayMap)

Aggregations

BatterySipper (com.android.internal.os.BatterySipper)148 ArrayList (java.util.ArrayList)60 BatteryStats (android.os.BatteryStats)48 VisibleForTesting (android.support.annotation.VisibleForTesting)30 Test (org.junit.Test)29 Anomaly (com.android.settings.fuelgauge.anomaly.Anomaly)18 HashMap (java.util.HashMap)16 UserHandle (android.os.UserHandle)15 ArrayMap (android.util.ArrayMap)10 BatteryStatsHelper (com.android.internal.os.BatteryStatsHelper)10 Map (java.util.Map)10 Drawable (android.graphics.drawable.Drawable)8 SparseArray (android.util.SparseArray)8 DrainType (com.android.internal.os.BatterySipper.DrainType)8 PowerProfile (com.android.internal.os.PowerProfile)8 Bundle (android.os.Bundle)7 SparseLongArray (android.util.SparseLongArray)7 Context (android.content.Context)6 TypedArray (android.content.res.TypedArray)6 PowerUsageData (com.android.settings.fuelgauge.PowerUsageAdvanced.PowerUsageData)6