Merge "Power profile audio & video support" into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
1ab03020db
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
61
core/java/com/android/internal/os/MediaPowerCalculator.java
Normal file
61
core/java/com/android/internal/os/MediaPowerCalculator.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -44,6 +44,7 @@ import org.junit.runners.Suite;
|
||||
KernelUidCpuClusterTimeReaderTest.class,
|
||||
KernelWakelockReaderTest.class,
|
||||
LongSamplingCounterArrayTest.class,
|
||||
PowerCalculatorTest.class,
|
||||
PowerProfileTest.class
|
||||
})
|
||||
public class BatteryStatsTests {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user