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

Commit b62b1fad authored by Dmitri Plotnikov's avatar Dmitri Plotnikov Committed by Android (Google) Code Review
Browse files

Merge "Convert MobileRadioPowerCalculator to work with BatteryUsageStats"

parents 6d6a9489 dfce5289
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ public abstract class BatteryConsumer {
            POWER_COMPONENT_AUDIO,
            POWER_COMPONENT_VIDEO,
            POWER_COMPONENT_FLASHLIGHT,
            POWER_COMPONENT_MOBILE_RADIO,
            POWER_COMPONENT_SYSTEM_SERVICES,
    })
    @Retention(RetentionPolicy.SOURCE)
@@ -57,8 +58,9 @@ public abstract class BatteryConsumer {
    public static final int POWER_COMPONENT_VIDEO = 5;
    public static final int POWER_COMPONENT_FLASHLIGHT = 6;
    public static final int POWER_COMPONENT_SYSTEM_SERVICES = 7;
    public static final int POWER_COMPONENT_MOBILE_RADIO = 8;

    public static final int POWER_COMPONENT_COUNT = 8;
    public static final int POWER_COMPONENT_COUNT = 9;

    public static final int FIRST_CUSTOM_POWER_COMPONENT_ID = 1000;
    public static final int LAST_CUSTOM_POWER_COMPONENT_ID = 9999;
@@ -87,6 +89,7 @@ public abstract class BatteryConsumer {
            TIME_COMPONENT_BLUETOOTH,
            TIME_COMPONENT_CAMERA,
            TIME_COMPONENT_FLASHLIGHT,
            TIME_COMPONENT_MOBILE_RADIO,
    })
    @Retention(RetentionPolicy.SOURCE)
    public static @interface TimeComponent {
@@ -100,8 +103,9 @@ public abstract class BatteryConsumer {
    public static final int TIME_COMPONENT_AUDIO = 5;
    public static final int TIME_COMPONENT_VIDEO = 6;
    public static final int TIME_COMPONENT_FLASHLIGHT = 7;
    public static final int TIME_COMPONENT_MOBILE_RADIO = 8;

    public static final int TIME_COMPONENT_COUNT = 8;
    public static final int TIME_COMPONENT_COUNT = 9;

    public static final int FIRST_CUSTOM_TIME_COMPONENT_ID = 1000;
    public static final int LAST_CUSTOM_TIME_COMPONENT_ID = 9999;
+2 −2
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ public class SystemBatteryConsumer extends BatteryConsumer implements Parcelable
            // Reserved: APP
            DRAIN_TYPE_BLUETOOTH,
            DRAIN_TYPE_CAMERA,
            DRAIN_TYPE_CELL,
            DRAIN_TYPE_MOBILE_RADIO,
            DRAIN_TYPE_FLASHLIGHT,
            DRAIN_TYPE_IDLE,
            DRAIN_TYPE_MEMORY,
@@ -59,7 +59,7 @@ public class SystemBatteryConsumer extends BatteryConsumer implements Parcelable
    public static final int DRAIN_TYPE_AMBIENT_DISPLAY = 0;
    public static final int DRAIN_TYPE_BLUETOOTH = 2;
    public static final int DRAIN_TYPE_CAMERA = 3;
    public static final int DRAIN_TYPE_CELL = 4;
    public static final int DRAIN_TYPE_MOBILE_RADIO = 4;
    public static final int DRAIN_TYPE_FLASHLIGHT = 5;
    public static final int DRAIN_TYPE_IDLE = 6;
    public static final int DRAIN_TYPE_MEMORY = 7;
+35 −34
Original line number Diff line number Diff line
@@ -860,14 +860,11 @@ public class BatteryStatsImpl extends BatteryStats {
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    protected int mScreenState = Display.STATE_UNKNOWN;
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    protected StopwatchTimer mScreenOnTimer;
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    protected StopwatchTimer mScreenDozeTimer;
    StopwatchTimer mScreenOnTimer;
    StopwatchTimer mScreenDozeTimer;
    int mScreenBrightnessBin = -1;
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    protected final StopwatchTimer[] mScreenBrightnessTimer =
    final StopwatchTimer[] mScreenBrightnessTimer =
            new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
    boolean mPretendScreenOff;
@@ -912,8 +909,7 @@ public class BatteryStatsImpl extends BatteryStats {
    int mUsbDataState = USB_DATA_UNKNOWN;
    int mGpsSignalQualityBin = -1;
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    protected final StopwatchTimer[] mGpsSignalQualityTimer =
    final StopwatchTimer[] mGpsSignalQualityTimer =
        new StopwatchTimer[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS];
    int mPhoneSignalStrengthBin = -1;
@@ -929,6 +925,7 @@ public class BatteryStatsImpl extends BatteryStats {
    final LongSamplingCounter[] mNetworkByteActivityCounters =
            new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
    final LongSamplingCounter[] mNetworkPacketActivityCounters =
            new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
@@ -948,8 +945,7 @@ public class BatteryStatsImpl extends BatteryStats {
    /**
     * The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
     */
    @VisibleForTesting
    protected ControllerActivityCounterImpl mBluetoothActivity;
    ControllerActivityCounterImpl mBluetoothActivity;
    /**
     * The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
@@ -993,8 +989,7 @@ public class BatteryStatsImpl extends BatteryStats {
    StopwatchTimer mWifiActiveTimer;
    int mBluetoothScanNesting;
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    protected StopwatchTimer mBluetoothScanTimer;
    StopwatchTimer mBluetoothScanTimer;
    int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
    long mMobileRadioActiveStartTimeMs;
@@ -10718,6 +10713,31 @@ public class BatteryStatsImpl extends BatteryStats {
        mHandler = new MyHandler(handler.getLooper());
        mConstants = new Constants(mHandler);
        mStartCount++;
        initTimersAndCounters();
        mOnBattery = mOnBatteryInternal = false;
        long uptimeUs = mClocks.uptimeMillis() * 1000;
        long realtimeUs = mClocks.elapsedRealtime() * 1000;
        initTimes(uptimeUs, realtimeUs);
        mStartPlatformVersion = mEndPlatformVersion = Build.ID;
        mDischargeStartLevel = 0;
        mDischargeUnplugLevel = 0;
        mDischargePlugLevel = -1;
        mDischargeCurrentLevel = 0;
        mCurrentBatteryLevel = 0;
        initDischarge(realtimeUs);
        clearHistoryLocked();
        updateDailyDeadlineLocked();
        mPlatformIdleStateCallback = cb;
        mMeasuredEnergyRetriever = energyStatsCb;
        mUserInfoProvider = userInfoProvider;
        // Notify statsd that the system is initially not in doze.
        mDeviceIdleMode = DEVICE_IDLE_MODE_OFF;
        FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mDeviceIdleMode);
    }
    @VisibleForTesting
    protected void initTimersAndCounters() {
        mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
        mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
@@ -10789,26 +10809,6 @@ public class BatteryStatsImpl extends BatteryStats {
        mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
        mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
        mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
        mOnBattery = mOnBatteryInternal = false;
        long uptimeUs = mClocks.uptimeMillis() * 1000;
        long realtimeUs = mClocks.elapsedRealtime() * 1000;
        initTimes(uptimeUs, realtimeUs);
        mStartPlatformVersion = mEndPlatformVersion = Build.ID;
        mDischargeStartLevel = 0;
        mDischargeUnplugLevel = 0;
        mDischargePlugLevel = -1;
        mDischargeCurrentLevel = 0;
        mCurrentBatteryLevel = 0;
        initDischarge(realtimeUs);
        clearHistoryLocked();
        updateDailyDeadlineLocked();
        mPlatformIdleStateCallback = cb;
        mMeasuredEnergyRetriever = energyStatsCb;
        mUserInfoProvider = userInfoProvider;
        // Notify statsd that the system is initially not in doze.
        mDeviceIdleMode = DEVICE_IDLE_MODE_OFF;
        FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mDeviceIdleMode);
    }
    @UnsupportedAppUsage
@@ -11623,7 +11623,8 @@ public class BatteryStatsImpl extends BatteryStats {
    @GuardedBy("mModemNetworkLock")
    private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1);
    private NetworkStats readNetworkStatsLocked(String[] ifaces) {
    @VisibleForTesting
    protected NetworkStats readNetworkStatsLocked(String[] ifaces) {
        try {
            if (!ArrayUtils.isEmpty(ifaces)) {
                INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
@@ -11922,7 +11923,7 @@ public class BatteryStatsImpl extends BatteryStats {
    /**
     * Distribute Cell radio energy info and network traffic to apps.
     */
    public void updateMobileRadioState(@Nullable final ModemActivityInfo activityInfo,
    public void noteModemControllerActivity(@Nullable final ModemActivityInfo activityInfo,
            long elapsedRealtimeMs, long uptimeMs) {
        if (DEBUG_ENERGY) {
            Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
+161 −85
Original line number Diff line number Diff line
@@ -15,7 +15,12 @@
 */
package com.android.internal.os;

import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
import android.os.SystemBatteryConsumer;
import android.os.UidBatteryConsumer;
import android.os.UserHandle;
import android.telephony.CellSignalStrength;
import android.util.Log;
@@ -26,103 +31,146 @@ import java.util.List;
public class MobileRadioPowerCalculator extends PowerCalculator {
    private static final String TAG = "MobRadioPowerCalculator";
    private static final boolean DEBUG = BatteryStatsHelper.DEBUG;
    private final double mPowerRadioOn;
    private final double[] mPowerBins = new double[CellSignalStrength.getNumSignalStrengthLevels()];
    private final double mPowerScan;
    private BatteryStats mStats;
    private long mTotalAppMobileActiveMs = 0;

    /**
     * Return estimated power (in mAs) of sending or receiving a packet with the mobile radio.
     */
    private double getMobilePowerPerPacket(long rawRealtimeUs, int statsType) {
        final long MOBILE_BPS = 200000; // TODO: Extract average bit rates from system
        final double MOBILE_POWER = mPowerRadioOn / 3600;
    private static final int NUM_SIGNAL_STRENGTH_LEVELS =
            CellSignalStrength.getNumSignalStrengthLevels();

        final long mobileRx = mStats.getNetworkActivityPackets(BatteryStats.NETWORK_MOBILE_RX_DATA,
                statsType);
        final long mobileTx = mStats.getNetworkActivityPackets(BatteryStats.NETWORK_MOBILE_TX_DATA,
                statsType);
        final long mobileData = mobileRx + mobileTx;
    private final UsageBasedPowerEstimator mActivePowerEstimator;
    private final UsageBasedPowerEstimator[] mIdlePowerEstimators =
            new UsageBasedPowerEstimator[NUM_SIGNAL_STRENGTH_LEVELS];
    private final UsageBasedPowerEstimator mScanPowerEstimator;

        final long radioDataUptimeMs =
                mStats.getMobileRadioActiveTime(rawRealtimeUs, statsType) / 1000;
        final double mobilePps = (mobileData != 0 && radioDataUptimeMs != 0)
                ? (mobileData / (double) radioDataUptimeMs)
                : (((double) MOBILE_BPS) / 8 / 2048);
        return (MOBILE_POWER / mobilePps) / (60 * 60);
    private static class PowerAndDuration {
        public long durationMs;
        public double powerMah;
        public long totalAppDurationMs;
        public long signalDurationMs;
        public long noCoverageDurationMs;
    }

    public MobileRadioPowerCalculator(PowerProfile profile) {
        double temp =
        // Power consumption when radio is active
        double powerRadioActiveMa =
                profile.getAveragePowerOrDefault(PowerProfile.POWER_RADIO_ACTIVE, -1);
        if (temp != -1) {
            mPowerRadioOn = temp;
        } else {
        if (powerRadioActiveMa == -1) {
            double sum = 0;
            sum += profile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
            for (int i = 0; i < mPowerBins.length; i++) {
            for (int i = 0; i < NUM_SIGNAL_STRENGTH_LEVELS; i++) {
                sum += profile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
            }
            mPowerRadioOn = sum / (mPowerBins.length + 1);
            powerRadioActiveMa = sum / (NUM_SIGNAL_STRENGTH_LEVELS + 1);
        }

        temp = profile.getAveragePowerOrDefault(PowerProfile.POWER_RADIO_ON, -1);
        if (temp != -1) {
            for (int i = 0; i < mPowerBins.length; i++) {
                mPowerBins[i] = profile.getAveragePower(PowerProfile.POWER_RADIO_ON, i);
        mActivePowerEstimator = new UsageBasedPowerEstimator(powerRadioActiveMa);

        // Power consumption when radio is on, but idle
        if (profile.getAveragePowerOrDefault(PowerProfile.POWER_RADIO_ON, -1) != -1) {
            for (int i = 0; i < NUM_SIGNAL_STRENGTH_LEVELS; i++) {
                mIdlePowerEstimators[i] = new UsageBasedPowerEstimator(
                        profile.getAveragePower(PowerProfile.POWER_RADIO_ON, i));
            }
        } else {
            double idle = profile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE);
            mPowerBins[0] = idle * 25 / 180;
            for (int i = 1; i < mPowerBins.length; i++) {
                mPowerBins[i] = Math.max(1, idle / 256);

            // Magical calculations preserved for historical compatibility
            mIdlePowerEstimators[0] = new UsageBasedPowerEstimator(idle * 25 / 180);
            for (int i = 1; i < NUM_SIGNAL_STRENGTH_LEVELS; i++) {
                mIdlePowerEstimators[i] = new UsageBasedPowerEstimator(Math.max(1, idle / 256));
            }
        }

        mScanPowerEstimator = new UsageBasedPowerEstimator(
                profile.getAveragePowerOrDefault(PowerProfile.POWER_RADIO_SCANNING, 0));
    }

    @Override
    public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
            long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
            SparseArray<UserHandle> asUsers) {

        PowerAndDuration total = new PowerAndDuration();

        final double powerPerPacketMah = getMobilePowerPerPacket(batteryStats, rawRealtimeUs,
                BatteryStats.STATS_SINCE_CHARGED);
        final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =
                builder.getUidBatteryConsumerBuilders();
        for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
            final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
            final BatteryStats.Uid uid = app.getBatteryStatsUid();
            calculateApp(app, uid, powerPerPacketMah, total);
        }

        calculateRemaining(total, batteryStats, rawRealtimeUs);

        if (total.powerMah != 0) {
            builder.getOrCreateSystemBatteryConsumerBuilder(
                    SystemBatteryConsumer.DRAIN_TYPE_MOBILE_RADIO)
                    .setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_MOBILE_RADIO,
                            total.durationMs)
                    .setConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO, total.powerMah);
        }
    }

    private void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
            double powerPerPacketMah, PowerAndDuration total) {
        final long radioActiveDurationMs = calculateDuration(u, BatteryStats.STATS_SINCE_CHARGED);
        total.totalAppDurationMs += radioActiveDurationMs;

        final double powerMah = calculatePower(u, powerPerPacketMah, radioActiveDurationMs);

        mPowerScan = profile.getAveragePowerOrDefault(PowerProfile.POWER_RADIO_SCANNING, 0);
        app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_MOBILE_RADIO,
                radioActiveDurationMs)
                .setConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO, powerMah);
    }

    @Override
    public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
            long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
        mStats = batteryStats;
        super.calculate(sippers, batteryStats, rawRealtimeUs, rawUptimeUs, statsType, asUsers);
        final double mobilePowerPerPacket = getMobilePowerPerPacket(batteryStats, rawRealtimeUs,
                statsType);
        PowerAndDuration total = new PowerAndDuration();
        for (int i = sippers.size() - 1; i >= 0; i--) {
            final BatterySipper app = sippers.get(i);
            if (app.drainType == BatterySipper.DrainType.APP) {
                final BatteryStats.Uid u = app.uidObj;
                calculateApp(app, u, statsType, mobilePowerPerPacket, total);
            }
        }

        BatterySipper radio = new BatterySipper(BatterySipper.DrainType.CELL, null, 0);
        calculateRemaining(radio, mStats, rawRealtimeUs, rawUptimeUs, statsType);
        calculateRemaining(total, batteryStats, rawRealtimeUs);
        if (total.powerMah != 0) {
            if (total.signalDurationMs != 0) {
                radio.noCoveragePercent =
                        total.noCoverageDurationMs * 100.0 / total.signalDurationMs;
            }
            radio.mobileActive = total.durationMs;
            radio.mobileActiveCount = batteryStats.getMobileRadioActiveUnknownCount(statsType);
            radio.mobileRadioPowerMah = total.powerMah;
            radio.sumPower();
        }
        if (radio.totalPowerMah > 0) {
            sippers.add(radio);
        }
    }

    @Override
    protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
            long rawUptimeUs, int statsType) {
    private void calculateApp(BatterySipper app, BatteryStats.Uid u, int statsType,
            double powerPerPacketMah, PowerAndDuration total) {
        app.mobileActive = calculateDuration(u, statsType);
        app.mobileRadioPowerMah = calculatePower(u, powerPerPacketMah, app.mobileActive);
        total.totalAppDurationMs += app.mobileActive;

        // Add cost of mobile traffic.
        app.mobileRxPackets = u.getNetworkActivityPackets(BatteryStats.NETWORK_MOBILE_RX_DATA,
                statsType);
        app.mobileTxPackets = u.getNetworkActivityPackets(BatteryStats.NETWORK_MOBILE_TX_DATA,
                statsType);
        app.mobileActive = u.getMobileRadioActiveTime(statsType) / 1000;
        app.mobileActiveCount = u.getMobileRadioActiveCount(statsType);
        app.mobileRxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_MOBILE_RX_DATA,
                statsType);
        app.mobileTxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_MOBILE_TX_DATA,
                statsType);

        if (app.mobileActive > 0) {
            // We are tracking when the radio is up, so can use the active time to
            // determine power use.
            mTotalAppMobileActiveMs += app.mobileActive;
            app.mobileRadioPowerMah = (app.mobileActive * mPowerRadioOn) / (1000 * 60 * 60);
        } else {
            // We are not tracking when the radio is up, so must approximate power use
            // based on the number of packets.
            app.mobileRadioPowerMah = (app.mobileRxPackets + app.mobileTxPackets)
                    * getMobilePowerPerPacket(rawRealtimeUs, statsType);
        }
        if (DEBUG && app.mobileRadioPowerMah != 0) {
            Log.d(TAG, "UID " + u.getUid() + ": mobile packets "
                    + (app.mobileRxPackets + app.mobileTxPackets)
@@ -131,52 +179,80 @@ public class MobileRadioPowerCalculator extends PowerCalculator {
        }
    }

    private void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs,
            long rawUptimeUs, int statsType) {
        double power = 0;
    private long calculateDuration(BatteryStats.Uid u, int statsType) {
        return u.getMobileRadioActiveTime(statsType) / 1000;
    }

    private double calculatePower(BatteryStats.Uid u, double powerPerPacketMah,
            long radioActiveDurationMs) {
        if (radioActiveDurationMs > 0) {
            // We are tracking when the radio is up, so can use the active time to
            // determine power use.
            return mActivePowerEstimator.calculatePower(radioActiveDurationMs);
        } else {
            // We are not tracking when the radio is up, so must approximate power use
            // based on the number of packets.
            final long mobileRxPackets = u.getNetworkActivityPackets(
                    BatteryStats.NETWORK_MOBILE_RX_DATA,
                    BatteryStats.STATS_SINCE_CHARGED);
            final long mobileTxPackets = u.getNetworkActivityPackets(
                    BatteryStats.NETWORK_MOBILE_TX_DATA,
                    BatteryStats.STATS_SINCE_CHARGED);
            return (mobileRxPackets + mobileTxPackets) * powerPerPacketMah;
        }
    }

    private void calculateRemaining(MobileRadioPowerCalculator.PowerAndDuration total,
            BatteryStats batteryStats, long rawRealtimeUs) {
        long signalTimeMs = 0;
        long noCoverageTimeMs = 0;
        for (int i = 0; i < mPowerBins.length; i++) {
            long strengthTimeMs = stats.getPhoneSignalStrengthTime(i, rawRealtimeUs, statsType)
                    / 1000;
            final double p = (strengthTimeMs * mPowerBins[i]) / (60 * 60 * 1000);
        double powerMah = 0;
        for (int i = 0; i < NUM_SIGNAL_STRENGTH_LEVELS; i++) {
            long strengthTimeMs = batteryStats.getPhoneSignalStrengthTime(i, rawRealtimeUs,
                    BatteryStats.STATS_SINCE_CHARGED) / 1000;
            final double p = mIdlePowerEstimators[i].calculatePower(strengthTimeMs);
            if (DEBUG && p != 0) {
                Log.d(TAG, "Cell strength #" + i + ": time=" + strengthTimeMs + " power="
                        + formatCharge(p));
            }
            power += p;
            powerMah += p;
            signalTimeMs += strengthTimeMs;
            if (i == 0) {
                noCoverageTimeMs = strengthTimeMs;
                total.noCoverageDurationMs = strengthTimeMs;
            }
        }

        final long scanningTimeMs = stats.getPhoneSignalScanningTime(rawRealtimeUs, statsType)
                / 1000;
        final double p = (scanningTimeMs * mPowerScan) / (60 * 60 * 1000);
        final long scanningTimeMs = batteryStats.getPhoneSignalScanningTime(rawRealtimeUs,
                BatteryStats.STATS_SINCE_CHARGED) / 1000;
        final double p = mScanPowerEstimator.calculatePower(scanningTimeMs);
        if (DEBUG && p != 0) {
            Log.d(TAG, "Cell radio scanning: time=" + scanningTimeMs + " power=" + formatCharge(p));
        }
        power += p;
        long radioActiveTimeMs = mStats.getMobileRadioActiveTime(rawRealtimeUs, statsType) / 1000;
        long remainingActiveTimeMs = radioActiveTimeMs - mTotalAppMobileActiveMs;
        powerMah += p;
        long radioActiveTimeMs = batteryStats.getMobileRadioActiveTime(rawRealtimeUs,
                BatteryStats.STATS_SINCE_CHARGED) / 1000;
        long remainingActiveTimeMs = radioActiveTimeMs - total.totalAppDurationMs;
        if (remainingActiveTimeMs > 0) {
            power += (mPowerRadioOn * remainingActiveTimeMs) / (1000 * 60 * 60);
        }

        if (power != 0) {
            if (signalTimeMs != 0) {
                app.noCoveragePercent = noCoverageTimeMs * 100.0 / signalTimeMs;
            }
            app.mobileActive = remainingActiveTimeMs;
            app.mobileActiveCount = stats.getMobileRadioActiveUnknownCount(statsType);
            app.mobileRadioPowerMah = power;
            powerMah += mActivePowerEstimator.calculatePower(remainingActiveTimeMs);
        }
        total.durationMs = radioActiveTimeMs;
        total.powerMah = powerMah;
        total.signalDurationMs = signalTimeMs;
    }

    @Override
    public void reset() {
        mTotalAppMobileActiveMs = 0;
        mStats = null;
    /**
     * Return estimated power (in mAh) of sending or receiving a packet with the mobile radio.
     */
    private double getMobilePowerPerPacket(BatteryStats stats, long rawRealtimeUs, int statsType) {
        final long radioDataUptimeMs =
                stats.getMobileRadioActiveTime(rawRealtimeUs, statsType) / 1000;
        final double mobilePower = mActivePowerEstimator.calculatePower(radioDataUptimeMs);

        final long mobileRx = stats.getNetworkActivityPackets(BatteryStats.NETWORK_MOBILE_RX_DATA,
                statsType);
        final long mobileTx = stats.getNetworkActivityPackets(BatteryStats.NETWORK_MOBILE_TX_DATA,
                statsType);
        final long mobilePackets = mobileRx + mobileTx;

        return mobilePackets != 0 ? mobilePower / mobilePackets : 0;
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ import org.junit.runners.Suite;
        KernelWakelockReaderTest.class,
        LongSamplingCounterTest.class,
        LongSamplingCounterArrayTest.class,
        MobileRadioPowerCalculatorTest.class,
        PowerCalculatorTest.class,
        PowerProfileTest.class,
        ScreenPowerCalculatorTest.class,
Loading