Merge "Statsd atom: Power Use"
This commit is contained in:
@@ -192,6 +192,9 @@ message Atom {
|
||||
NativeProcessMemoryState native_process_memory_state = 10036;
|
||||
CpuTimePerThreadFreq cpu_time_per_thread_freq = 10037;
|
||||
OnDevicePowerMeasurement on_device_power_measurement = 10038;
|
||||
DeviceCalculatedPowerUse device_calculated_power_use = 10039;
|
||||
DeviceCalculatedPowerBlameUid device_calculated_power_blame_uid = 10040;
|
||||
DeviceCalculatedPowerBlameOther device_calculated_power_blame_other = 10041;
|
||||
}
|
||||
|
||||
// DO NOT USE field numbers above 100,000 in AOSP.
|
||||
@@ -3198,3 +3201,63 @@ message CpuTimePerThreadFreq {
|
||||
// Time spent in frequency in milliseconds, since thread start.
|
||||
optional uint32 time_millis = 7;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pulls on-device BatteryStats power use calculations for the overall device.
|
||||
*/
|
||||
message DeviceCalculatedPowerUse {
|
||||
// Power used by the device in mAh, as computed by BatteryStats, since BatteryStats last reset
|
||||
// (i.e. roughly since device was last significantly charged).
|
||||
// Currently, this is BatteryStatsHelper.getComputedPower() (not getTotalPower()).
|
||||
optional float computed_power_milli_amp_hours = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pulls on-device BatteryStats power use calculations broken down by uid.
|
||||
* This atom should be complemented by DeviceCalculatedPowerBlameOther, which contains the power use
|
||||
* that is attributed to non-uid items. They must all be included to get the total power use.
|
||||
*/
|
||||
message DeviceCalculatedPowerBlameUid {
|
||||
// Uid being blamed. Note: isolated uids have already been mapped to host uid.
|
||||
optional int32 uid = 1 [(is_uid) = true];
|
||||
|
||||
// Power used by this uid in mAh, as computed by BatteryStats, since BatteryStats last reset
|
||||
// (i.e. roughly since device was last significantly charged).
|
||||
optional float power_milli_amp_hours = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pulls on-device BatteryStats power use calculations that are not due to a uid, broken down by
|
||||
* drain type.
|
||||
* This atom should be complemented by DeviceCalculatedPowerBlameUid, which contains the blame that
|
||||
* is attributed uids. They must all be included to get the total power use.
|
||||
*/
|
||||
message DeviceCalculatedPowerBlameOther {
|
||||
// The type of item whose power use is being reported.
|
||||
enum DrainType {
|
||||
AMBIENT_DISPLAY = 0;
|
||||
// reserved 1; reserved "APP"; // Logged instead in DeviceCalculatedPowerBlameUid.
|
||||
BLUETOOTH = 2;
|
||||
CAMERA = 3;
|
||||
// Cell-standby
|
||||
CELL = 4;
|
||||
FLASHLIGHT = 5;
|
||||
IDLE = 6;
|
||||
MEMORY = 7;
|
||||
// Amount that total computed drain exceeded the drain estimated using the
|
||||
// battery level changes and capacity.
|
||||
OVERCOUNTED = 8;
|
||||
PHONE = 9;
|
||||
SCREEN = 10;
|
||||
// Amount that total computed drain was below the drain estimated using the
|
||||
// battery level changes and capacity.
|
||||
UNACCOUNTED = 11;
|
||||
// reserved 12; reserved "USER"; // Entire drain for a user. This is NOT supported.
|
||||
WIFI = 13;
|
||||
}
|
||||
optional DrainType drain_type = 1;
|
||||
|
||||
// Power used by this item in mAh, as computed by BatteryStats, since BatteryStats last reset
|
||||
// (i.e. roughly since device was last significantly charged).
|
||||
optional float power_milli_amp_hours = 2;
|
||||
}
|
||||
14
cmds/statsd/src/external/StatsPullerManager.cpp
vendored
14
cmds/statsd/src/external/StatsPullerManager.cpp
vendored
@@ -243,6 +243,20 @@ const std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
|
||||
{2, 3, 4, 5, 6},
|
||||
1 * NS_PER_SEC,
|
||||
new StatsCompanionServicePuller(android::util::CPU_TIME_PER_THREAD_FREQ)}},
|
||||
// DeviceCalculatedPowerUse.
|
||||
{android::util::DEVICE_CALCULATED_POWER_USE,
|
||||
{{}, {}, 1 * NS_PER_SEC,
|
||||
new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_USE)}},
|
||||
// DeviceCalculatedPowerBlameUid.
|
||||
{android::util::DEVICE_CALCULATED_POWER_BLAME_UID,
|
||||
{{}, {}, // BatteryStats already merged isolated with host ids so it's unnecessary here.
|
||||
1 * NS_PER_SEC,
|
||||
new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_BLAME_UID)}},
|
||||
// DeviceCalculatedPowerBlameOther.
|
||||
{android::util::DEVICE_CALCULATED_POWER_BLAME_OTHER,
|
||||
{{}, {},
|
||||
1 * NS_PER_SEC,
|
||||
new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_BLAME_OTHER)}},
|
||||
};
|
||||
|
||||
StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
|
||||
|
||||
@@ -103,14 +103,6 @@ public final class StatsLogEventWrapper implements Parcelable {
|
||||
mValues.add(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a double value.
|
||||
*/
|
||||
public void writeDouble(double val) {
|
||||
mTypes.add(EVENT_TYPE_DOUBLE);
|
||||
mValues.add(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a storage value.
|
||||
*/
|
||||
|
||||
@@ -130,6 +130,10 @@ public class BatterySipper implements Comparable<BatterySipper> {
|
||||
public double wakeLockPowerMah;
|
||||
public double wifiPowerMah;
|
||||
|
||||
// ****************
|
||||
// This list must be kept current with atoms.proto (frameworks/base/cmds/statsd/src/atoms.proto)
|
||||
// so the ordinal values (and therefore the order) must never change.
|
||||
// ****************
|
||||
public enum DrainType {
|
||||
AMBIENT_DISPLAY,
|
||||
@UnsupportedAppUsage
|
||||
|
||||
@@ -41,6 +41,7 @@ import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.filters.SmallTest;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.StatsLog;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
@@ -258,6 +259,36 @@ public class BatteryStatsHelperTest extends TestCase {
|
||||
assertThat(time).isEqualTo(TIME_STATE_FOREGROUND_MS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDrainTypesSyncedWithProto() {
|
||||
assertEquals(BatterySipper.DrainType.AMBIENT_DISPLAY.ordinal(),
|
||||
StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__AMBIENT_DISPLAY);
|
||||
// AtomsProto has no "APP"
|
||||
assertEquals(BatterySipper.DrainType.BLUETOOTH.ordinal(),
|
||||
StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__BLUETOOTH);
|
||||
assertEquals(BatterySipper.DrainType.CAMERA.ordinal(),
|
||||
StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__CAMERA);
|
||||
assertEquals(BatterySipper.DrainType.CELL.ordinal(),
|
||||
StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__CELL);
|
||||
assertEquals(BatterySipper.DrainType.FLASHLIGHT.ordinal(),
|
||||
StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__FLASHLIGHT);
|
||||
assertEquals(BatterySipper.DrainType.IDLE.ordinal(),
|
||||
StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__IDLE);
|
||||
assertEquals(BatterySipper.DrainType.MEMORY.ordinal(),
|
||||
StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__MEMORY);
|
||||
assertEquals(BatterySipper.DrainType.OVERCOUNTED.ordinal(),
|
||||
StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__OVERCOUNTED);
|
||||
assertEquals(BatterySipper.DrainType.PHONE.ordinal(),
|
||||
StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__PHONE);
|
||||
assertEquals(BatterySipper.DrainType.SCREEN.ordinal(),
|
||||
StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__SCREEN);
|
||||
assertEquals(BatterySipper.DrainType.UNACCOUNTED.ordinal(),
|
||||
StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__UNACCOUNTED);
|
||||
// AtomsProto has no "USER"
|
||||
assertEquals(BatterySipper.DrainType.WIFI.ordinal(),
|
||||
StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__WIFI);
|
||||
}
|
||||
|
||||
private BatterySipper createTestSmearBatterySipper(long activityTime, double totalPowerMah,
|
||||
int uidCode, boolean isUidNull) {
|
||||
final BatterySipper sipper = mock(BatterySipper.class);
|
||||
|
||||
@@ -173,6 +173,7 @@
|
||||
<assign-permission name="android.permission.ACCESS_LOWPAN_STATE" uid="lowpan" />
|
||||
<assign-permission name="android.permission.MANAGE_LOWPAN_INTERFACES" uid="lowpan" />
|
||||
|
||||
<assign-permission name="android.permission.BATTERY_STATS" uid="statsd" />
|
||||
<assign-permission name="android.permission.DUMP" uid="statsd" />
|
||||
<assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="statsd" />
|
||||
<assign-permission name="android.permission.STATSCOMPANION" uid="statsd" />
|
||||
|
||||
@@ -85,9 +85,6 @@ status_t StatsLogEventWrapper::readFromParcel(const Parcel* in) {
|
||||
case StatsLogValue::FLOAT:
|
||||
mElements.push_back(StatsLogValue(in->readFloat()));
|
||||
break;
|
||||
case StatsLogValue::DOUBLE:
|
||||
mElements.push_back(StatsLogValue(in->readDouble()));
|
||||
break;
|
||||
case StatsLogValue::STORAGE:
|
||||
mElements.push_back(StatsLogValue());
|
||||
mElements.back().setType(StatsLogValue::STORAGE);
|
||||
|
||||
@@ -47,6 +47,7 @@ import android.net.NetworkRequest;
|
||||
import android.net.NetworkStats;
|
||||
import android.net.wifi.IWifiManager;
|
||||
import android.net.wifi.WifiActivityEnergyInfo;
|
||||
import android.os.BatteryStats;
|
||||
import android.os.BatteryStatsInternal;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
@@ -87,6 +88,8 @@ import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.app.procstats.IProcessStats;
|
||||
import com.android.internal.app.procstats.ProcessStats;
|
||||
import com.android.internal.net.NetworkStatsFactory;
|
||||
import com.android.internal.os.BatterySipper;
|
||||
import com.android.internal.os.BatteryStatsHelper;
|
||||
import com.android.internal.os.BinderCallsStats.ExportedCallStat;
|
||||
import com.android.internal.os.KernelCpuSpeedReader;
|
||||
import com.android.internal.os.KernelCpuThreadReader;
|
||||
@@ -205,6 +208,10 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
@Nullable
|
||||
private final KernelCpuThreadReader mKernelCpuThreadReader;
|
||||
|
||||
private BatteryStatsHelper mBatteryStatsHelper = null;
|
||||
private static final int MAX_BATTERY_STATS_HELPER_FREQUENCY_MS = 1000;
|
||||
private long mBatteryStatsHelperTimestampMs = -MAX_BATTERY_STATS_HELPER_FREQUENCY_MS;
|
||||
|
||||
private static IThermalService sThermalService;
|
||||
private File mBaseDir =
|
||||
new File(SystemServiceManager.ensureSystemDir(), "stats_companion");
|
||||
@@ -1449,6 +1456,73 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
pulledData.add(e);
|
||||
}
|
||||
|
||||
private BatteryStatsHelper getBatteryStatsHelper() {
|
||||
if (mBatteryStatsHelper == null) {
|
||||
final long callingToken = Binder.clearCallingIdentity();
|
||||
try {
|
||||
// clearCallingIdentity required for BatteryStatsHelper.checkWifiOnly().
|
||||
mBatteryStatsHelper = new BatteryStatsHelper(mContext, false);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(callingToken);
|
||||
}
|
||||
mBatteryStatsHelper.create((Bundle) null);
|
||||
}
|
||||
long currentTime = SystemClock.elapsedRealtime();
|
||||
if (currentTime - mBatteryStatsHelperTimestampMs >= MAX_BATTERY_STATS_HELPER_FREQUENCY_MS) {
|
||||
// Load BatteryStats and do all the calculations.
|
||||
mBatteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, UserHandle.USER_ALL);
|
||||
// Calculations are done so we don't need to save the raw BatteryStats data in RAM.
|
||||
mBatteryStatsHelper.clearStats();
|
||||
mBatteryStatsHelperTimestampMs = currentTime;
|
||||
}
|
||||
return mBatteryStatsHelper;
|
||||
}
|
||||
|
||||
private void pullDeviceCalculatedPowerUse(int tagId,
|
||||
long elapsedNanos, final long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
|
||||
BatteryStatsHelper bsHelper = getBatteryStatsHelper();
|
||||
StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
|
||||
e.writeFloat((float) bsHelper.getComputedPower());
|
||||
pulledData.add(e);
|
||||
}
|
||||
|
||||
private void pullDeviceCalculatedPowerBlameUid(int tagId,
|
||||
long elapsedNanos, final long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
|
||||
final List<BatterySipper> sippers = getBatteryStatsHelper().getUsageList();
|
||||
if (sippers == null) {
|
||||
return;
|
||||
}
|
||||
for (BatterySipper bs : sippers) {
|
||||
if (bs.drainType != bs.drainType.APP) {
|
||||
continue;
|
||||
}
|
||||
StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
|
||||
e.writeInt(bs.uidObj.getUid());
|
||||
e.writeFloat((float) bs.totalPowerMah);
|
||||
pulledData.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void pullDeviceCalculatedPowerBlameOther(int tagId,
|
||||
long elapsedNanos, final long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
|
||||
final List<BatterySipper> sippers = getBatteryStatsHelper().getUsageList();
|
||||
if (sippers == null) {
|
||||
return;
|
||||
}
|
||||
for (BatterySipper bs : sippers) {
|
||||
if (bs.drainType == bs.drainType.APP) {
|
||||
continue; // This is a separate atom; see pullDeviceCalculatedPowerBlameUid().
|
||||
}
|
||||
if (bs.drainType == bs.drainType.USER) {
|
||||
continue; // This is not supported. We purposefully calculate over USER_ALL.
|
||||
}
|
||||
StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
|
||||
e.writeInt(bs.drainType.ordinal());
|
||||
e.writeFloat((float) bs.totalPowerMah);
|
||||
pulledData.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void pullDiskIo(int tagId, long elapsedNanos, final long wallClockNanos,
|
||||
List<StatsLogEventWrapper> pulledData) {
|
||||
mStoragedUidIoStatsReader.readAbsolute((uid, fgCharsRead, fgCharsWrite, fgBytesRead,
|
||||
@@ -1674,6 +1748,18 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
pullCpuTimePerThreadFreq(tagId, elapsedNanos, wallClockNanos, ret);
|
||||
break;
|
||||
}
|
||||
case StatsLog.DEVICE_CALCULATED_POWER_USE: {
|
||||
pullDeviceCalculatedPowerUse(tagId, elapsedNanos, wallClockNanos, ret);
|
||||
break;
|
||||
}
|
||||
case StatsLog.DEVICE_CALCULATED_POWER_BLAME_UID: {
|
||||
pullDeviceCalculatedPowerBlameUid(tagId, elapsedNanos, wallClockNanos, ret);
|
||||
break;
|
||||
}
|
||||
case StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER: {
|
||||
pullDeviceCalculatedPowerBlameOther(tagId, elapsedNanos, wallClockNanos, ret);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Slog.w(TAG, "No such tagId data as " + tagId);
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user