diff options
| author | 2016-07-27 23:24:54 +0000 | |
|---|---|---|
| committer | 2016-07-27 23:24:55 +0000 | |
| commit | d2a4944d68bd05f98856ea0f95cf36117bd5fd48 (patch) | |
| tree | 4f19b924783b1cfade7ab7721df1a0901e3721a6 | |
| parent | 3abdfedac49c2f9503afc5d10344196c18cfa89c (diff) | |
| parent | 2dd7e5e3ef0a20864a5908fd8c0896776575d68a (diff) | |
Merge "Calculate and account for memory power use"
6 files changed, 111 insertions, 1 deletions
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index f0cc3905e991..370f7f97ba8f 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -30,6 +30,7 @@ import android.content.pm.ApplicationInfo; import android.telephony.SignalStrength; import android.text.format.DateFormat; import android.util.ArrayMap; +import android.util.LongSparseArray; import android.util.MutableBoolean; import android.util.Pair; import android.util.Printer; @@ -2450,6 +2451,8 @@ public abstract class BatteryStats implements Parcelable { public abstract Map<String, ? extends Timer> getKernelWakelockStats(); + public abstract LongSparseArray<? extends Timer> getKernelMemoryStats(); + public abstract void writeToParcelWithoutUids(Parcel out, int flags); private final static void formatTimeRaw(StringBuilder out, long seconds) { @@ -4116,6 +4119,17 @@ public abstract class BatteryStats implements Parcelable { } } + final LongSparseArray<? extends Timer> mMemoryStats = getKernelMemoryStats(); + pw.println("Memory Stats"); + for (int i = 0; i < mMemoryStats.size(); i++) { + sb.setLength(0); + sb.append("Bandwidth "); + sb.append(mMemoryStats.keyAt(i)); + sb.append(" Time "); + sb.append(mMemoryStats.valueAt(i).getTotalTimeLocked(rawRealtime, which)); + pw.println(sb.toString()); + } + for (int iu=0; iu<NU; iu++) { final int uid = uidStats.keyAt(iu); if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) { diff --git a/core/java/com/android/internal/os/BatterySipper.java b/core/java/com/android/internal/os/BatterySipper.java index d92e59691fe9..5ea9475dbd9a 100644 --- a/core/java/com/android/internal/os/BatterySipper.java +++ b/core/java/com/android/internal/os/BatterySipper.java @@ -88,7 +88,8 @@ public class BatterySipper implements Comparable<BatterySipper> { USER, UNACCOUNTED, OVERCOUNTED, - CAMERA + CAMERA, + MEMORY } public BatterySipper(DrainType drainType, Uid uid, double value) { diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java index 27ffb8b98844..1ae5c6625652 100644 --- a/core/java/com/android/internal/os/BatteryStatsHelper.java +++ b/core/java/com/android/internal/os/BatteryStatsHelper.java @@ -125,6 +125,7 @@ public final class BatteryStatsHelper { PowerCalculator mSensorPowerCalculator; PowerCalculator mCameraPowerCalculator; PowerCalculator mFlashlightPowerCalculator; + PowerCalculator mMemoryPowerCalculator; boolean mHasWifiPowerReporting = false; boolean mHasBluetoothPowerReporting = false; @@ -342,6 +343,11 @@ public final class BatteryStatsHelper { } mCpuPowerCalculator.reset(); + if (mMemoryPowerCalculator == null) { + mMemoryPowerCalculator = new MemoryPowerCalculator(mPowerProfile); + } + mMemoryPowerCalculator.reset(); + if (mWakelockPowerCalculator == null) { mWakelockPowerCalculator = new WakelockPowerCalculator(mPowerProfile); } @@ -672,12 +678,23 @@ public final class BatteryStatsHelper { } } + private void addMemoryUsage() { + BatterySipper memory = new BatterySipper(DrainType.MEMORY, null, 0); + mMemoryPowerCalculator.calculateRemaining(memory, mStats, mRawRealtimeUs, mRawUptimeUs, + mStatsType); + memory.sumPower(); + if (memory.totalPowerMah > 0) { + mUsageList.add(memory); + } + } + private void processMiscUsage() { addUserUsage(); addPhoneUsage(); addScreenUsage(); addWiFiUsage(); addBluetoothUsage(); + addMemoryUsage(); addIdleUsage(); // Not including cellular idle power // Don't compute radio usage if it's a wifi-only device if (!mWifiOnly) { diff --git a/core/java/com/android/internal/os/MemoryPowerCalculator.java b/core/java/com/android/internal/os/MemoryPowerCalculator.java new file mode 100644 index 000000000000..efd3ab51284b --- /dev/null +++ b/core/java/com/android/internal/os/MemoryPowerCalculator.java @@ -0,0 +1,54 @@ +package com.android.internal.os; + +import android.os.BatteryStats; +import android.util.Log; +import android.util.LongSparseArray; + +public class MemoryPowerCalculator extends PowerCalculator { + + public static final String TAG = "MemoryPowerCalculator"; + private static final boolean DEBUG = BatteryStatsHelper.DEBUG; + private final double[] powerAverages; + + public MemoryPowerCalculator(PowerProfile profile) { + int numBuckets = profile.getNumElements(PowerProfile.POWER_MEMORY); + powerAverages = new double[numBuckets]; + for (int i = 0; i < numBuckets; i++) { + powerAverages[i] = profile.getAveragePower(PowerProfile.POWER_MEMORY, i); + if (powerAverages[i] == 0 && DEBUG) { + Log.d(TAG, "Problem with PowerProfile. Received 0 value in MemoryPowerCalculator"); + } + } + } + + @Override + public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs, + long rawUptimeUs, int statsType) {} + + @Override + public void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs, + long rawUptimeUs, int statsType) { + double totalMah = 0; + long totalTimeMs = 0; + LongSparseArray<? extends BatteryStats.Timer> timers = stats.getKernelMemoryStats(); + for (int i = 0; i < timers.size() && i < powerAverages.length; i++) { + double mAatRail = powerAverages[(int) timers.keyAt(i)]; + long timeMs = timers.valueAt(i).getTotalTimeLocked(rawRealtimeUs, statsType); + double mAm = (mAatRail * timeMs) / (1000*60); + if(DEBUG) { + Log.d(TAG, "Calculating mAh for bucket " + timers.keyAt(i) + " while unplugged"); + Log.d(TAG, "Converted power profile number from " + + powerAverages[(int) timers.keyAt(i)] + " into " + mAatRail); + Log.d(TAG, "Calculated mAm " + mAm); + } + totalMah += mAm/60; + totalTimeMs += timeMs; + } + app.usagePowerMah = totalMah; + app.usageTimeMs = totalTimeMs; + if (DEBUG) { + Log.d(TAG, String.format("Calculated total mAh for memory %f while unplugged %d ", + totalMah, totalTimeMs)); + } + } +} diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java index ad14a2071330..51cf2eae851f 100644 --- a/core/java/com/android/internal/os/PowerProfile.java +++ b/core/java/com/android/internal/os/PowerProfile.java @@ -171,6 +171,11 @@ public class PowerProfile { public static final String POWER_FLASHLIGHT = "camera.flashlight"; /** + * Power consumption when DDR is being used. + */ + public static final String POWER_MEMORY = "memory.bandwidths"; + + /** * Average power consumption when the camera is on over all standard use cases. * * TODO: Add more fine-grained camera power metrics. @@ -365,6 +370,24 @@ 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) { + if (sPowerMap.containsKey(key)) { + Object data = sPowerMap.get(key); + if (data instanceof Double[]) { + final Double[] values = (Double[]) data; + return values.length; + } else { + return 1; + } + } + return 0; + } + + /** * 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 diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index ff13125a8417..67cac4776440 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -1516,6 +1516,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub mStats.updateCpuTimeLocked(); mStats.updateKernelWakelocksLocked(); + mStats.updateKernelMemoryBandwidthLocked(); if (wifiInfo != null) { if (wifiInfo.isValid()) { |