Loading services/core/java/com/android/server/power/stats/BatteryStatsImpl.java +40 −24 Original line number Diff line number Diff line Loading @@ -251,9 +251,10 @@ public class BatteryStatsImpl extends BatteryStats { private static final LongCounter[] ZERO_LONG_COUNTER_ARRAY = new LongCounter[]{ZERO_LONG_COUNTER}; private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader(); private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats(); @VisibleForTesting protected KernelWakelockReader mKernelWakelockReader; @VisibleForTesting protected KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader; @VisibleForTesting Loading Loading @@ -1763,6 +1764,7 @@ public class BatteryStatsImpl extends BatteryStats { mCpuUidFreqTimeReader = new KernelCpuUidFreqTimeReader(true, clock); mCpuUidActiveTimeReader = new KernelCpuUidActiveTimeReader(true, clock); mCpuUidClusterTimeReader = new KernelCpuUidClusterTimeReader(true, clock); mKernelWakelockReader = new KernelWakelockReader(); } /** Loading Loading @@ -2675,19 +2677,18 @@ public class BatteryStatsImpl extends BatteryStats { * The reported count from /proc/wakelocks when unplug() was last * called. */ int mUnpluggedReportedCount; int mBaseReportedCount; /** * The most recent reported total_time from /proc/wakelocks. */ long mCurrentReportedTotalTimeUs; /** * The reported total_time from /proc/wakelocks when unplug() was last * called. */ long mUnpluggedReportedTotalTimeUs; long mBaseReportedTotalTimeUs; /** * Whether we are currently in a discharge cycle. Loading @@ -2708,9 +2709,9 @@ public class BatteryStatsImpl extends BatteryStats { public SamplingTimer(Clock clock, TimeBase timeBase, Parcel in) { super(clock, 0, timeBase, in); mCurrentReportedCount = in.readInt(); mUnpluggedReportedCount = in.readInt(); mBaseReportedCount = in.readInt(); mCurrentReportedTotalTimeUs = in.readLong(); mUnpluggedReportedTotalTimeUs = in.readLong(); mBaseReportedTotalTimeUs = in.readLong(); mTrackingReportedValues = in.readInt() == 1; mTimeBaseRunning = timeBase.isRunning(); } Loading @@ -2736,8 +2737,8 @@ public class BatteryStatsImpl extends BatteryStats { public void endSample(long elapsedRealtimeUs) { mTotalTimeUs = computeRunTimeLocked(0 /* unused by us */, elapsedRealtimeUs); mCount = computeCurrentCountLocked(); mUnpluggedReportedTotalTimeUs = mCurrentReportedTotalTimeUs = 0; mUnpluggedReportedCount = mCurrentReportedCount = 0; mBaseReportedTotalTimeUs = mCurrentReportedTotalTimeUs = 0; mBaseReportedCount = mCurrentReportedCount = 0; mTrackingReportedValues = false; } Loading @@ -2762,10 +2763,21 @@ public class BatteryStatsImpl extends BatteryStats { * @param count total number of times the event being sampled occurred. */ public void update(long totalTimeUs, int count, long elapsedRealtimeUs) { update(totalTimeUs, 0, count, elapsedRealtimeUs); } /** * Updates the current recorded values. See {@link #update(long, int, long)} * * @param activeTimeUs Time that the currently active wake lock has been held. */ public void update(long totalTimeUs, long activeTimeUs, int count, long elapsedRealtimeUs) { if (mTimeBaseRunning && !mTrackingReportedValues) { // Updating the reported value for the first time. mUnpluggedReportedTotalTimeUs = totalTimeUs; mUnpluggedReportedCount = count; // Updating the reported value for the first time. If the wake lock is currently // active, mark the time it was acquired as the base timestamp. mBaseReportedTotalTimeUs = totalTimeUs - activeTimeUs; mBaseReportedCount = activeTimeUs == 0 ? count : count - 1; } mTrackingReportedValues = true; Loading Loading @@ -2800,8 +2812,8 @@ public class BatteryStatsImpl extends BatteryStats { public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) { super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs); if (mTrackingReportedValues) { mUnpluggedReportedTotalTimeUs = mCurrentReportedTotalTimeUs; mUnpluggedReportedCount = mCurrentReportedCount; mBaseReportedTotalTimeUs = mCurrentReportedTotalTimeUs; mBaseReportedCount = mCurrentReportedCount; } mTimeBaseRunning = true; } Loading @@ -2816,30 +2828,30 @@ public class BatteryStatsImpl extends BatteryStats { public void logState(Printer pw, String prefix) { super.logState(pw, prefix); pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount + " mUnpluggedReportedCount=" + mUnpluggedReportedCount + " mBaseReportedCount=" + mBaseReportedCount + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTimeUs + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTimeUs); + " mBaseReportedTotalTimeUs=" + mBaseReportedTotalTimeUs); } @Override protected long computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs) { return mTotalTimeUs + (mTimeBaseRunning && mTrackingReportedValues ? mCurrentReportedTotalTimeUs - mUnpluggedReportedTotalTimeUs : 0); ? mCurrentReportedTotalTimeUs - mBaseReportedTotalTimeUs : 0); } @Override protected int computeCurrentCountLocked() { return mCount + (mTimeBaseRunning && mTrackingReportedValues ? mCurrentReportedCount - mUnpluggedReportedCount : 0); ? mCurrentReportedCount - mBaseReportedCount : 0); } @Override public void writeToParcel(Parcel out, long elapsedRealtimeUs) { super.writeToParcel(out, elapsedRealtimeUs); out.writeInt(mCurrentReportedCount); out.writeInt(mUnpluggedReportedCount); out.writeInt(mBaseReportedCount); out.writeLong(mCurrentReportedTotalTimeUs); out.writeLong(mUnpluggedReportedTotalTimeUs); out.writeLong(mBaseReportedTotalTimeUs); out.writeInt(mTrackingReportedValues ? 1 : 0); } Loading @@ -2847,8 +2859,8 @@ public class BatteryStatsImpl extends BatteryStats { public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) { super.reset(detachIfReset, elapsedRealtimeUs); mTrackingReportedValues = false; mUnpluggedReportedTotalTimeUs = 0; mUnpluggedReportedCount = 0; mBaseReportedTotalTimeUs = 0; mBaseReportedCount = 0; return true; } } Loading Loading @@ -13398,6 +13410,10 @@ public class BatteryStatsImpl extends BatteryStats { * Read and distribute kernel wake lock use across apps. */ public void updateKernelWakelocksLocked(long elapsedRealtimeUs) { if (mKernelWakelockReader == null) { return; } final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats( mTmpWakelockStats); if (wakelockStats == null) { Loading @@ -13416,8 +13432,8 @@ public class BatteryStatsImpl extends BatteryStats { mKernelWakelockStats.put(name, kwlt); } kwlt.update(kws.mTotalTime, kws.mCount, elapsedRealtimeUs); kwlt.setUpdateVersion(kws.mVersion); kwlt.update(kws.totalTimeUs, kws.activeTimeUs, kws.count, elapsedRealtimeUs); kwlt.setUpdateVersion(kws.version); } int numWakelocksSetStale = 0; Loading Loading @@ -13471,7 +13487,7 @@ public class BatteryStatsImpl extends BatteryStats { Slog.d(TAG, String.format("Added entry %d and updated timer to: " + "mUnpluggedReportedTotalTimeUs %d size %d", bandwidthEntries.keyAt(i), mKernelMemoryStats.get( bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTimeUs, bandwidthEntries.keyAt(i)).mBaseReportedTotalTimeUs, mKernelMemoryStats.size())); } } services/core/java/com/android/server/power/stats/KernelWakelockReader.java +53 −42 Original line number Diff line number Diff line Loading @@ -43,29 +43,30 @@ public class KernelWakelockReader { private static final String sSysClassWakeupDir = "/sys/class/wakeup"; private static final int[] PROC_WAKELOCKS_FORMAT = new int[]{ Process.PROC_TAB_TERM|Process.PROC_OUT_STRING| // 0: name Process.PROC_QUOTES, Process.PROC_TAB_TERM | Process.PROC_OUT_STRING // 0: name | Process.PROC_QUOTES, Process.PROC_TAB_TERM | Process.PROC_OUT_LONG, // 1: count Process.PROC_TAB_TERM, Process.PROC_TAB_TERM, Process.PROC_TAB_TERM | Process.PROC_OUT_LONG, // 3: activeSince Process.PROC_TAB_TERM, Process.PROC_TAB_TERM | Process.PROC_OUT_LONG, // 5: totalTime }; private static final int[] WAKEUP_SOURCES_FORMAT = new int[]{ Process.PROC_TAB_TERM | Process.PROC_OUT_STRING, // 0: name Process.PROC_TAB_TERM|Process.PROC_COMBINE| Process.PROC_OUT_LONG, // 1: count Process.PROC_TAB_TERM|Process.PROC_COMBINE, Process.PROC_TAB_TERM | Process.PROC_COMBINE | Process.PROC_OUT_LONG, // 1: count Process.PROC_TAB_TERM | Process.PROC_COMBINE, Process.PROC_TAB_TERM | Process.PROC_COMBINE, Process.PROC_TAB_TERM | Process.PROC_COMBINE, Process.PROC_TAB_TERM | Process.PROC_COMBINE | Process.PROC_OUT_LONG, // 5: activeSince Process.PROC_TAB_TERM | Process.PROC_COMBINE | Process.PROC_OUT_LONG, // 6: totalTime }; private final String[] mProcWakelocksName = new String[3]; private final long[] mProcWakelocksData = new long[3]; private final long[] mProcWakelocksData = new long[4]; private ISuspendControlServiceInternal mSuspendControlService = null; private byte[] mKernelWakelockBuffer = new byte[32 * 1024]; Loading @@ -74,7 +75,7 @@ public class KernelWakelockReader { * @param staleStats Existing object to update. * @return the updated data. */ public final KernelWakelockStats readKernelWakelockStats(KernelWakelockStats staleStats) { public KernelWakelockStats readKernelWakelockStats(KernelWakelockStats staleStats) { boolean useSystemSuspend = (new File(sSysClassWakeupDir)).exists(); if (useSystemSuspend) { Loading Loading @@ -180,14 +181,16 @@ public class KernelWakelockReader { */ private KernelWakelockStats getWakelockStatsFromSystemSuspend( final KernelWakelockStats staleStats) { WakeLockInfo[] wlStats = null; if (mSuspendControlService == null) { try { mSuspendControlService = waitForSuspendControlService(); } catch (ServiceNotFoundException e) { Slog.wtf(TAG, "Required service suspend_control not available", e); return null; } } WakeLockInfo[] wlStats; try { wlStats = mSuspendControlService.getWakeLockStats(); updateWakelockStats(wlStats, staleStats); Loading @@ -210,13 +213,16 @@ public class KernelWakelockReader { for (WakeLockInfo info : wlStats) { if (!staleStats.containsKey(info.name)) { staleStats.put(info.name, new KernelWakelockStats.Entry((int) info.activeCount, info.totalTime * 1000 /* ms to us */, sKernelWakelockUpdateVersion)); info.totalTime * 1000 /* ms to us */, info.isActive ? info.activeTime * 1000 : 0, sKernelWakelockUpdateVersion)); } else { KernelWakelockStats.Entry kwlStats = staleStats.get(info.name); kwlStats.mCount = (int) info.activeCount; kwlStats.count = (int) info.activeCount; // Convert milliseconds to microseconds kwlStats.mTotalTime = info.totalTime * 1000; kwlStats.mVersion = sKernelWakelockUpdateVersion; kwlStats.totalTimeUs = info.totalTime * 1000; kwlStats.activeTimeUs = info.isActive ? info.activeTime * 1000 : 0; kwlStats.version = sKernelWakelockUpdateVersion; } } Loading @@ -232,6 +238,7 @@ public class KernelWakelockReader { String name; int count; long totalTime; long activeTime; int startIndex; int endIndex; Loading Loading @@ -269,25 +276,29 @@ public class KernelWakelockReader { if (wakeup_sources) { // convert milliseconds to microseconds totalTime = wlData[2] * 1000; activeTime = wlData[2] * 1000; totalTime = wlData[3] * 1000; } else { // convert nanoseconds to microseconds with rounding. totalTime = (wlData[2] + 500) / 1000; activeTime = (wlData[2] + 500) / 1000; totalTime = (wlData[3] + 500) / 1000; } if (parsed && name.length() > 0) { if (!staleStats.containsKey(name)) { staleStats.put(name, new KernelWakelockStats.Entry(count, totalTime, sKernelWakelockUpdateVersion)); activeTime, sKernelWakelockUpdateVersion)); } else { KernelWakelockStats.Entry kwlStats = staleStats.get(name); if (kwlStats.mVersion == sKernelWakelockUpdateVersion) { kwlStats.mCount += count; kwlStats.mTotalTime += totalTime; if (kwlStats.version == sKernelWakelockUpdateVersion) { kwlStats.count += count; kwlStats.totalTimeUs += totalTime; kwlStats.activeTimeUs = activeTime; } else { kwlStats.mCount = count; kwlStats.mTotalTime = totalTime; kwlStats.mVersion = sKernelWakelockUpdateVersion; kwlStats.count = count; kwlStats.totalTimeUs = totalTime; kwlStats.activeTimeUs = activeTime; kwlStats.version = sKernelWakelockUpdateVersion; } } } else if (!parsed) { Loading Loading @@ -326,7 +337,7 @@ public class KernelWakelockReader { public KernelWakelockStats removeOldStats(final KernelWakelockStats staleStats) { Iterator<KernelWakelockStats.Entry> itr = staleStats.values().iterator(); while (itr.hasNext()) { if (itr.next().mVersion != sKernelWakelockUpdateVersion) { if (itr.next().version != sKernelWakelockUpdateVersion) { itr.remove(); } } Loading services/core/java/com/android/server/power/stats/KernelWakelockStats.java +9 −7 Original line number Diff line number Diff line Loading @@ -22,14 +22,16 @@ import java.util.HashMap; */ public class KernelWakelockStats extends HashMap<String, KernelWakelockStats.Entry> { public static class Entry { public int mCount; public long mTotalTime; public int mVersion; public int count; public long totalTimeUs; public long activeTimeUs; public int version; Entry(int count, long totalTime, int version) { mCount = count; mTotalTime = totalTime; mVersion = version; Entry(int count, long totalTimeUs, long activeTimeUs, int version) { this.count = count; this.totalTimeUs = totalTimeUs; this.activeTimeUs = activeTimeUs; this.version = version; } } Loading services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +1 −1 Original line number Diff line number Diff line Loading @@ -1733,7 +1733,7 @@ public class StatsPullAtomService extends SystemService { String name = ent.getKey(); KernelWakelockStats.Entry kws = ent.getValue(); pulledData.add(FrameworkStatsLog.buildStatsEvent( atomTag, name, kws.mCount, kws.mVersion, kws.mTotalTime)); atomTag, name, kws.count, kws.version, kws.totalTimeUs)); } return StatsManager.PULL_SUCCESS; } Loading services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsImplTest.java +51 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static android.os.BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE; import static android.os.BatteryStats.Uid.PROCESS_STATE_TOP; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; Loading Loading @@ -55,6 +56,7 @@ import com.android.internal.os.LongArrayMultiStateCounter; import com.android.internal.os.PowerProfile; import com.google.common.collect.ImmutableList; import com.google.common.truth.LongSubject; import org.junit.Before; import org.junit.Test; Loading @@ -77,6 +79,9 @@ public class BatteryStatsImplTest { private KernelSingleUidTimeReader mKernelSingleUidTimeReader; @Mock private PowerProfile mPowerProfile; @Mock private KernelWakelockReader mKernelWakelockReader; private KernelWakelockStats mKernelWakelockStats = new KernelWakelockStats(); private final MockClock mMockClock = new MockClock(); private MockBatteryStatsImpl mBatteryStatsImpl; Loading @@ -89,10 +94,13 @@ public class BatteryStatsImplTest { when(mKernelUidCpuFreqTimeReader.readFreqs(any())).thenReturn(CPU_FREQS); when(mKernelUidCpuFreqTimeReader.allUidTimesAvailable()).thenReturn(true); when(mKernelSingleUidTimeReader.singleUidCpuTimesAvailable()).thenReturn(true); when(mKernelWakelockReader.readKernelWakelockStats( any(KernelWakelockStats.class))).thenReturn(mKernelWakelockStats); mBatteryStatsImpl = new MockBatteryStatsImpl(mMockClock) .setPowerProfile(mPowerProfile) .setKernelCpuUidFreqTimeReader(mKernelUidCpuFreqTimeReader) .setKernelSingleUidTimeReader(mKernelSingleUidTimeReader); .setKernelSingleUidTimeReader(mKernelSingleUidTimeReader) .setKernelWakelockReader(mKernelWakelockReader); } @Test Loading Loading @@ -558,6 +566,48 @@ public class BatteryStatsImplTest { assertThat(wakeLock2.totalTimeHeldMs).isEqualTo(4000); // (5000-4000) + (9000-6000) } @Test public void kernelWakelocks() { mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0); mKernelWakelockStats.put("lock1", new KernelWakelockStats.Entry(42, 1000, 314, 0)); mKernelWakelockStats.put("lock2", new KernelWakelockStats.Entry(6, 2000, 0, 0)); mMockClock.realtime = 5000; // The fist call makes a snapshot of the initial state of the wakelocks mBatteryStatsImpl.updateKernelWakelocksLocked(mMockClock.realtime * 1000); assertThat(mBatteryStatsImpl.getKernelWakelockStats()).hasSize(2); mMockClock.realtime += 2000; assertThatKernelWakelockTotalTime("lock1").isEqualTo(314); // active assertThatKernelWakelockTotalTime("lock2").isEqualTo(0); // inactive mKernelWakelockStats.put("lock1", new KernelWakelockStats.Entry(43, 1100, 414, 0)); mKernelWakelockStats.put("lock2", new KernelWakelockStats.Entry(6, 2222, 0, 0)); mMockClock.realtime += 3000; // Compute delta from the initial snapshot mBatteryStatsImpl.updateKernelWakelocksLocked(mMockClock.realtime * 1000); mMockClock.realtime += 4000; assertThatKernelWakelockTotalTime("lock1").isEqualTo(414); // Wake lock not active. Expect relative total time as reported by Kernel: // 2_222 - 2_000 = 222 assertThatKernelWakelockTotalTime("lock2").isEqualTo(222); } private LongSubject assertThatKernelWakelockTotalTime(String name) { return assertWithMessage("Kernel wakelock " + name + " at " + mMockClock.realtime) .that(mBatteryStatsImpl.getKernelWakelockStats().get(name) .getTotalTimeLocked(mMockClock.realtime * 1000, 0)); } @Test public void testGetBluetoothBatteryStats() { when(mPowerProfile.getAveragePower( Loading Loading
services/core/java/com/android/server/power/stats/BatteryStatsImpl.java +40 −24 Original line number Diff line number Diff line Loading @@ -251,9 +251,10 @@ public class BatteryStatsImpl extends BatteryStats { private static final LongCounter[] ZERO_LONG_COUNTER_ARRAY = new LongCounter[]{ZERO_LONG_COUNTER}; private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader(); private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats(); @VisibleForTesting protected KernelWakelockReader mKernelWakelockReader; @VisibleForTesting protected KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader; @VisibleForTesting Loading Loading @@ -1763,6 +1764,7 @@ public class BatteryStatsImpl extends BatteryStats { mCpuUidFreqTimeReader = new KernelCpuUidFreqTimeReader(true, clock); mCpuUidActiveTimeReader = new KernelCpuUidActiveTimeReader(true, clock); mCpuUidClusterTimeReader = new KernelCpuUidClusterTimeReader(true, clock); mKernelWakelockReader = new KernelWakelockReader(); } /** Loading Loading @@ -2675,19 +2677,18 @@ public class BatteryStatsImpl extends BatteryStats { * The reported count from /proc/wakelocks when unplug() was last * called. */ int mUnpluggedReportedCount; int mBaseReportedCount; /** * The most recent reported total_time from /proc/wakelocks. */ long mCurrentReportedTotalTimeUs; /** * The reported total_time from /proc/wakelocks when unplug() was last * called. */ long mUnpluggedReportedTotalTimeUs; long mBaseReportedTotalTimeUs; /** * Whether we are currently in a discharge cycle. Loading @@ -2708,9 +2709,9 @@ public class BatteryStatsImpl extends BatteryStats { public SamplingTimer(Clock clock, TimeBase timeBase, Parcel in) { super(clock, 0, timeBase, in); mCurrentReportedCount = in.readInt(); mUnpluggedReportedCount = in.readInt(); mBaseReportedCount = in.readInt(); mCurrentReportedTotalTimeUs = in.readLong(); mUnpluggedReportedTotalTimeUs = in.readLong(); mBaseReportedTotalTimeUs = in.readLong(); mTrackingReportedValues = in.readInt() == 1; mTimeBaseRunning = timeBase.isRunning(); } Loading @@ -2736,8 +2737,8 @@ public class BatteryStatsImpl extends BatteryStats { public void endSample(long elapsedRealtimeUs) { mTotalTimeUs = computeRunTimeLocked(0 /* unused by us */, elapsedRealtimeUs); mCount = computeCurrentCountLocked(); mUnpluggedReportedTotalTimeUs = mCurrentReportedTotalTimeUs = 0; mUnpluggedReportedCount = mCurrentReportedCount = 0; mBaseReportedTotalTimeUs = mCurrentReportedTotalTimeUs = 0; mBaseReportedCount = mCurrentReportedCount = 0; mTrackingReportedValues = false; } Loading @@ -2762,10 +2763,21 @@ public class BatteryStatsImpl extends BatteryStats { * @param count total number of times the event being sampled occurred. */ public void update(long totalTimeUs, int count, long elapsedRealtimeUs) { update(totalTimeUs, 0, count, elapsedRealtimeUs); } /** * Updates the current recorded values. See {@link #update(long, int, long)} * * @param activeTimeUs Time that the currently active wake lock has been held. */ public void update(long totalTimeUs, long activeTimeUs, int count, long elapsedRealtimeUs) { if (mTimeBaseRunning && !mTrackingReportedValues) { // Updating the reported value for the first time. mUnpluggedReportedTotalTimeUs = totalTimeUs; mUnpluggedReportedCount = count; // Updating the reported value for the first time. If the wake lock is currently // active, mark the time it was acquired as the base timestamp. mBaseReportedTotalTimeUs = totalTimeUs - activeTimeUs; mBaseReportedCount = activeTimeUs == 0 ? count : count - 1; } mTrackingReportedValues = true; Loading Loading @@ -2800,8 +2812,8 @@ public class BatteryStatsImpl extends BatteryStats { public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) { super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs); if (mTrackingReportedValues) { mUnpluggedReportedTotalTimeUs = mCurrentReportedTotalTimeUs; mUnpluggedReportedCount = mCurrentReportedCount; mBaseReportedTotalTimeUs = mCurrentReportedTotalTimeUs; mBaseReportedCount = mCurrentReportedCount; } mTimeBaseRunning = true; } Loading @@ -2816,30 +2828,30 @@ public class BatteryStatsImpl extends BatteryStats { public void logState(Printer pw, String prefix) { super.logState(pw, prefix); pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount + " mUnpluggedReportedCount=" + mUnpluggedReportedCount + " mBaseReportedCount=" + mBaseReportedCount + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTimeUs + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTimeUs); + " mBaseReportedTotalTimeUs=" + mBaseReportedTotalTimeUs); } @Override protected long computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs) { return mTotalTimeUs + (mTimeBaseRunning && mTrackingReportedValues ? mCurrentReportedTotalTimeUs - mUnpluggedReportedTotalTimeUs : 0); ? mCurrentReportedTotalTimeUs - mBaseReportedTotalTimeUs : 0); } @Override protected int computeCurrentCountLocked() { return mCount + (mTimeBaseRunning && mTrackingReportedValues ? mCurrentReportedCount - mUnpluggedReportedCount : 0); ? mCurrentReportedCount - mBaseReportedCount : 0); } @Override public void writeToParcel(Parcel out, long elapsedRealtimeUs) { super.writeToParcel(out, elapsedRealtimeUs); out.writeInt(mCurrentReportedCount); out.writeInt(mUnpluggedReportedCount); out.writeInt(mBaseReportedCount); out.writeLong(mCurrentReportedTotalTimeUs); out.writeLong(mUnpluggedReportedTotalTimeUs); out.writeLong(mBaseReportedTotalTimeUs); out.writeInt(mTrackingReportedValues ? 1 : 0); } Loading @@ -2847,8 +2859,8 @@ public class BatteryStatsImpl extends BatteryStats { public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) { super.reset(detachIfReset, elapsedRealtimeUs); mTrackingReportedValues = false; mUnpluggedReportedTotalTimeUs = 0; mUnpluggedReportedCount = 0; mBaseReportedTotalTimeUs = 0; mBaseReportedCount = 0; return true; } } Loading Loading @@ -13398,6 +13410,10 @@ public class BatteryStatsImpl extends BatteryStats { * Read and distribute kernel wake lock use across apps. */ public void updateKernelWakelocksLocked(long elapsedRealtimeUs) { if (mKernelWakelockReader == null) { return; } final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats( mTmpWakelockStats); if (wakelockStats == null) { Loading @@ -13416,8 +13432,8 @@ public class BatteryStatsImpl extends BatteryStats { mKernelWakelockStats.put(name, kwlt); } kwlt.update(kws.mTotalTime, kws.mCount, elapsedRealtimeUs); kwlt.setUpdateVersion(kws.mVersion); kwlt.update(kws.totalTimeUs, kws.activeTimeUs, kws.count, elapsedRealtimeUs); kwlt.setUpdateVersion(kws.version); } int numWakelocksSetStale = 0; Loading Loading @@ -13471,7 +13487,7 @@ public class BatteryStatsImpl extends BatteryStats { Slog.d(TAG, String.format("Added entry %d and updated timer to: " + "mUnpluggedReportedTotalTimeUs %d size %d", bandwidthEntries.keyAt(i), mKernelMemoryStats.get( bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTimeUs, bandwidthEntries.keyAt(i)).mBaseReportedTotalTimeUs, mKernelMemoryStats.size())); } }
services/core/java/com/android/server/power/stats/KernelWakelockReader.java +53 −42 Original line number Diff line number Diff line Loading @@ -43,29 +43,30 @@ public class KernelWakelockReader { private static final String sSysClassWakeupDir = "/sys/class/wakeup"; private static final int[] PROC_WAKELOCKS_FORMAT = new int[]{ Process.PROC_TAB_TERM|Process.PROC_OUT_STRING| // 0: name Process.PROC_QUOTES, Process.PROC_TAB_TERM | Process.PROC_OUT_STRING // 0: name | Process.PROC_QUOTES, Process.PROC_TAB_TERM | Process.PROC_OUT_LONG, // 1: count Process.PROC_TAB_TERM, Process.PROC_TAB_TERM, Process.PROC_TAB_TERM | Process.PROC_OUT_LONG, // 3: activeSince Process.PROC_TAB_TERM, Process.PROC_TAB_TERM | Process.PROC_OUT_LONG, // 5: totalTime }; private static final int[] WAKEUP_SOURCES_FORMAT = new int[]{ Process.PROC_TAB_TERM | Process.PROC_OUT_STRING, // 0: name Process.PROC_TAB_TERM|Process.PROC_COMBINE| Process.PROC_OUT_LONG, // 1: count Process.PROC_TAB_TERM|Process.PROC_COMBINE, Process.PROC_TAB_TERM | Process.PROC_COMBINE | Process.PROC_OUT_LONG, // 1: count Process.PROC_TAB_TERM | Process.PROC_COMBINE, Process.PROC_TAB_TERM | Process.PROC_COMBINE, Process.PROC_TAB_TERM | Process.PROC_COMBINE, Process.PROC_TAB_TERM | Process.PROC_COMBINE | Process.PROC_OUT_LONG, // 5: activeSince Process.PROC_TAB_TERM | Process.PROC_COMBINE | Process.PROC_OUT_LONG, // 6: totalTime }; private final String[] mProcWakelocksName = new String[3]; private final long[] mProcWakelocksData = new long[3]; private final long[] mProcWakelocksData = new long[4]; private ISuspendControlServiceInternal mSuspendControlService = null; private byte[] mKernelWakelockBuffer = new byte[32 * 1024]; Loading @@ -74,7 +75,7 @@ public class KernelWakelockReader { * @param staleStats Existing object to update. * @return the updated data. */ public final KernelWakelockStats readKernelWakelockStats(KernelWakelockStats staleStats) { public KernelWakelockStats readKernelWakelockStats(KernelWakelockStats staleStats) { boolean useSystemSuspend = (new File(sSysClassWakeupDir)).exists(); if (useSystemSuspend) { Loading Loading @@ -180,14 +181,16 @@ public class KernelWakelockReader { */ private KernelWakelockStats getWakelockStatsFromSystemSuspend( final KernelWakelockStats staleStats) { WakeLockInfo[] wlStats = null; if (mSuspendControlService == null) { try { mSuspendControlService = waitForSuspendControlService(); } catch (ServiceNotFoundException e) { Slog.wtf(TAG, "Required service suspend_control not available", e); return null; } } WakeLockInfo[] wlStats; try { wlStats = mSuspendControlService.getWakeLockStats(); updateWakelockStats(wlStats, staleStats); Loading @@ -210,13 +213,16 @@ public class KernelWakelockReader { for (WakeLockInfo info : wlStats) { if (!staleStats.containsKey(info.name)) { staleStats.put(info.name, new KernelWakelockStats.Entry((int) info.activeCount, info.totalTime * 1000 /* ms to us */, sKernelWakelockUpdateVersion)); info.totalTime * 1000 /* ms to us */, info.isActive ? info.activeTime * 1000 : 0, sKernelWakelockUpdateVersion)); } else { KernelWakelockStats.Entry kwlStats = staleStats.get(info.name); kwlStats.mCount = (int) info.activeCount; kwlStats.count = (int) info.activeCount; // Convert milliseconds to microseconds kwlStats.mTotalTime = info.totalTime * 1000; kwlStats.mVersion = sKernelWakelockUpdateVersion; kwlStats.totalTimeUs = info.totalTime * 1000; kwlStats.activeTimeUs = info.isActive ? info.activeTime * 1000 : 0; kwlStats.version = sKernelWakelockUpdateVersion; } } Loading @@ -232,6 +238,7 @@ public class KernelWakelockReader { String name; int count; long totalTime; long activeTime; int startIndex; int endIndex; Loading Loading @@ -269,25 +276,29 @@ public class KernelWakelockReader { if (wakeup_sources) { // convert milliseconds to microseconds totalTime = wlData[2] * 1000; activeTime = wlData[2] * 1000; totalTime = wlData[3] * 1000; } else { // convert nanoseconds to microseconds with rounding. totalTime = (wlData[2] + 500) / 1000; activeTime = (wlData[2] + 500) / 1000; totalTime = (wlData[3] + 500) / 1000; } if (parsed && name.length() > 0) { if (!staleStats.containsKey(name)) { staleStats.put(name, new KernelWakelockStats.Entry(count, totalTime, sKernelWakelockUpdateVersion)); activeTime, sKernelWakelockUpdateVersion)); } else { KernelWakelockStats.Entry kwlStats = staleStats.get(name); if (kwlStats.mVersion == sKernelWakelockUpdateVersion) { kwlStats.mCount += count; kwlStats.mTotalTime += totalTime; if (kwlStats.version == sKernelWakelockUpdateVersion) { kwlStats.count += count; kwlStats.totalTimeUs += totalTime; kwlStats.activeTimeUs = activeTime; } else { kwlStats.mCount = count; kwlStats.mTotalTime = totalTime; kwlStats.mVersion = sKernelWakelockUpdateVersion; kwlStats.count = count; kwlStats.totalTimeUs = totalTime; kwlStats.activeTimeUs = activeTime; kwlStats.version = sKernelWakelockUpdateVersion; } } } else if (!parsed) { Loading Loading @@ -326,7 +337,7 @@ public class KernelWakelockReader { public KernelWakelockStats removeOldStats(final KernelWakelockStats staleStats) { Iterator<KernelWakelockStats.Entry> itr = staleStats.values().iterator(); while (itr.hasNext()) { if (itr.next().mVersion != sKernelWakelockUpdateVersion) { if (itr.next().version != sKernelWakelockUpdateVersion) { itr.remove(); } } Loading
services/core/java/com/android/server/power/stats/KernelWakelockStats.java +9 −7 Original line number Diff line number Diff line Loading @@ -22,14 +22,16 @@ import java.util.HashMap; */ public class KernelWakelockStats extends HashMap<String, KernelWakelockStats.Entry> { public static class Entry { public int mCount; public long mTotalTime; public int mVersion; public int count; public long totalTimeUs; public long activeTimeUs; public int version; Entry(int count, long totalTime, int version) { mCount = count; mTotalTime = totalTime; mVersion = version; Entry(int count, long totalTimeUs, long activeTimeUs, int version) { this.count = count; this.totalTimeUs = totalTimeUs; this.activeTimeUs = activeTimeUs; this.version = version; } } Loading
services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +1 −1 Original line number Diff line number Diff line Loading @@ -1733,7 +1733,7 @@ public class StatsPullAtomService extends SystemService { String name = ent.getKey(); KernelWakelockStats.Entry kws = ent.getValue(); pulledData.add(FrameworkStatsLog.buildStatsEvent( atomTag, name, kws.mCount, kws.mVersion, kws.mTotalTime)); atomTag, name, kws.count, kws.version, kws.totalTimeUs)); } return StatsManager.PULL_SUCCESS; } Loading
services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsImplTest.java +51 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static android.os.BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE; import static android.os.BatteryStats.Uid.PROCESS_STATE_TOP; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; Loading Loading @@ -55,6 +56,7 @@ import com.android.internal.os.LongArrayMultiStateCounter; import com.android.internal.os.PowerProfile; import com.google.common.collect.ImmutableList; import com.google.common.truth.LongSubject; import org.junit.Before; import org.junit.Test; Loading @@ -77,6 +79,9 @@ public class BatteryStatsImplTest { private KernelSingleUidTimeReader mKernelSingleUidTimeReader; @Mock private PowerProfile mPowerProfile; @Mock private KernelWakelockReader mKernelWakelockReader; private KernelWakelockStats mKernelWakelockStats = new KernelWakelockStats(); private final MockClock mMockClock = new MockClock(); private MockBatteryStatsImpl mBatteryStatsImpl; Loading @@ -89,10 +94,13 @@ public class BatteryStatsImplTest { when(mKernelUidCpuFreqTimeReader.readFreqs(any())).thenReturn(CPU_FREQS); when(mKernelUidCpuFreqTimeReader.allUidTimesAvailable()).thenReturn(true); when(mKernelSingleUidTimeReader.singleUidCpuTimesAvailable()).thenReturn(true); when(mKernelWakelockReader.readKernelWakelockStats( any(KernelWakelockStats.class))).thenReturn(mKernelWakelockStats); mBatteryStatsImpl = new MockBatteryStatsImpl(mMockClock) .setPowerProfile(mPowerProfile) .setKernelCpuUidFreqTimeReader(mKernelUidCpuFreqTimeReader) .setKernelSingleUidTimeReader(mKernelSingleUidTimeReader); .setKernelSingleUidTimeReader(mKernelSingleUidTimeReader) .setKernelWakelockReader(mKernelWakelockReader); } @Test Loading Loading @@ -558,6 +566,48 @@ public class BatteryStatsImplTest { assertThat(wakeLock2.totalTimeHeldMs).isEqualTo(4000); // (5000-4000) + (9000-6000) } @Test public void kernelWakelocks() { mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0); mKernelWakelockStats.put("lock1", new KernelWakelockStats.Entry(42, 1000, 314, 0)); mKernelWakelockStats.put("lock2", new KernelWakelockStats.Entry(6, 2000, 0, 0)); mMockClock.realtime = 5000; // The fist call makes a snapshot of the initial state of the wakelocks mBatteryStatsImpl.updateKernelWakelocksLocked(mMockClock.realtime * 1000); assertThat(mBatteryStatsImpl.getKernelWakelockStats()).hasSize(2); mMockClock.realtime += 2000; assertThatKernelWakelockTotalTime("lock1").isEqualTo(314); // active assertThatKernelWakelockTotalTime("lock2").isEqualTo(0); // inactive mKernelWakelockStats.put("lock1", new KernelWakelockStats.Entry(43, 1100, 414, 0)); mKernelWakelockStats.put("lock2", new KernelWakelockStats.Entry(6, 2222, 0, 0)); mMockClock.realtime += 3000; // Compute delta from the initial snapshot mBatteryStatsImpl.updateKernelWakelocksLocked(mMockClock.realtime * 1000); mMockClock.realtime += 4000; assertThatKernelWakelockTotalTime("lock1").isEqualTo(414); // Wake lock not active. Expect relative total time as reported by Kernel: // 2_222 - 2_000 = 222 assertThatKernelWakelockTotalTime("lock2").isEqualTo(222); } private LongSubject assertThatKernelWakelockTotalTime(String name) { return assertWithMessage("Kernel wakelock " + name + " at " + mMockClock.realtime) .that(mBatteryStatsImpl.getKernelWakelockStats().get(name) .getTotalTimeLocked(mMockClock.realtime * 1000, 0)); } @Test public void testGetBluetoothBatteryStats() { when(mPowerProfile.getAveragePower( Loading