Merge "Power profile audio & video support" into pi-dev

This commit is contained in:
TreeHugger Robot
2018-03-06 07:44:28 +00:00
committed by Android (Google) Code Review
9 changed files with 190 additions and 30 deletions

View File

@@ -73,14 +73,16 @@ public class BatterySipper implements Comparable<BatterySipper> {
public double usagePowerMah;
// Subsystem usage times.
public long cpuTimeMs;
public long gpsTimeMs;
public long wifiRunningTimeMs;
public long cpuFgTimeMs;
public long wakeLockTimeMs;
public long cameraTimeMs;
public long flashlightTimeMs;
public long audioTimeMs;
public long bluetoothRunningTimeMs;
public long cameraTimeMs;
public long cpuFgTimeMs;
public long cpuTimeMs;
public long flashlightTimeMs;
public long gpsTimeMs;
public long videoTimeMs;
public long wakeLockTimeMs;
public long wifiRunningTimeMs;
public long mobileRxPackets;
public long mobileTxPackets;
@@ -102,15 +104,17 @@ public class BatterySipper implements Comparable<BatterySipper> {
// Measured in mAh (milli-ampere per hour).
// These are included when summed.
public double wifiPowerMah;
public double cpuPowerMah;
public double wakeLockPowerMah;
public double mobileRadioPowerMah;
public double gpsPowerMah;
public double sensorPowerMah;
public double cameraPowerMah;
public double flashlightPowerMah;
public double audioPowerMah;
public double bluetoothPowerMah;
public double cameraPowerMah;
public double cpuPowerMah;
public double flashlightPowerMah;
public double gpsPowerMah;
public double mobileRadioPowerMah;
public double sensorPowerMah;
public double videoPowerMah;
public double wakeLockPowerMah;
public double wifiPowerMah;
public enum DrainType {
AMBIENT_DISPLAY,
@@ -177,10 +181,12 @@ public class BatterySipper implements Comparable<BatterySipper> {
totalPowerMah += other.totalPowerMah;
usageTimeMs += other.usageTimeMs;
usagePowerMah += other.usagePowerMah;
audioTimeMs += other.audioTimeMs;
cpuTimeMs += other.cpuTimeMs;
gpsTimeMs += other.gpsTimeMs;
wifiRunningTimeMs += other.wifiRunningTimeMs;
cpuFgTimeMs += other.cpuFgTimeMs;
videoTimeMs += other.videoTimeMs;
wakeLockTimeMs += other.wakeLockTimeMs;
cameraTimeMs += other.cameraTimeMs;
flashlightTimeMs += other.flashlightTimeMs;
@@ -197,6 +203,7 @@ public class BatterySipper implements Comparable<BatterySipper> {
wifiTxBytes += other.wifiTxBytes;
btRxBytes += other.btRxBytes;
btTxBytes += other.btTxBytes;
audioPowerMah += other.audioPowerMah;
wifiPowerMah += other.wifiPowerMah;
gpsPowerMah += other.gpsPowerMah;
cpuPowerMah += other.cpuPowerMah;
@@ -207,6 +214,7 @@ public class BatterySipper implements Comparable<BatterySipper> {
flashlightPowerMah += other.flashlightPowerMah;
bluetoothPowerMah += other.bluetoothPowerMah;
screenPowerMah += other.screenPowerMah;
videoPowerMah += other.videoPowerMah;
proportionalSmearMah += other.proportionalSmearMah;
totalSmearedPowerMah += other.totalSmearedPowerMah;
}
@@ -220,7 +228,7 @@ public class BatterySipper implements Comparable<BatterySipper> {
public double sumPower() {
totalPowerMah = usagePowerMah + wifiPowerMah + gpsPowerMah + cpuPowerMah +
sensorPowerMah + mobileRadioPowerMah + wakeLockPowerMah + cameraPowerMah +
flashlightPowerMah + bluetoothPowerMah;
flashlightPowerMah + bluetoothPowerMah + audioPowerMah + videoPowerMah;
totalSmearedPowerMah = totalPowerMah + screenPowerMah + proportionalSmearMah;
return totalPowerMah;

View File

@@ -136,6 +136,7 @@ public class BatteryStatsHelper {
PowerCalculator mCameraPowerCalculator;
PowerCalculator mFlashlightPowerCalculator;
PowerCalculator mMemoryPowerCalculator;
PowerCalculator mMediaPowerCalculator;
boolean mHasWifiPowerReporting = false;
boolean mHasBluetoothPowerReporting = false;
@@ -424,6 +425,11 @@ public class BatteryStatsHelper {
}
mFlashlightPowerCalculator.reset();
if (mMediaPowerCalculator == null) {
mMediaPowerCalculator = new MediaPowerCalculator(mPowerProfile);
}
mMediaPowerCalculator.reset();
mStatsType = statsType;
mRawUptimeUs = rawUptimeUs;
mRawRealtimeUs = rawRealtimeUs;
@@ -560,6 +566,7 @@ public class BatteryStatsHelper {
mCameraPowerCalculator.calculateApp(app, u, mRawRealtimeUs, mRawUptimeUs, mStatsType);
mFlashlightPowerCalculator.calculateApp(app, u, mRawRealtimeUs, mRawUptimeUs,
mStatsType);
mMediaPowerCalculator.calculateApp(app, u, mRawRealtimeUs, mRawUptimeUs, mStatsType);
final double totalPower = app.sumPower();
if (DEBUG && totalPower != 0) {

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.internal.os;
import android.os.BatteryStats;
/**
* A {@link PowerCalculator} to calculate power consumed by audio and video hardware.
*
* Also see {@link PowerProfile#POWER_AUDIO} and {@link PowerProfile#POWER_VIDEO}.
*/
public class MediaPowerCalculator extends PowerCalculator {
private static final int MS_IN_HR = 1000 * 60 * 60;
private final double mAudioAveragePowerMa;
private final double mVideoAveragePowerMa;
public MediaPowerCalculator(PowerProfile profile) {
mAudioAveragePowerMa = profile.getAveragePower(PowerProfile.POWER_AUDIO);
mVideoAveragePowerMa = profile.getAveragePower(PowerProfile.POWER_VIDEO);
}
@Override
public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
long rawUptimeUs, int statsType) {
// Calculate audio power usage, an estimate based on the average power routed to different
// components like speaker, bluetooth, usb-c, earphone, etc.
final BatteryStats.Timer audioTimer = u.getAudioTurnedOnTimer();
if (audioTimer == null) {
app.audioTimeMs = 0;
app.audioPowerMah = 0;
} else {
final long totalTime = audioTimer.getTotalTimeLocked(rawRealtimeUs, statsType) / 1000;
app.audioTimeMs = totalTime;
app.audioPowerMah = (totalTime * mAudioAveragePowerMa) / MS_IN_HR;
}
// Calculate video power usage.
final BatteryStats.Timer videoTimer = u.getVideoTurnedOnTimer();
if (videoTimer == null) {
app.videoTimeMs = 0;
app.videoPowerMah = 0;
} else {
final long totalTime = videoTimer.getTotalTimeLocked(rawRealtimeUs, statsType) / 1000;
app.videoTimeMs = totalTime;
app.videoPowerMah = (totalTime * mVideoAveragePowerMa) / MS_IN_HR;
}
}
}

View File

@@ -43,12 +43,12 @@ public class PowerProfile {
*/
public static final String POWER_NONE = "none";
/**
/*
* POWER_CPU_SUSPEND: Power consumption when CPU is in power collapse mode.
* POWER_CPU_IDLE: Power consumption when CPU is awake (when a wake lock is held). This should
* be zero on devices that can go into full CPU power collapse even when a wake
* lock is held. Otherwise, this is the power consumption in addition to
* POWER_CPU_SUSPEND due to a wake lock being held but with no CPU activity.
* POWER_CPU_SUSPEND due to a wake lock being held but with no CPU activity.
* POWER_CPU_ACTIVE: Power consumption when CPU is running, excluding power consumed by clusters
* and cores.
*
@@ -84,7 +84,6 @@ public class PowerProfile {
// Updated power constants. These are not estimated, they are real world
// currents and voltages for the underlying bluetooth and wifi controllers.
//
public static final String POWER_WIFI_CONTROLLER_IDLE = "wifi.controller.idle";
public static final String POWER_WIFI_CONTROLLER_RX = "wifi.controller.rx";
public static final String POWER_WIFI_CONTROLLER_TX = "wifi.controller.tx";
@@ -117,6 +116,7 @@ public class PowerProfile {
/**
* Power consumption when Bluetooth driver is on.
*
* @deprecated
*/
@Deprecated
@@ -124,6 +124,7 @@ public class PowerProfile {
/**
* Power consumption when Bluetooth driver is transmitting/receiving.
*
* @deprecated
*/
@Deprecated
@@ -131,6 +132,7 @@ public class PowerProfile {
/**
* Power consumption when Bluetooth driver gets an AT command.
*
* @deprecated
*/
@Deprecated
@@ -171,13 +173,13 @@ public class PowerProfile {
* Power consumed by the audio hardware when playing back audio content. This is in addition
* to the CPU power, probably due to a DSP and / or amplifier.
*/
public static final String POWER_AUDIO = "dsp.audio";
public static final String POWER_AUDIO = "audio";
/**
* Power consumed by any media hardware when playing back video content. This is in addition
* to the CPU power, probably due to a DSP.
*/
public static final String POWER_VIDEO = "dsp.video";
public static final String POWER_VIDEO = "video";
/**
* Average power consumption when camera flashlight is on.
@@ -409,6 +411,7 @@ public class PowerProfile {
/**
* Returns the number of memory bandwidth buckets defined in power_profile.xml, or a
* default value if the subsystem has no recorded value.
*
* @return the number of memory bandwidth buckets.
*/
public int getNumElements(String key) {
@@ -423,7 +426,8 @@ public class PowerProfile {
/**
* Returns the average current in mA consumed by the subsystem, or the given
* default value if the subsystem has no recorded value.
* @param type the subsystem type
*
* @param type the subsystem type
* @param defaultValue the value to return if the subsystem has no recorded value.
* @return the average current in milliAmps.
*/
@@ -439,19 +443,21 @@ public class PowerProfile {
/**
* Returns the average current in mA consumed by the subsystem
*
* @param type the subsystem type
* @return the average current in milliAmps.
*/
public double getAveragePower(String type) {
return getAveragePowerOrDefault(type, 0);
}
/**
* Returns the average current in mA consumed by the subsystem for the given level.
* @param type the subsystem type
*
* @param type the subsystem type
* @param level the level of power at which the subsystem is running. For instance, the
* signal strength of the cell network between 0 and 4 (if there are 4 bars max.)
* If there is no data for multiple levels, the level is ignored.
* signal strength of the cell network between 0 and 4 (if there are 4 bars max.)
* If there is no data for multiple levels, the level is ignored.
* @return the average current in milliAmps.
*/
public double getAveragePower(String type, int level) {
@@ -474,6 +480,7 @@ public class PowerProfile {
/**
* Returns the battery capacity, if available, in milli Amp Hours. If not available,
* it returns zero.
*
* @return the battery capacity in mAh
*/
public double getBatteryCapacity() {

View File

@@ -36,8 +36,8 @@
<item name="wifi.on">0.1</item> <!-- ~3mA -->
<item name="wifi.active">0.1</item> <!-- WIFI data transfer, ~200mA -->
<item name="wifi.scan">0.1</item> <!-- WIFI network scanning, ~100mA -->
<item name="dsp.audio">0.1</item> <!-- ~10mA -->
<item name="dsp.video">0.1</item> <!-- ~50mA -->
<item name="audio">0.1</item> <!-- ~10mA -->
<item name="video">0.1</item> <!-- ~50mA -->
<item name="camera.flashlight">0.1</item> <!-- Avg. power for camera flash, ~160mA -->
<item name="camera.avg">0.1</item> <!-- Avg. power use of camera in standard usecases, ~550mA -->
<item name="gps.on">0.1</item> <!-- ~50mA -->

View File

@@ -96,8 +96,11 @@
minute. -->
<item name="camera.avg">600</item>
<!-- Additional power used when audio decoding/encoding via DSP -->
<item name="dsp.audio">100</item>
<!-- Additional power used by the audio hardware, probably due to DSP -->
<item name="audio">100.0</item>
<!-- Additional power used by the video hardware, probably due to DSP -->
<item name="video">150.0</item> <!-- ~50mA -->
<!-- Additional power used when GPS is acquiring a signal -->
<item name="gps.on">10</item>

View File

@@ -44,6 +44,7 @@ import org.junit.runners.Suite;
KernelUidCpuClusterTimeReaderTest.class,
KernelWakelockReaderTest.class,
LongSamplingCounterArrayTest.class,
PowerCalculatorTest.class,
PowerProfileTest.class
})
public class BatteryStatsTests {

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2018 The Android Open Source Project
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
*/
package com.android.internal.os;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.os.BatteryStats;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import junit.framework.TestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class PowerCalculatorTest extends TestCase {
private static final long US_IN_HR = 1000L * 1000L * 60L * 60L;
@Mock
private PowerProfile mPowerProfile;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
/** Test {@link MediaPowerCalculator#calculateApp} */
@Test
public void testMediaPowerCalculator() {
when(mPowerProfile.getAveragePower(PowerProfile.POWER_AUDIO)).thenReturn(12.0);
when(mPowerProfile.getAveragePower(PowerProfile.POWER_VIDEO)).thenReturn(25.0);
BatteryStats.Uid u = mock(BatteryStats.Uid.class);
BatteryStats.Timer audioTimer = mock(BatteryStats.Timer.class);
when(u.getAudioTurnedOnTimer()).thenReturn(audioTimer);
when(audioTimer.getTotalTimeLocked(2L * US_IN_HR, 0)).thenReturn(2L * US_IN_HR);
BatteryStats.Timer videoTimer = mock(BatteryStats.Timer.class);
when(u.getVideoTurnedOnTimer()).thenReturn(videoTimer);
when(videoTimer.getTotalTimeLocked(2L * US_IN_HR, 0)).thenReturn(1L * US_IN_HR);
MediaPowerCalculator mediaPowerCalculator = new MediaPowerCalculator(mPowerProfile);
BatterySipper app = new BatterySipper(BatterySipper.DrainType.APP, null, 0);
mediaPowerCalculator.calculateApp(app, u, 2L * US_IN_HR, 2L * US_IN_HR, 0);
assertEquals(49.0, app.sumPower());
}
}

View File

@@ -54,6 +54,8 @@ public class PowerProfileTest extends TestCase {
assertEquals(60.0, mProfile.getAveragePowerForCpuCore(1, 3));
assertEquals(3000.0, mProfile.getBatteryCapacity());
assertEquals(0.5, mProfile.getAveragePower(PowerProfile.POWER_AMBIENT_DISPLAY));
assertEquals(100.0, mProfile.getAveragePower(PowerProfile.POWER_AUDIO));
assertEquals(150.0, mProfile.getAveragePower(PowerProfile.POWER_VIDEO));
}
}