Loading core/java/android/os/BatteryStats.java +109 −29 Original line number Diff line number Diff line Loading @@ -296,8 +296,10 @@ public abstract class BatteryStats { * New in version 35: * - Fixed bug that was not reporting high cellular tx power correctly * - Added out of service and emergency service modes to data connection types * New in version 36: * - Added PowerStats and CPU time-in-state data */ static final int CHECKIN_VERSION = 35; static final int CHECKIN_VERSION = 36; /** * Old version, we hit 9 and ran out of room, need to remove. Loading Loading @@ -1809,6 +1811,36 @@ public abstract class BatteryStats { } } /** * CPU usage for a given UID. */ public static final class CpuUsageDetails { /** * Descriptions of CPU power brackets, see PowerProfile.getCpuPowerBracketDescription */ public String[] cpuBracketDescriptions; public int uid; /** * The delta, in milliseconds, per CPU power bracket, from the previous record for the * same UID. */ public long[] cpuUsageMs; @Override public String toString() { final StringBuilder sb = new StringBuilder(); UserHandle.formatUid(sb, uid); sb.append(": "); for (int bracket = 0; bracket < cpuUsageMs.length; bracket++) { if (bracket != 0) { sb.append(", "); } sb.append(cpuUsageMs[bracket]); } return sb.toString(); } } /** * Battery history record. */ Loading Loading @@ -1952,6 +1984,9 @@ public abstract class BatteryStats { // Non-null when there is measured energy information public MeasuredEnergyDetails measuredEnergyDetails; // Non-null when there is CPU usage information public CpuUsageDetails cpuUsageDetails; public static final int EVENT_FLAG_START = 0x8000; public static final int EVENT_FLAG_FINISH = 0x4000; Loading Loading @@ -2161,6 +2196,7 @@ public abstract class BatteryStats { eventTag = null; tagsFirstOccurrence = false; measuredEnergyDetails = null; cpuUsageDetails = null; } @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) Loading Loading @@ -2211,6 +2247,7 @@ public abstract class BatteryStats { tagsFirstOccurrence = o.tagsFirstOccurrence; currentTime = o.currentTime; measuredEnergyDetails = o.measuredEnergyDetails; cpuUsageDetails = o.cpuUsageDetails; } public boolean sameNonEvent(HistoryItem o) { Loading Loading @@ -6808,6 +6845,25 @@ public abstract class BatteryStats { private String printNextItem(HistoryItem rec, long baseTime, boolean checkin, boolean verbose) { StringBuilder item = new StringBuilder(); if (rec.cpuUsageDetails != null && rec.cpuUsageDetails.cpuBracketDescriptions != null && checkin) { String[] descriptions = rec.cpuUsageDetails.cpuBracketDescriptions; for (int bracket = 0; bracket < descriptions.length; bracket++) { item.append(BATTERY_STATS_CHECKIN_VERSION); item.append(','); item.append(HISTORY_DATA); item.append(",0,XB,"); item.append(descriptions.length); item.append(','); item.append(bracket); item.append(','); item.append(descriptions[bracket]); item.append("\n"); } } if (!checkin) { item.append(" "); TimeUtils.formatDuration( Loading Loading @@ -7000,14 +7056,6 @@ public abstract class BatteryStats { item.append("\""); } } if ((rec.states2 & HistoryItem.STATE2_EXTENSIONS_FLAG) != 0) { if (!checkin) { item.append(" ext="); if (rec.measuredEnergyDetails != null) { item.append("E"); } } } if (rec.eventCode != HistoryItem.EVENT_NONE) { item.append(checkin ? "," : " "); if ((rec.eventCode&HistoryItem.EVENT_FLAG_START) != 0) { Loading Loading @@ -7036,6 +7084,58 @@ public abstract class BatteryStats { item.append("\""); } } boolean firstExtension = true; if (rec.measuredEnergyDetails != null) { firstExtension = false; if (!checkin) { item.append(" ext=energy:"); item.append(rec.measuredEnergyDetails); } else { item.append(",XE"); for (int i = 0; i < rec.measuredEnergyDetails.consumers.length; i++) { if (rec.measuredEnergyDetails.chargeUC[i] != POWER_DATA_UNAVAILABLE) { item.append(','); item.append(rec.measuredEnergyDetails.consumers[i].name); item.append('='); item.append(rec.measuredEnergyDetails.chargeUC[i]); } } } } if (rec.cpuUsageDetails != null) { if (!checkin) { if (!firstExtension) { item.append("\n "); } String[] descriptions = rec.cpuUsageDetails.cpuBracketDescriptions; if (descriptions != null) { for (int bracket = 0; bracket < descriptions.length; bracket++) { item.append(" ext=cpu-bracket:"); item.append(bracket); item.append(":"); item.append(descriptions[bracket]); item.append("\n "); } } item.append(" ext=cpu:"); item.append(rec.cpuUsageDetails); } else { if (!firstExtension) { item.append('\n'); item.append(BATTERY_STATS_CHECKIN_VERSION); item.append(','); item.append(HISTORY_DATA); item.append(",0"); } item.append(",XC,"); item.append(rec.cpuUsageDetails.uid); for (int i = 0; i < rec.cpuUsageDetails.cpuUsageMs.length; i++) { item.append(','); item.append(rec.cpuUsageDetails.cpuUsageMs[i]); } } firstExtension = false; } item.append("\n"); if (rec.stepDetails != null) { if (!checkin) { Loading Loading @@ -7132,25 +7232,6 @@ public abstract class BatteryStats { item.append("\n"); } } if (rec.measuredEnergyDetails != null) { if (!checkin) { item.append(" Energy: "); item.append(rec.measuredEnergyDetails); item.append("\n"); } else { item.append(BATTERY_STATS_CHECKIN_VERSION); item.append(','); item.append(HISTORY_DATA); item.append(",0,XE"); for (int i = 0; i < rec.measuredEnergyDetails.consumers.length; i++) { if (rec.measuredEnergyDetails.chargeUC[i] != POWER_DATA_UNAVAILABLE) { item.append(','); item.append(rec.measuredEnergyDetails.consumers[i].name); item.append('='); item.append(rec.measuredEnergyDetails.chargeUC[i]); } } item.append("\n"); } } oldState = rec.states; oldState2 = rec.states2; // Clear High Tx Power Flag for volta positioning Loading @@ -7158,7 +7239,6 @@ public abstract class BatteryStats { rec.states2 &= ~HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG; } } return item.toString(); } Loading core/java/com/android/internal/os/BatteryStatsHistory.java +40 −2 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.annotation.Nullable; import android.os.BatteryManager; import android.os.BatteryStats; import android.os.BatteryStats.BitDescription; import android.os.BatteryStats.CpuUsageDetails; import android.os.BatteryStats.HistoryItem; import android.os.BatteryStats.HistoryStepDetails; import android.os.BatteryStats.HistoryTag; Loading Loading @@ -122,6 +123,8 @@ public class BatteryStatsHistory { static final int EXTENSION_MEASURED_ENERGY_HEADER_FLAG = 0x00000001; static final int EXTENSION_MEASURED_ENERGY_FLAG = 0x00000002; static final int EXTENSION_CPU_USAGE_HEADER_FLAG = 0x00000004; static final int EXTENSION_CPU_USAGE_FLAG = 0x00000008; private final Parcel mHistoryBuffer; private final File mSystemDir; Loading Loading @@ -194,6 +197,7 @@ public class BatteryStatsHistory { private long mTrackRunningHistoryUptimeMs = 0; private long mHistoryBaseTimeMs; private boolean mMeasuredEnergyHeaderWritten = false; private boolean mCpuUsageHeaderWritten = false; private byte mLastHistoryStepLevel = 0; Loading Loading @@ -351,6 +355,7 @@ public class BatteryStatsHistory { mTrackRunningHistoryElapsedRealtimeMs = 0; mTrackRunningHistoryUptimeMs = 0; mMeasuredEnergyHeaderWritten = false; mCpuUsageHeaderWritten = false; mHistoryBuffer.setDataSize(0); mHistoryBuffer.setDataPosition(0); Loading Loading @@ -1190,6 +1195,17 @@ public class BatteryStatsHistory { mTracer.traceInstantEvent(track, name); } /** * Records CPU usage by a specific UID. The recorded data is the delta from * the previous record for the same UID. */ public void recordCpuUsage(long elapsedRealtimeMs, long uptimeMs, CpuUsageDetails cpuUsageDetails) { mHistoryCur.cpuUsageDetails = cpuUsageDetails; mHistoryCur.states2 |= HistoryItem.STATE2_EXTENSIONS_FLAG; writeHistoryItem(elapsedRealtimeMs, uptimeMs); } /** * Writes changes to a HistoryItem state bitmap to Atrace. */ Loading Loading @@ -1338,6 +1354,7 @@ public class BatteryStatsHistory { entry.setValue(entry.getValue() | BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG); } mMeasuredEnergyHeaderWritten = false; mCpuUsageHeaderWritten = false; // Make a copy of mHistoryCur. HistoryItem copy = new HistoryItem(); Loading Loading @@ -1377,6 +1394,7 @@ public class BatteryStatsHistory { cur.eventTag = null; cur.tagsFirstOccurrence = false; cur.measuredEnergyDetails = null; cur.cpuUsageDetails = null; if (DEBUG) { Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos + " now " + mHistoryBuffer.dataPosition() Loading Loading @@ -1502,12 +1520,18 @@ public class BatteryStatsHistory { extensionFlags |= BatteryStatsHistory.EXTENSION_MEASURED_ENERGY_HEADER_FLAG; } } if (cur.cpuUsageDetails != null) { extensionFlags |= EXTENSION_CPU_USAGE_FLAG; if (!mCpuUsageHeaderWritten) { extensionFlags |= BatteryStatsHistory.EXTENSION_CPU_USAGE_HEADER_FLAG; } } if (extensionFlags != 0) { cur.states2 |= HistoryItem.STATE2_EXTENSIONS_FLAG; } else { cur.states2 &= ~HistoryItem.STATE2_EXTENSIONS_FLAG; } final boolean state2IntChanged = cur.states2 != last.states2; final boolean state2IntChanged = cur.states2 != last.states2 || extensionFlags != 0; if (state2IntChanged) { firstToken |= BatteryStatsHistory.DELTA_STATE2_FLAG; } Loading Loading @@ -1645,6 +1669,20 @@ public class BatteryStatsHistory { dest.writeLong(chargeUC); } } if (cur.cpuUsageDetails != null) { if (DEBUG) { Slog.i(TAG, "WRITE DELTA: cpuUsageDetails=" + cur.cpuUsageDetails); } if (!mCpuUsageHeaderWritten) { dest.writeStringArray(cur.cpuUsageDetails.cpuBracketDescriptions); mCpuUsageHeaderWritten = true; } dest.writeInt(cur.cpuUsageDetails.uid); for (long cpuUsageMs: cur.cpuUsageDetails.cpuUsageMs) { dest.writeLong(cpuUsageMs); } } } } Loading core/java/com/android/internal/os/BatteryStatsHistoryIterator.java +27 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ public class BatteryStatsHistoryIterator { new BatteryStats.HistoryStepDetails(); private final SparseArray<BatteryStats.HistoryTag> mHistoryTags = new SparseArray<>(); private BatteryStats.MeasuredEnergyDetails mMeasuredEnergyDetails; private BatteryStats.CpuUsageDetails mCpuUsageDetails; public BatteryStatsHistoryIterator(@NonNull BatteryStatsHistory history) { mBatteryStatsHistory = history; Loading Loading @@ -229,9 +230,35 @@ public class BatteryStatsHistoryIterator { mMeasuredEnergyDetails.chargeUC[i] = src.readLong(); } cur.measuredEnergyDetails = mMeasuredEnergyDetails; } else { cur.measuredEnergyDetails = null; } if ((extensionFlags & BatteryStatsHistory.EXTENSION_CPU_USAGE_HEADER_FLAG) != 0) { mCpuUsageDetails = new BatteryStats.CpuUsageDetails(); mCpuUsageDetails.cpuBracketDescriptions = src.readStringArray(); mCpuUsageDetails.cpuUsageMs = new long[mCpuUsageDetails.cpuBracketDescriptions.length]; } else if (mCpuUsageDetails != null) { mCpuUsageDetails.cpuBracketDescriptions = null; } if ((extensionFlags & BatteryStatsHistory.EXTENSION_CPU_USAGE_FLAG) != 0) { if (mCpuUsageDetails == null) { throw new IllegalStateException("CpuUsageDetails without a header"); } mCpuUsageDetails.uid = src.readInt(); for (int i = 0; i < mCpuUsageDetails.cpuUsageMs.length; i++) { mCpuUsageDetails.cpuUsageMs[i] = src.readLong(); } cur.cpuUsageDetails = mCpuUsageDetails; } else { cur.cpuUsageDetails = null; } } else { cur.measuredEnergyDetails = null; cur.cpuUsageDetails = null; } } Loading core/java/com/android/internal/os/KernelSingleUidTimeReader.java +0 −1 Original line number Diff line number Diff line Loading @@ -33,7 +33,6 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; @VisibleForTesting(visibility = PACKAGE) public class KernelSingleUidTimeReader { private static final String TAG = KernelSingleUidTimeReader.class.getName(); private static final boolean DBG = false; Loading services/core/java/com/android/server/power/stats/BatteryStatsImpl.java +84 −27 Original line number Diff line number Diff line Loading @@ -270,6 +270,8 @@ public class BatteryStatsImpl extends BatteryStats { private final KernelMemoryBandwidthStats mKernelMemoryBandwidthStats = new KernelMemoryBandwidthStats(); private final LongSparseArray<SamplingTimer> mKernelMemoryStats = new LongSparseArray<>(); private int[] mCpuPowerBracketMap; private final CpuUsageDetails mCpuUsageDetails = new CpuUsageDetails(); public LongSparseArray<SamplingTimer> getKernelMemoryStats() { return mKernelMemoryStats; Loading Loading @@ -478,7 +480,7 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") @SuppressWarnings("GuardedBy") // errorprone false positive on getProcStateTimeCounter @VisibleForTesting public void updateProcStateCpuTimesLocked(int uid, long timestampMs) { public void updateProcStateCpuTimesLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { if (!initKernelSingleUidTimeReaderLocked()) { return; } Loading @@ -488,12 +490,20 @@ public class BatteryStatsImpl extends BatteryStats { mNumSingleUidCpuTimeReads++; LongArrayMultiStateCounter onBatteryCounter = u.getProcStateTimeCounter(timestampMs).getCounter(); u.getProcStateTimeCounter(elapsedRealtimeMs).getCounter(); LongArrayMultiStateCounter onBatteryScreenOffCounter = u.getProcStateScreenOffTimeCounter(timestampMs).getCounter(); u.getProcStateScreenOffTimeCounter(elapsedRealtimeMs).getCounter(); mKernelSingleUidTimeReader.addDelta(uid, onBatteryCounter, timestampMs); mKernelSingleUidTimeReader.addDelta(uid, onBatteryScreenOffCounter, timestampMs); if (isUsageHistoryEnabled()) { LongArrayMultiStateCounter.LongArrayContainer deltaContainer = getCpuTimeInFreqContainer(); mKernelSingleUidTimeReader.addDelta(uid, onBatteryCounter, elapsedRealtimeMs, deltaContainer); recordCpuUsage(uid, deltaContainer, elapsedRealtimeMs, uptimeMs); } else { mKernelSingleUidTimeReader.addDelta(uid, onBatteryCounter, elapsedRealtimeMs); } mKernelSingleUidTimeReader.addDelta(uid, onBatteryScreenOffCounter, elapsedRealtimeMs); if (u.mChildUids != null) { LongArrayMultiStateCounter.LongArrayContainer deltaContainer = Loading @@ -504,14 +514,27 @@ public class BatteryStatsImpl extends BatteryStats { u.mChildUids.valueAt(j).cpuTimeInFreqCounter; if (cpuTimeInFreqCounter != null) { mKernelSingleUidTimeReader.addDelta(u.mChildUids.keyAt(j), cpuTimeInFreqCounter, timestampMs, deltaContainer); cpuTimeInFreqCounter, elapsedRealtimeMs, deltaContainer); onBatteryCounter.addCounts(deltaContainer); if (isUsageHistoryEnabled()) { recordCpuUsage(uid, deltaContainer, elapsedRealtimeMs, uptimeMs); } onBatteryScreenOffCounter.addCounts(deltaContainer); } } } } private void recordCpuUsage(int uid, LongArrayMultiStateCounter.LongArrayContainer cpuUsage, long elapsedRealtimeMs, long uptimeMs) { if (!cpuUsage.combineValues(mCpuUsageDetails.cpuUsageMs, mCpuPowerBracketMap)) { return; } mCpuUsageDetails.uid = uid; mHistory.recordCpuUsage(elapsedRealtimeMs, uptimeMs, mCpuUsageDetails); } /** * Removes kernel CPU stats for removed UIDs, in the order they were added to the * mPendingRemovedUids queue. Loading Loading @@ -557,16 +580,26 @@ public class BatteryStatsImpl extends BatteryStats { continue; } final long timestampMs = mClock.elapsedRealtime(); final long elapsedRealtimeMs = mClock.elapsedRealtime(); final long uptimeMs = mClock.uptimeMillis(); final LongArrayMultiStateCounter onBatteryCounter = u.getProcStateTimeCounter(timestampMs).getCounter(); u.getProcStateTimeCounter(elapsedRealtimeMs).getCounter(); final LongArrayMultiStateCounter onBatteryScreenOffCounter = u.getProcStateScreenOffTimeCounter(timestampMs).getCounter(); u.getProcStateScreenOffTimeCounter(elapsedRealtimeMs).getCounter(); if (uid == parentUid || Process.isSdkSandboxUid(uid)) { mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryCounter, timestampMs); if (isUsageHistoryEnabled()) { LongArrayMultiStateCounter.LongArrayContainer deltaContainer = getCpuTimeInFreqContainer(); mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryCounter, elapsedRealtimeMs, deltaContainer); recordCpuUsage(parentUid, deltaContainer, elapsedRealtimeMs, uptimeMs); } else { mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryCounter, elapsedRealtimeMs); } mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryScreenOffCounter, timestampMs); elapsedRealtimeMs); } else { Uid.ChildUid childUid = u.getChildUid(uid); if (childUid != null) { Loading @@ -574,26 +607,18 @@ public class BatteryStatsImpl extends BatteryStats { if (counter != null) { final LongArrayMultiStateCounter.LongArrayContainer deltaContainer = getCpuTimeInFreqContainer(); mKernelSingleUidTimeReader.addDelta(uid, counter, timestampMs, mKernelSingleUidTimeReader.addDelta(uid, counter, elapsedRealtimeMs, deltaContainer); onBatteryCounter.addCounts(deltaContainer); onBatteryScreenOffCounter.addCounts(deltaContainer); } } if (isUsageHistoryEnabled()) { recordCpuUsage(uid, deltaContainer, elapsedRealtimeMs, uptimeMs); } onBatteryScreenOffCounter.addCounts(deltaContainer); } } } @VisibleForTesting public static long[] addCpuTimes(long[] timesA, long[] timesB) { if (timesA != null && timesB != null) { for (int i = timesA.length - 1; i >= 0; --i) { timesA[i] += timesB[i]; } return timesA; } return timesA == null ? (timesB == null ? null : timesB) : timesA; } @GuardedBy("this") Loading Loading @@ -7422,9 +7447,11 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") public void recordMeasuredEnergyDetailsLocked(long elapsedRealtimeMs, long uptimeMs, MeasuredEnergyDetails measuredEnergyDetails) { if (isUsageHistoryEnabled()) { mHistory.recordMeasuredEnergyDetails(elapsedRealtimeMs, uptimeMs, measuredEnergyDetails); } } @GuardedBy("this") @Override public long getStartClockTime() { Loading Loading @@ -10285,7 +10312,7 @@ public class BatteryStatsImpl extends BatteryStats { } if (mBsi.trackPerProcStateCpuTimes()) { mBsi.updateProcStateCpuTimesLocked(mUid, elapsedRealtimeMs); mBsi.updateProcStateCpuTimesLocked(mUid, elapsedRealtimeMs, uptimeMs); LongArrayMultiStateCounter onBatteryCounter = getProcStateTimeCounter(elapsedRealtimeMs).getCounter(); Loading Loading @@ -10784,6 +10811,10 @@ public class BatteryStatsImpl extends BatteryStats { mBatteryLevel = 0; } /** * Injects a power profile. */ @GuardedBy("this") public void setPowerProfileLocked(PowerProfile profile) { mPowerProfile = profile; Loading @@ -10800,6 +10831,27 @@ public class BatteryStatsImpl extends BatteryStats { firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i); } // Initialize CPU power bracket map, which combines CPU states (cluster/freq pairs) // into a small number of brackets mCpuPowerBracketMap = new int[getCpuFreqCount()]; int index = 0; int numCpuClusters = mPowerProfile.getNumCpuClusters(); for (int cluster = 0; cluster < numCpuClusters; cluster++) { int steps = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster); for (int step = 0; step < steps; step++) { mCpuPowerBracketMap[index++] = mPowerProfile.getPowerBracketForCpuCore(cluster, step); } } int cpuPowerBracketCount = mPowerProfile.getCpuPowerBracketCount(); mCpuUsageDetails.cpuBracketDescriptions = new String[cpuPowerBracketCount]; mCpuUsageDetails.cpuUsageMs = new long[cpuPowerBracketCount]; for (int i = 0; i < cpuPowerBracketCount; i++) { mCpuUsageDetails.cpuBracketDescriptions[i] = mPowerProfile.getCpuPowerBracketDescription(i); } if (mEstimatedBatteryCapacityMah == -1) { // Initialize the estimated battery capacity to a known preset one. mEstimatedBatteryCapacityMah = (int) mPowerProfile.getBatteryCapacity(); Loading Loading @@ -14630,10 +14682,15 @@ public class BatteryStatsImpl extends BatteryStats { } @GuardedBy("this") public boolean trackPerProcStateCpuTimes() { private boolean trackPerProcStateCpuTimes() { return mCpuUidFreqTimeReader.isFastCpuTimesReader(); } @GuardedBy("this") private boolean isUsageHistoryEnabled() { return false; } @GuardedBy("this") public void systemServicesReady(Context context) { mConstants.startObserving(context.getContentResolver()); Loading
core/java/android/os/BatteryStats.java +109 −29 Original line number Diff line number Diff line Loading @@ -296,8 +296,10 @@ public abstract class BatteryStats { * New in version 35: * - Fixed bug that was not reporting high cellular tx power correctly * - Added out of service and emergency service modes to data connection types * New in version 36: * - Added PowerStats and CPU time-in-state data */ static final int CHECKIN_VERSION = 35; static final int CHECKIN_VERSION = 36; /** * Old version, we hit 9 and ran out of room, need to remove. Loading Loading @@ -1809,6 +1811,36 @@ public abstract class BatteryStats { } } /** * CPU usage for a given UID. */ public static final class CpuUsageDetails { /** * Descriptions of CPU power brackets, see PowerProfile.getCpuPowerBracketDescription */ public String[] cpuBracketDescriptions; public int uid; /** * The delta, in milliseconds, per CPU power bracket, from the previous record for the * same UID. */ public long[] cpuUsageMs; @Override public String toString() { final StringBuilder sb = new StringBuilder(); UserHandle.formatUid(sb, uid); sb.append(": "); for (int bracket = 0; bracket < cpuUsageMs.length; bracket++) { if (bracket != 0) { sb.append(", "); } sb.append(cpuUsageMs[bracket]); } return sb.toString(); } } /** * Battery history record. */ Loading Loading @@ -1952,6 +1984,9 @@ public abstract class BatteryStats { // Non-null when there is measured energy information public MeasuredEnergyDetails measuredEnergyDetails; // Non-null when there is CPU usage information public CpuUsageDetails cpuUsageDetails; public static final int EVENT_FLAG_START = 0x8000; public static final int EVENT_FLAG_FINISH = 0x4000; Loading Loading @@ -2161,6 +2196,7 @@ public abstract class BatteryStats { eventTag = null; tagsFirstOccurrence = false; measuredEnergyDetails = null; cpuUsageDetails = null; } @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) Loading Loading @@ -2211,6 +2247,7 @@ public abstract class BatteryStats { tagsFirstOccurrence = o.tagsFirstOccurrence; currentTime = o.currentTime; measuredEnergyDetails = o.measuredEnergyDetails; cpuUsageDetails = o.cpuUsageDetails; } public boolean sameNonEvent(HistoryItem o) { Loading Loading @@ -6808,6 +6845,25 @@ public abstract class BatteryStats { private String printNextItem(HistoryItem rec, long baseTime, boolean checkin, boolean verbose) { StringBuilder item = new StringBuilder(); if (rec.cpuUsageDetails != null && rec.cpuUsageDetails.cpuBracketDescriptions != null && checkin) { String[] descriptions = rec.cpuUsageDetails.cpuBracketDescriptions; for (int bracket = 0; bracket < descriptions.length; bracket++) { item.append(BATTERY_STATS_CHECKIN_VERSION); item.append(','); item.append(HISTORY_DATA); item.append(",0,XB,"); item.append(descriptions.length); item.append(','); item.append(bracket); item.append(','); item.append(descriptions[bracket]); item.append("\n"); } } if (!checkin) { item.append(" "); TimeUtils.formatDuration( Loading Loading @@ -7000,14 +7056,6 @@ public abstract class BatteryStats { item.append("\""); } } if ((rec.states2 & HistoryItem.STATE2_EXTENSIONS_FLAG) != 0) { if (!checkin) { item.append(" ext="); if (rec.measuredEnergyDetails != null) { item.append("E"); } } } if (rec.eventCode != HistoryItem.EVENT_NONE) { item.append(checkin ? "," : " "); if ((rec.eventCode&HistoryItem.EVENT_FLAG_START) != 0) { Loading Loading @@ -7036,6 +7084,58 @@ public abstract class BatteryStats { item.append("\""); } } boolean firstExtension = true; if (rec.measuredEnergyDetails != null) { firstExtension = false; if (!checkin) { item.append(" ext=energy:"); item.append(rec.measuredEnergyDetails); } else { item.append(",XE"); for (int i = 0; i < rec.measuredEnergyDetails.consumers.length; i++) { if (rec.measuredEnergyDetails.chargeUC[i] != POWER_DATA_UNAVAILABLE) { item.append(','); item.append(rec.measuredEnergyDetails.consumers[i].name); item.append('='); item.append(rec.measuredEnergyDetails.chargeUC[i]); } } } } if (rec.cpuUsageDetails != null) { if (!checkin) { if (!firstExtension) { item.append("\n "); } String[] descriptions = rec.cpuUsageDetails.cpuBracketDescriptions; if (descriptions != null) { for (int bracket = 0; bracket < descriptions.length; bracket++) { item.append(" ext=cpu-bracket:"); item.append(bracket); item.append(":"); item.append(descriptions[bracket]); item.append("\n "); } } item.append(" ext=cpu:"); item.append(rec.cpuUsageDetails); } else { if (!firstExtension) { item.append('\n'); item.append(BATTERY_STATS_CHECKIN_VERSION); item.append(','); item.append(HISTORY_DATA); item.append(",0"); } item.append(",XC,"); item.append(rec.cpuUsageDetails.uid); for (int i = 0; i < rec.cpuUsageDetails.cpuUsageMs.length; i++) { item.append(','); item.append(rec.cpuUsageDetails.cpuUsageMs[i]); } } firstExtension = false; } item.append("\n"); if (rec.stepDetails != null) { if (!checkin) { Loading Loading @@ -7132,25 +7232,6 @@ public abstract class BatteryStats { item.append("\n"); } } if (rec.measuredEnergyDetails != null) { if (!checkin) { item.append(" Energy: "); item.append(rec.measuredEnergyDetails); item.append("\n"); } else { item.append(BATTERY_STATS_CHECKIN_VERSION); item.append(','); item.append(HISTORY_DATA); item.append(",0,XE"); for (int i = 0; i < rec.measuredEnergyDetails.consumers.length; i++) { if (rec.measuredEnergyDetails.chargeUC[i] != POWER_DATA_UNAVAILABLE) { item.append(','); item.append(rec.measuredEnergyDetails.consumers[i].name); item.append('='); item.append(rec.measuredEnergyDetails.chargeUC[i]); } } item.append("\n"); } } oldState = rec.states; oldState2 = rec.states2; // Clear High Tx Power Flag for volta positioning Loading @@ -7158,7 +7239,6 @@ public abstract class BatteryStats { rec.states2 &= ~HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG; } } return item.toString(); } Loading
core/java/com/android/internal/os/BatteryStatsHistory.java +40 −2 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.annotation.Nullable; import android.os.BatteryManager; import android.os.BatteryStats; import android.os.BatteryStats.BitDescription; import android.os.BatteryStats.CpuUsageDetails; import android.os.BatteryStats.HistoryItem; import android.os.BatteryStats.HistoryStepDetails; import android.os.BatteryStats.HistoryTag; Loading Loading @@ -122,6 +123,8 @@ public class BatteryStatsHistory { static final int EXTENSION_MEASURED_ENERGY_HEADER_FLAG = 0x00000001; static final int EXTENSION_MEASURED_ENERGY_FLAG = 0x00000002; static final int EXTENSION_CPU_USAGE_HEADER_FLAG = 0x00000004; static final int EXTENSION_CPU_USAGE_FLAG = 0x00000008; private final Parcel mHistoryBuffer; private final File mSystemDir; Loading Loading @@ -194,6 +197,7 @@ public class BatteryStatsHistory { private long mTrackRunningHistoryUptimeMs = 0; private long mHistoryBaseTimeMs; private boolean mMeasuredEnergyHeaderWritten = false; private boolean mCpuUsageHeaderWritten = false; private byte mLastHistoryStepLevel = 0; Loading Loading @@ -351,6 +355,7 @@ public class BatteryStatsHistory { mTrackRunningHistoryElapsedRealtimeMs = 0; mTrackRunningHistoryUptimeMs = 0; mMeasuredEnergyHeaderWritten = false; mCpuUsageHeaderWritten = false; mHistoryBuffer.setDataSize(0); mHistoryBuffer.setDataPosition(0); Loading Loading @@ -1190,6 +1195,17 @@ public class BatteryStatsHistory { mTracer.traceInstantEvent(track, name); } /** * Records CPU usage by a specific UID. The recorded data is the delta from * the previous record for the same UID. */ public void recordCpuUsage(long elapsedRealtimeMs, long uptimeMs, CpuUsageDetails cpuUsageDetails) { mHistoryCur.cpuUsageDetails = cpuUsageDetails; mHistoryCur.states2 |= HistoryItem.STATE2_EXTENSIONS_FLAG; writeHistoryItem(elapsedRealtimeMs, uptimeMs); } /** * Writes changes to a HistoryItem state bitmap to Atrace. */ Loading Loading @@ -1338,6 +1354,7 @@ public class BatteryStatsHistory { entry.setValue(entry.getValue() | BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG); } mMeasuredEnergyHeaderWritten = false; mCpuUsageHeaderWritten = false; // Make a copy of mHistoryCur. HistoryItem copy = new HistoryItem(); Loading Loading @@ -1377,6 +1394,7 @@ public class BatteryStatsHistory { cur.eventTag = null; cur.tagsFirstOccurrence = false; cur.measuredEnergyDetails = null; cur.cpuUsageDetails = null; if (DEBUG) { Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos + " now " + mHistoryBuffer.dataPosition() Loading Loading @@ -1502,12 +1520,18 @@ public class BatteryStatsHistory { extensionFlags |= BatteryStatsHistory.EXTENSION_MEASURED_ENERGY_HEADER_FLAG; } } if (cur.cpuUsageDetails != null) { extensionFlags |= EXTENSION_CPU_USAGE_FLAG; if (!mCpuUsageHeaderWritten) { extensionFlags |= BatteryStatsHistory.EXTENSION_CPU_USAGE_HEADER_FLAG; } } if (extensionFlags != 0) { cur.states2 |= HistoryItem.STATE2_EXTENSIONS_FLAG; } else { cur.states2 &= ~HistoryItem.STATE2_EXTENSIONS_FLAG; } final boolean state2IntChanged = cur.states2 != last.states2; final boolean state2IntChanged = cur.states2 != last.states2 || extensionFlags != 0; if (state2IntChanged) { firstToken |= BatteryStatsHistory.DELTA_STATE2_FLAG; } Loading Loading @@ -1645,6 +1669,20 @@ public class BatteryStatsHistory { dest.writeLong(chargeUC); } } if (cur.cpuUsageDetails != null) { if (DEBUG) { Slog.i(TAG, "WRITE DELTA: cpuUsageDetails=" + cur.cpuUsageDetails); } if (!mCpuUsageHeaderWritten) { dest.writeStringArray(cur.cpuUsageDetails.cpuBracketDescriptions); mCpuUsageHeaderWritten = true; } dest.writeInt(cur.cpuUsageDetails.uid); for (long cpuUsageMs: cur.cpuUsageDetails.cpuUsageMs) { dest.writeLong(cpuUsageMs); } } } } Loading
core/java/com/android/internal/os/BatteryStatsHistoryIterator.java +27 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ public class BatteryStatsHistoryIterator { new BatteryStats.HistoryStepDetails(); private final SparseArray<BatteryStats.HistoryTag> mHistoryTags = new SparseArray<>(); private BatteryStats.MeasuredEnergyDetails mMeasuredEnergyDetails; private BatteryStats.CpuUsageDetails mCpuUsageDetails; public BatteryStatsHistoryIterator(@NonNull BatteryStatsHistory history) { mBatteryStatsHistory = history; Loading Loading @@ -229,9 +230,35 @@ public class BatteryStatsHistoryIterator { mMeasuredEnergyDetails.chargeUC[i] = src.readLong(); } cur.measuredEnergyDetails = mMeasuredEnergyDetails; } else { cur.measuredEnergyDetails = null; } if ((extensionFlags & BatteryStatsHistory.EXTENSION_CPU_USAGE_HEADER_FLAG) != 0) { mCpuUsageDetails = new BatteryStats.CpuUsageDetails(); mCpuUsageDetails.cpuBracketDescriptions = src.readStringArray(); mCpuUsageDetails.cpuUsageMs = new long[mCpuUsageDetails.cpuBracketDescriptions.length]; } else if (mCpuUsageDetails != null) { mCpuUsageDetails.cpuBracketDescriptions = null; } if ((extensionFlags & BatteryStatsHistory.EXTENSION_CPU_USAGE_FLAG) != 0) { if (mCpuUsageDetails == null) { throw new IllegalStateException("CpuUsageDetails without a header"); } mCpuUsageDetails.uid = src.readInt(); for (int i = 0; i < mCpuUsageDetails.cpuUsageMs.length; i++) { mCpuUsageDetails.cpuUsageMs[i] = src.readLong(); } cur.cpuUsageDetails = mCpuUsageDetails; } else { cur.cpuUsageDetails = null; } } else { cur.measuredEnergyDetails = null; cur.cpuUsageDetails = null; } } Loading
core/java/com/android/internal/os/KernelSingleUidTimeReader.java +0 −1 Original line number Diff line number Diff line Loading @@ -33,7 +33,6 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; @VisibleForTesting(visibility = PACKAGE) public class KernelSingleUidTimeReader { private static final String TAG = KernelSingleUidTimeReader.class.getName(); private static final boolean DBG = false; Loading
services/core/java/com/android/server/power/stats/BatteryStatsImpl.java +84 −27 Original line number Diff line number Diff line Loading @@ -270,6 +270,8 @@ public class BatteryStatsImpl extends BatteryStats { private final KernelMemoryBandwidthStats mKernelMemoryBandwidthStats = new KernelMemoryBandwidthStats(); private final LongSparseArray<SamplingTimer> mKernelMemoryStats = new LongSparseArray<>(); private int[] mCpuPowerBracketMap; private final CpuUsageDetails mCpuUsageDetails = new CpuUsageDetails(); public LongSparseArray<SamplingTimer> getKernelMemoryStats() { return mKernelMemoryStats; Loading Loading @@ -478,7 +480,7 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") @SuppressWarnings("GuardedBy") // errorprone false positive on getProcStateTimeCounter @VisibleForTesting public void updateProcStateCpuTimesLocked(int uid, long timestampMs) { public void updateProcStateCpuTimesLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { if (!initKernelSingleUidTimeReaderLocked()) { return; } Loading @@ -488,12 +490,20 @@ public class BatteryStatsImpl extends BatteryStats { mNumSingleUidCpuTimeReads++; LongArrayMultiStateCounter onBatteryCounter = u.getProcStateTimeCounter(timestampMs).getCounter(); u.getProcStateTimeCounter(elapsedRealtimeMs).getCounter(); LongArrayMultiStateCounter onBatteryScreenOffCounter = u.getProcStateScreenOffTimeCounter(timestampMs).getCounter(); u.getProcStateScreenOffTimeCounter(elapsedRealtimeMs).getCounter(); mKernelSingleUidTimeReader.addDelta(uid, onBatteryCounter, timestampMs); mKernelSingleUidTimeReader.addDelta(uid, onBatteryScreenOffCounter, timestampMs); if (isUsageHistoryEnabled()) { LongArrayMultiStateCounter.LongArrayContainer deltaContainer = getCpuTimeInFreqContainer(); mKernelSingleUidTimeReader.addDelta(uid, onBatteryCounter, elapsedRealtimeMs, deltaContainer); recordCpuUsage(uid, deltaContainer, elapsedRealtimeMs, uptimeMs); } else { mKernelSingleUidTimeReader.addDelta(uid, onBatteryCounter, elapsedRealtimeMs); } mKernelSingleUidTimeReader.addDelta(uid, onBatteryScreenOffCounter, elapsedRealtimeMs); if (u.mChildUids != null) { LongArrayMultiStateCounter.LongArrayContainer deltaContainer = Loading @@ -504,14 +514,27 @@ public class BatteryStatsImpl extends BatteryStats { u.mChildUids.valueAt(j).cpuTimeInFreqCounter; if (cpuTimeInFreqCounter != null) { mKernelSingleUidTimeReader.addDelta(u.mChildUids.keyAt(j), cpuTimeInFreqCounter, timestampMs, deltaContainer); cpuTimeInFreqCounter, elapsedRealtimeMs, deltaContainer); onBatteryCounter.addCounts(deltaContainer); if (isUsageHistoryEnabled()) { recordCpuUsage(uid, deltaContainer, elapsedRealtimeMs, uptimeMs); } onBatteryScreenOffCounter.addCounts(deltaContainer); } } } } private void recordCpuUsage(int uid, LongArrayMultiStateCounter.LongArrayContainer cpuUsage, long elapsedRealtimeMs, long uptimeMs) { if (!cpuUsage.combineValues(mCpuUsageDetails.cpuUsageMs, mCpuPowerBracketMap)) { return; } mCpuUsageDetails.uid = uid; mHistory.recordCpuUsage(elapsedRealtimeMs, uptimeMs, mCpuUsageDetails); } /** * Removes kernel CPU stats for removed UIDs, in the order they were added to the * mPendingRemovedUids queue. Loading Loading @@ -557,16 +580,26 @@ public class BatteryStatsImpl extends BatteryStats { continue; } final long timestampMs = mClock.elapsedRealtime(); final long elapsedRealtimeMs = mClock.elapsedRealtime(); final long uptimeMs = mClock.uptimeMillis(); final LongArrayMultiStateCounter onBatteryCounter = u.getProcStateTimeCounter(timestampMs).getCounter(); u.getProcStateTimeCounter(elapsedRealtimeMs).getCounter(); final LongArrayMultiStateCounter onBatteryScreenOffCounter = u.getProcStateScreenOffTimeCounter(timestampMs).getCounter(); u.getProcStateScreenOffTimeCounter(elapsedRealtimeMs).getCounter(); if (uid == parentUid || Process.isSdkSandboxUid(uid)) { mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryCounter, timestampMs); if (isUsageHistoryEnabled()) { LongArrayMultiStateCounter.LongArrayContainer deltaContainer = getCpuTimeInFreqContainer(); mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryCounter, elapsedRealtimeMs, deltaContainer); recordCpuUsage(parentUid, deltaContainer, elapsedRealtimeMs, uptimeMs); } else { mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryCounter, elapsedRealtimeMs); } mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryScreenOffCounter, timestampMs); elapsedRealtimeMs); } else { Uid.ChildUid childUid = u.getChildUid(uid); if (childUid != null) { Loading @@ -574,26 +607,18 @@ public class BatteryStatsImpl extends BatteryStats { if (counter != null) { final LongArrayMultiStateCounter.LongArrayContainer deltaContainer = getCpuTimeInFreqContainer(); mKernelSingleUidTimeReader.addDelta(uid, counter, timestampMs, mKernelSingleUidTimeReader.addDelta(uid, counter, elapsedRealtimeMs, deltaContainer); onBatteryCounter.addCounts(deltaContainer); onBatteryScreenOffCounter.addCounts(deltaContainer); } } if (isUsageHistoryEnabled()) { recordCpuUsage(uid, deltaContainer, elapsedRealtimeMs, uptimeMs); } onBatteryScreenOffCounter.addCounts(deltaContainer); } } } @VisibleForTesting public static long[] addCpuTimes(long[] timesA, long[] timesB) { if (timesA != null && timesB != null) { for (int i = timesA.length - 1; i >= 0; --i) { timesA[i] += timesB[i]; } return timesA; } return timesA == null ? (timesB == null ? null : timesB) : timesA; } @GuardedBy("this") Loading Loading @@ -7422,9 +7447,11 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") public void recordMeasuredEnergyDetailsLocked(long elapsedRealtimeMs, long uptimeMs, MeasuredEnergyDetails measuredEnergyDetails) { if (isUsageHistoryEnabled()) { mHistory.recordMeasuredEnergyDetails(elapsedRealtimeMs, uptimeMs, measuredEnergyDetails); } } @GuardedBy("this") @Override public long getStartClockTime() { Loading Loading @@ -10285,7 +10312,7 @@ public class BatteryStatsImpl extends BatteryStats { } if (mBsi.trackPerProcStateCpuTimes()) { mBsi.updateProcStateCpuTimesLocked(mUid, elapsedRealtimeMs); mBsi.updateProcStateCpuTimesLocked(mUid, elapsedRealtimeMs, uptimeMs); LongArrayMultiStateCounter onBatteryCounter = getProcStateTimeCounter(elapsedRealtimeMs).getCounter(); Loading Loading @@ -10784,6 +10811,10 @@ public class BatteryStatsImpl extends BatteryStats { mBatteryLevel = 0; } /** * Injects a power profile. */ @GuardedBy("this") public void setPowerProfileLocked(PowerProfile profile) { mPowerProfile = profile; Loading @@ -10800,6 +10831,27 @@ public class BatteryStatsImpl extends BatteryStats { firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i); } // Initialize CPU power bracket map, which combines CPU states (cluster/freq pairs) // into a small number of brackets mCpuPowerBracketMap = new int[getCpuFreqCount()]; int index = 0; int numCpuClusters = mPowerProfile.getNumCpuClusters(); for (int cluster = 0; cluster < numCpuClusters; cluster++) { int steps = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster); for (int step = 0; step < steps; step++) { mCpuPowerBracketMap[index++] = mPowerProfile.getPowerBracketForCpuCore(cluster, step); } } int cpuPowerBracketCount = mPowerProfile.getCpuPowerBracketCount(); mCpuUsageDetails.cpuBracketDescriptions = new String[cpuPowerBracketCount]; mCpuUsageDetails.cpuUsageMs = new long[cpuPowerBracketCount]; for (int i = 0; i < cpuPowerBracketCount; i++) { mCpuUsageDetails.cpuBracketDescriptions[i] = mPowerProfile.getCpuPowerBracketDescription(i); } if (mEstimatedBatteryCapacityMah == -1) { // Initialize the estimated battery capacity to a known preset one. mEstimatedBatteryCapacityMah = (int) mPowerProfile.getBatteryCapacity(); Loading Loading @@ -14630,10 +14682,15 @@ public class BatteryStatsImpl extends BatteryStats { } @GuardedBy("this") public boolean trackPerProcStateCpuTimes() { private boolean trackPerProcStateCpuTimes() { return mCpuUidFreqTimeReader.isFastCpuTimesReader(); } @GuardedBy("this") private boolean isUsageHistoryEnabled() { return false; } @GuardedBy("this") public void systemServicesReady(Context context) { mConstants.startObserving(context.getContentResolver());