summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/power/stats/AggregatedPowerStats.java81
-rw-r--r--services/core/java/com/android/server/power/stats/PowerStatsAggregator.java7
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java33
3 files changed, 105 insertions, 16 deletions
diff --git a/services/core/java/com/android/server/power/stats/AggregatedPowerStats.java b/services/core/java/com/android/server/power/stats/AggregatedPowerStats.java
index 65d7f1cfc60f..288912a2b89f 100644
--- a/services/core/java/com/android/server/power/stats/AggregatedPowerStats.java
+++ b/services/core/java/com/android/server/power/stats/AggregatedPowerStats.java
@@ -16,16 +16,21 @@
package com.android.server.power.stats;
+import android.annotation.CurrentTimeMillisLong;
import android.annotation.DurationMillisLong;
import android.os.UserHandle;
import android.text.format.DateFormat;
import android.util.IndentingPrintWriter;
+import android.util.Slog;
+import android.util.TimeUtils;
import com.android.internal.os.PowerStats;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
/**
@@ -33,10 +38,16 @@ import java.util.Set;
* etc) covering a specific period of power usage history.
*/
class AggregatedPowerStats {
+ private static final String TAG = "AggregatedPowerStats";
+ private static final int MAX_CLOCK_UPDATES = 100;
private final PowerComponentAggregatedPowerStats[] mPowerComponentStats;
- // See MonotonicClock
- private long mStartTime;
+ static class ClockUpdate {
+ public long monotonicTime;
+ @CurrentTimeMillisLong public long currentTime;
+ }
+
+ private final List<ClockUpdate> mClockUpdates = new ArrayList<>();
@DurationMillisLong
private long mDurationMs;
@@ -46,17 +57,39 @@ class AggregatedPowerStats {
}
/**
- * @param startTime monotonic time
+ * Records a mapping of monotonic time to wall-clock time. Since wall-clock time can change,
+ * there may be multiple clock updates in one set of aggregated stats.
+ *
+ * @param monotonicTime monotonic time in milliseconds, see
+ * {@link com.android.internal.os.MonotonicClock}
+ * @param currentTime current time in milliseconds, see {@link System#currentTimeMillis()}
*/
- void setStartTime(long startTime) {
- mStartTime = startTime;
+ void addClockUpdate(long monotonicTime, @CurrentTimeMillisLong long currentTime) {
+ ClockUpdate clockUpdate = new ClockUpdate();
+ clockUpdate.monotonicTime = monotonicTime;
+ clockUpdate.currentTime = currentTime;
+ if (mClockUpdates.size() < MAX_CLOCK_UPDATES) {
+ mClockUpdates.add(clockUpdate);
+ } else {
+ Slog.i(TAG, "Too many clock updates. Replacing the previous update with "
+ + DateFormat.format("yyyy-MM-dd-HH-mm-ss", currentTime));
+ mClockUpdates.set(mClockUpdates.size() - 1, clockUpdate);
+ }
}
/**
* Start time according to {@link com.android.internal.os.MonotonicClock}
*/
- public long getStartTime() {
- return mStartTime;
+ long getStartTime() {
+ if (mClockUpdates.isEmpty()) {
+ return 0;
+ } else {
+ return mClockUpdates.get(0).monotonicTime;
+ }
+ }
+
+ List<ClockUpdate> getClockUpdates() {
+ return mClockUpdates;
}
void setDuration(long durationMs) {
@@ -110,7 +143,7 @@ class AggregatedPowerStats {
}
void reset() {
- mStartTime = 0;
+ mClockUpdates.clear();
mDurationMs = 0;
for (PowerComponentAggregatedPowerStats stats : mPowerComponentStats) {
stats.reset();
@@ -119,11 +152,33 @@ class AggregatedPowerStats {
void dump(PrintWriter pw) {
IndentingPrintWriter ipw = new IndentingPrintWriter(pw);
- ipw.print("Start time: ");
- ipw.print(DateFormat.format("yyyy-MM-dd-HH-mm-ss", mStartTime));
- ipw.print(" duration: ");
- ipw.print(mDurationMs);
- ipw.println();
+ StringBuilder sb = new StringBuilder();
+ long baseTime = 0;
+ for (int i = 0; i < mClockUpdates.size(); i++) {
+ ClockUpdate clockUpdate = mClockUpdates.get(i);
+ sb.setLength(0);
+ if (i == 0) {
+ baseTime = clockUpdate.monotonicTime;
+ sb.append("Start time: ")
+ .append(DateFormat.format("yyyy-MM-dd-HH-mm-ss", clockUpdate.currentTime))
+ .append(" (")
+ .append(baseTime)
+ .append(") duration: ")
+ .append(mDurationMs);
+ ipw.println(sb);
+ } else {
+ sb.setLength(0);
+ sb.append("Clock update: ");
+ TimeUtils.formatDuration(
+ clockUpdate.monotonicTime - baseTime, sb,
+ TimeUtils.HUNDRED_DAY_FIELD_LEN + 3);
+ sb.append(" ").append(
+ DateFormat.format("yyyy-MM-dd-HH-mm-ss", clockUpdate.currentTime));
+ ipw.increaseIndent();
+ ipw.println(sb);
+ ipw.decreaseIndent();
+ }
+ }
ipw.println("Device");
ipw.increaseIndent();
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java b/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java
index 5e47da3992a5..cfb081dca70f 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java
@@ -96,8 +96,11 @@ class PowerStatsAggregator {
BatteryStats.HistoryItem item = iterator.next();
if (baseTime < 0) {
- mStats.setStartTime(item.time);
+ mStats.addClockUpdate(item.time, item.currentTime);
baseTime = item.time;
+ } else if (item.cmd == BatteryStats.HistoryItem.CMD_CURRENT_TIME
+ || item.cmd == BatteryStats.HistoryItem.CMD_RESET) {
+ mStats.addClockUpdate(item.time, item.currentTime);
}
lastTime = item.time;
@@ -128,7 +131,7 @@ class PowerStatsAggregator {
mStats.setDuration(lastTime - baseTime);
consumer.accept(mStats);
mStats.reset();
- mStats.setStartTime(item.time);
+ mStats.addClockUpdate(item.time, item.currentTime);
baseTime = lastTime = item.time;
}
mStats.addPowerStats(item.powerStats, item.time);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java
index 45f30a34260d..5bb38858ab7c 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java
@@ -24,7 +24,9 @@ import static org.mockito.Mockito.mock;
import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.os.PersistableBundle;
+import android.text.format.DateFormat;
+import androidx.annotation.NonNull;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -37,6 +39,9 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import java.text.ParseException;
+import java.util.Calendar;
+import java.util.List;
+import java.util.TimeZone;
@RunWith(AndroidJUnit4.class)
@SmallTest
@@ -71,6 +76,8 @@ public class PowerStatsAggregatorTest {
@Test
public void stateUpdates() {
+ mClock.currentTime = 1222156800000L; // An important date in world history
+
mHistory.forceRecordAllHistory();
mHistory.recordBatteryState(mClock.realtime, mClock.uptime, 10, /* plugged */ true);
mHistory.recordStateStartEvent(mClock.realtime, mClock.uptime,
@@ -97,7 +104,12 @@ public class PowerStatsAggregatorTest {
mHistory.recordProcessStateChange(mClock.realtime, mClock.uptime, TEST_UID,
BatteryConsumer.PROCESS_STATE_BACKGROUND);
- advance(3000);
+ advance(1000);
+
+ mClock.currentTime += 60 * 60 * 1000; // one hour
+ mHistory.recordCurrentTimeChange(mClock.realtime, mClock.uptime, mClock.currentTime);
+
+ advance(2000);
powerStats.stats = new long[]{20000};
powerStats.uidStats.put(TEST_UID, new long[]{4444});
@@ -106,6 +118,18 @@ public class PowerStatsAggregatorTest {
mAggregator.aggregateBatteryStats(0, 0, stats -> {
assertThat(mAggregatedStatsCount++).isEqualTo(0);
assertThat(stats.getStartTime()).isEqualTo(START_TIME);
+
+ List<AggregatedPowerStats.ClockUpdate> clockUpdates = stats.getClockUpdates();
+ assertThat(clockUpdates).hasSize(2);
+
+ AggregatedPowerStats.ClockUpdate clockUpdate0 = clockUpdates.get(0);
+ assertThat(clockUpdate0.monotonicTime).isEqualTo(1234);
+ assertThat(formatDateTime(clockUpdate0.currentTime)).isEqualTo("2008-09-23 08:00:00");
+
+ AggregatedPowerStats.ClockUpdate clockUpdate1 = clockUpdates.get(1);
+ assertThat(clockUpdate1.monotonicTime).isEqualTo(1234 + 3000);
+ assertThat(formatDateTime(clockUpdate1.currentTime)).isEqualTo("2008-09-23 09:00:03");
+
assertThat(stats.getDuration()).isEqualTo(5000);
long[] values = new long[1];
@@ -148,6 +172,13 @@ public class PowerStatsAggregatorTest {
});
}
+ @NonNull
+ private static CharSequence formatDateTime(long timeInMillis) {
+ Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+ cal.setTimeInMillis(timeInMillis);
+ return DateFormat.format("yyyy-MM-dd hh:mm:ss", cal);
+ }
+
@Test
public void incompatiblePowerStats() {
mHistory.forceRecordAllHistory();