diff options
| author | 2024-08-26 18:30:54 +0000 | |
|---|---|---|
| committer | 2024-08-26 18:30:54 +0000 | |
| commit | b844f252c2886ffff829e58e49d54a8e3119ea0c (patch) | |
| tree | 1864766b7456d3f8a658d0623e465d5cad2a8cbf | |
| parent | dd30a976287694d271d1d3d784a1e5399b4183ee (diff) | |
| parent | 6f1900c55af0454835b85dac93aea9bf00876e3e (diff) | |
Merge "Fix GNSS power stats processor by properly initializing state" into main
5 files changed, 173 insertions, 57 deletions
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index c7751e3e5cea..c4d12d4336c6 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -1997,6 +1997,8 @@ public abstract class BatteryStats { STATE2_VIDEO_ON_FLAG | STATE2_FLASHLIGHT_FLAG | STATE2_CAMERA_FLAG | STATE2_GPS_SIGNAL_QUALITY_MASK; + public static final int GNSS_SIGNAL_QUALITY_NONE = 2; + @UnsupportedAppUsage public int states2; @@ -2220,7 +2222,7 @@ public abstract class BatteryStats { modemRailChargeMah = 0; wifiRailChargeMah = 0; states = 0; - states2 = 0; + states2 = GNSS_SIGNAL_QUALITY_NONE << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT; wakelockTag = null; wakeReasonTag = null; eventCode = EVENT_NONE; diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java index d04b73347c80..b45651d7aafc 100644 --- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java +++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java @@ -1167,7 +1167,6 @@ public class BatteryStatsImpl extends BatteryStats { private static final int USB_DATA_CONNECTED = 2; int mUsbDataState = USB_DATA_UNKNOWN; - private static final int GPS_SIGNAL_QUALITY_NONE = 2; int mGpsSignalQualityBin = -1; final StopwatchTimer[] mGpsSignalQualityTimer = new StopwatchTimer[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS]; @@ -5528,7 +5527,7 @@ public class BatteryStatsImpl extends BatteryStats { mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.STATE_GPS_ON_FLAG, uid, "gnss"); mHistory.recordGpsSignalQualityEvent(elapsedRealtimeMs, uptimeMs, - GPS_SIGNAL_QUALITY_NONE); + HistoryItem.GNSS_SIGNAL_QUALITY_NONE); stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs); mGpsSignalQualityBin = -1; if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_GNSS)) { diff --git a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsProcessor.java index 393fa39cdff6..03df46aa1701 100644 --- a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsProcessor.java +++ b/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsProcessor.java @@ -115,6 +115,12 @@ abstract class BinaryStatePowerStatsProcessor extends PowerStatsProcessor { mInitiatingUid = mUidResolver.mapUid(item.eventTag.uid); } } else { + if (mInitiatingUid == Process.INVALID_UID) { + if (item.eventCode == (BatteryStats.HistoryItem.EVENT_STATE_CHANGE + | BatteryStats.HistoryItem.EVENT_FLAG_FINISH)) { + mInitiatingUid = mUidResolver.mapUid(item.eventTag.uid); + } + } recordUsageDuration(mPowerStats, mInitiatingUid, item.time); mInitiatingUid = Process.INVALID_UID; if (!mEnergyConsumerSupported) { diff --git a/services/core/java/com/android/server/power/stats/GnssPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/GnssPowerStatsProcessor.java index 572bde9b9266..0b287109cfa6 100644 --- a/services/core/java/com/android/server/power/stats/GnssPowerStatsProcessor.java +++ b/services/core/java/com/android/server/power/stats/GnssPowerStatsProcessor.java @@ -27,15 +27,15 @@ import com.android.internal.os.PowerStats; import java.util.Arrays; public class GnssPowerStatsProcessor extends BinaryStatePowerStatsProcessor { - private int mGnssSignalLevel = GnssSignalQuality.GNSS_SIGNAL_QUALITY_UNKNOWN; - private long mGnssSignalLevelTimestamp; - private final long[] mGnssSignalDurations = - new long[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS]; private static final GnssPowerStatsLayout sStatsLayout = new GnssPowerStatsLayout(); private final UsageBasedPowerEstimator[] mSignalLevelEstimators = new UsageBasedPowerEstimator[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS]; private final boolean mUseSignalLevelEstimators; private long[] mTmpDeviceStatsArray; + private int mGnssSignalLevel; + private long mGnssSignalLevelTimestamp; + private final long[] mGnssSignalDurations = + new long[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS]; public GnssPowerStatsProcessor(PowerProfile powerProfile, PowerStatsUidResolver uidResolver) { super(BatteryConsumer.POWER_COMPONENT_GNSS, uidResolver, @@ -55,20 +55,33 @@ public class GnssPowerStatsProcessor extends BinaryStatePowerStatsProcessor { } @Override - protected @BinaryState int getBinaryState(BatteryStats.HistoryItem item) { - if ((item.states & BatteryStats.HistoryItem.STATE_GPS_ON_FLAG) == 0) { - mGnssSignalLevel = GnssSignalQuality.GNSS_SIGNAL_QUALITY_UNKNOWN; - return STATE_OFF; - } + void start(PowerComponentAggregatedPowerStats stats, long timestampMs) { + super.start(stats, timestampMs); - noteGnssSignalLevel(item); - return STATE_ON; + mGnssSignalLevelTimestamp = timestampMs; + mGnssSignalLevel = GnssSignalQuality.GNSS_SIGNAL_QUALITY_UNKNOWN; + Arrays.fill(mGnssSignalDurations, 0); } - private void noteGnssSignalLevel(BatteryStats.HistoryItem item) { - int signalLevel = (item.states2 & BatteryStats.HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK) - >> BatteryStats.HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT; - if (signalLevel >= GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS) { + @Override + protected @BinaryState int getBinaryState(BatteryStats.HistoryItem item) { + return (item.states & BatteryStats.HistoryItem.STATE_GPS_ON_FLAG) != 0 + ? STATE_ON : STATE_OFF; + } + + @Override + void noteStateChange(PowerComponentAggregatedPowerStats stats, BatteryStats.HistoryItem item) { + super.noteStateChange(stats, item); + + int signalLevel; + if ((item.states & BatteryStats.HistoryItem.STATE_GPS_ON_FLAG) != 0) { + signalLevel = (item.states2 & BatteryStats.HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK) + >> BatteryStats.HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT; + if (signalLevel >= GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS) { + // Default GNSS signal quality to GOOD for the purposes of power attribution + signalLevel = GnssSignalQuality.GNSS_SIGNAL_QUALITY_GOOD; + } + } else { signalLevel = GnssSignalQuality.GNSS_SIGNAL_QUALITY_UNKNOWN; } if (signalLevel == mGnssSignalLevel) { diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/GnssPowerStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/GnssPowerStatsTest.java index 127ab8a6e549..f22279a88a50 100644 --- a/services/tests/powerstatstests/src/com/android/server/power/stats/GnssPowerStatsTest.java +++ b/services/tests/powerstatstests/src/com/android/server/power/stats/GnssPowerStatsTest.java @@ -74,6 +74,7 @@ public class GnssPowerStatsTest { private static final int APP_UID2 = Process.FIRST_APPLICATION_UID + 101; private static final int VOLTAGE_MV = 3500; private static final int ENERGY_CONSUMER_ID = 777; + private static final long START_TIME = 10_000_000_000L; private final PowerStatsUidResolver mUidResolver = new PowerStatsUidResolver(); @Mock @@ -113,11 +114,13 @@ public class GnssPowerStatsTest { }; private MonotonicClock mMonotonicClock; + private final BatteryStats.HistoryItem mHistoryItem = new BatteryStats.HistoryItem(); @Before public void setup() { MockitoAnnotations.initMocks(this); - mMonotonicClock = new MonotonicClock(0, mStatsRule.getMockClock()); + mMonotonicClock = new MonotonicClock(START_TIME, mStatsRule.getMockClock()); + mHistoryItem.clear(); } @Test @@ -129,7 +132,6 @@ public class GnssPowerStatsTest { PowerComponentAggregatedPowerStats stats = createAggregatedPowerStats( () -> new GnssPowerStatsProcessor(mStatsRule.getPowerProfile(), mUidResolver)); - stats.start(0); GnssPowerStatsCollector collector = new GnssPowerStatsCollector(mInjector); collector.addConsumer( @@ -142,9 +144,11 @@ public class GnssPowerStatsTest { stats.noteStateChange(buildHistoryItem(0, true, APP_UID1)); // Turn the screen off after 2.5 seconds - stats.setState(STATE_SCREEN, SCREEN_STATE_OTHER, 2500); - stats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_BACKGROUND, 2500); - stats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_FOREGROUND_SERVICE, 5000); + stats.setState(STATE_SCREEN, SCREEN_STATE_OTHER, START_TIME + 2500); + stats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_BACKGROUND, + START_TIME + 2500); + stats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_FOREGROUND_SERVICE, + START_TIME + 5000); stats.noteStateChange(buildHistoryItem(6000, false, APP_UID1)); @@ -158,7 +162,87 @@ public class GnssPowerStatsTest { mStatsRule.setTime(11_000, 11_000); collector.collectAndDeliverStats(); - stats.finish(11_000); + stats.finish(START_TIME + 11_000); + + PowerStats.Descriptor descriptor = stats.getPowerStatsDescriptor(); + BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout(); + statsLayout.fromExtras(descriptor.extras); + + // scr-on, GNSS-good: 2500 * 100 = 250000 mA-ms = 0.06944 mAh + // scr-off GNSS=good: 4500 * 100 = 0.12500 mAh + // scr-off GNSS=poor: 3000 * 1000 = 0.83333 mAh + // scr-off GNSS-on: 0.12500 + 0.83333 = 0.95833 mAh + long[] deviceStats = new long[descriptor.statsArrayLength]; + stats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_ON)); + assertThat(statsLayout.getDevicePowerEstimate(deviceStats)) + .isWithin(PRECISION).of(0.06944); + + stats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_OTHER)); + assertThat(statsLayout.getDevicePowerEstimate(deviceStats)) + .isWithin(PRECISION).of(0.12500 + 0.83333); + + // UID1 = + // scr-on FG: 2500 -> 0.06944 mAh + // scr-off BG: 2500/7500 * 0.95833 = 0.31944 mAh + // scr-off FGS: 1000/7500 * 0.95833 = 0.12777 mAh + long[] uidStats = new long[descriptor.uidStatsArrayLength]; + stats.getUidStats(uidStats, APP_UID1, + states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_FOREGROUND)); + assertThat(statsLayout.getUidPowerEstimate(uidStats)) + .isWithin(PRECISION).of(0.06944); + + stats.getUidStats(uidStats, APP_UID1, + states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_BACKGROUND)); + assertThat(statsLayout.getUidPowerEstimate(uidStats)) + .isWithin(PRECISION).of(0.31944); + + stats.getUidStats(uidStats, APP_UID1, + states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_FOREGROUND_SERVICE)); + assertThat(statsLayout.getUidPowerEstimate(uidStats)) + .isWithin(PRECISION).of(0.12777); + + // UID2 = + // scr-off cached: 4000/7500 * 0.95833 = 0.51111 mAh + stats.getUidStats(uidStats, APP_UID2, + states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_CACHED)); + assertThat(statsLayout.getUidPowerEstimate(uidStats)) + .isWithin(PRECISION).of(0.51111); + + stats.getUidStats(uidStats, APP_UID2, + states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED)); + assertThat(statsLayout.getUidPowerEstimate(uidStats)) + .isWithin(PRECISION).of(0); + } + + @Test + public void initialStateGnssOn() { + // ODPM unsupported + when(mConsumedEnergyRetriever + .getEnergyConsumerIds(eq((int) EnergyConsumerType.GNSS), any())) + .thenReturn(new int[0]); + + PowerComponentAggregatedPowerStats stats = createAggregatedPowerStats( + () -> new GnssPowerStatsProcessor(mStatsRule.getPowerProfile(), mUidResolver)); + + stats.noteStateChange(buildHistoryItemInitialStateGpsOn(0)); + + // Turn the screen off after 2.5 seconds + stats.setState(STATE_SCREEN, SCREEN_STATE_OTHER, START_TIME + 2500); + stats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_BACKGROUND, + START_TIME + 2500); + stats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_FOREGROUND_SERVICE, + START_TIME + 5000); + + stats.noteStateChange(buildHistoryItem(6000, false, APP_UID1)); + + stats.noteStateChange(buildHistoryItem(7000, true, APP_UID2)); + stats.noteStateChange(buildHistoryItem(7000, + GnssSignalQuality.GNSS_SIGNAL_QUALITY_GOOD)); + stats.noteStateChange(buildHistoryItem(8000, + GnssSignalQuality.GNSS_SIGNAL_QUALITY_POOR)); + mStatsRule.setTime(11_000, 11_000); + + stats.finish(START_TIME + 11_000); PowerStats.Descriptor descriptor = stats.getPowerStatsDescriptor(); BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout(); @@ -224,8 +308,6 @@ public class GnssPowerStatsTest { powerStats -> stats.addPowerStats(powerStats, mMonotonicClock.monotonicTime())); collector.setEnabled(true); - stats.start(0); - // Establish a baseline when(mConsumedEnergyRetriever.getConsumedEnergy(new int[]{ENERGY_CONSUMER_ID})) .thenReturn(createEnergyConsumerResults(ENERGY_CONSUMER_ID, 10000)); @@ -234,9 +316,11 @@ public class GnssPowerStatsTest { stats.noteStateChange(buildHistoryItem(0, true, APP_UID1)); // Turn the screen off after 2.5 seconds - stats.setState(STATE_SCREEN, SCREEN_STATE_OTHER, 2500); - stats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_BACKGROUND, 2500); - stats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_FOREGROUND_SERVICE, 5000); + stats.setState(STATE_SCREEN, SCREEN_STATE_OTHER, START_TIME + 2500); + stats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_BACKGROUND, + START_TIME + 2500); + stats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_FOREGROUND_SERVICE, + START_TIME + 5000); stats.noteStateChange(buildHistoryItem(6000, false, APP_UID1)); @@ -245,16 +329,14 @@ public class GnssPowerStatsTest { collector.collectAndDeliverStats(); stats.noteStateChange(buildHistoryItem(7000, true, APP_UID2)); - stats.noteStateChange(buildHistoryItem(7000, - GnssSignalQuality.GNSS_SIGNAL_QUALITY_GOOD)); - stats.noteStateChange(buildHistoryItem(8000, - GnssSignalQuality.GNSS_SIGNAL_QUALITY_POOR)); + stats.noteStateChange(buildHistoryItem(7000, GnssSignalQuality.GNSS_SIGNAL_QUALITY_GOOD)); + stats.noteStateChange(buildHistoryItem(8000, GnssSignalQuality.GNSS_SIGNAL_QUALITY_POOR)); mStatsRule.setTime(11_000, 11_000); when(mConsumedEnergyRetriever.getConsumedEnergy(new int[]{ENERGY_CONSUMER_ID})) .thenReturn(createEnergyConsumerResults(ENERGY_CONSUMER_ID, 3_610_000)); collector.collectAndDeliverStats(); - stats.finish(11_000); + stats.finish(START_TIME + 11_000); PowerStats.Descriptor descriptor = stats.getPowerStatsDescriptor(); BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout(); @@ -313,33 +395,45 @@ public class GnssPowerStatsTest { .isWithin(PRECISION).of(0); } - private BatteryStats.HistoryItem buildHistoryItem(int timestamp, boolean stateOn, + private BatteryStats.HistoryItem buildHistoryItemInitialStateGpsOn(long timestamp) { + mStatsRule.setTime(timestamp, timestamp); + mHistoryItem.time = mMonotonicClock.monotonicTime(); + mHistoryItem.states = BatteryStats.HistoryItem.STATE_GPS_ON_FLAG; + setGnssSignalLevel(BatteryStats.HistoryItem.GNSS_SIGNAL_QUALITY_NONE); + return mHistoryItem; + } + + private BatteryStats.HistoryItem buildHistoryItem(long timestamp, boolean stateOn, int uid) { mStatsRule.setTime(timestamp, timestamp); - BatteryStats.HistoryItem historyItem = new BatteryStats.HistoryItem(); - historyItem.time = mMonotonicClock.monotonicTime(); - historyItem.states = stateOn ? BatteryStats.HistoryItem.STATE_GPS_ON_FLAG : 0; + mHistoryItem.time = mMonotonicClock.monotonicTime(); + mHistoryItem.states = stateOn ? BatteryStats.HistoryItem.STATE_GPS_ON_FLAG : 0; if (stateOn) { - historyItem.eventCode = BatteryStats.HistoryItem.EVENT_STATE_CHANGE + mHistoryItem.eventCode = BatteryStats.HistoryItem.EVENT_STATE_CHANGE | BatteryStats.HistoryItem.EVENT_FLAG_START; } else { - historyItem.eventCode = BatteryStats.HistoryItem.EVENT_STATE_CHANGE + mHistoryItem.eventCode = BatteryStats.HistoryItem.EVENT_STATE_CHANGE | BatteryStats.HistoryItem.EVENT_FLAG_FINISH; } - historyItem.eventTag = historyItem.localEventTag; - historyItem.eventTag.uid = uid; - historyItem.eventTag.string = "gnss"; - return historyItem; + mHistoryItem.eventTag = mHistoryItem.localEventTag; + mHistoryItem.eventTag.uid = uid; + mHistoryItem.eventTag.string = "gnss"; + return mHistoryItem; } - private BatteryStats.HistoryItem buildHistoryItem(int timestamp, int signalLevel) { + private BatteryStats.HistoryItem buildHistoryItem(long timestamp, int signalLevel) { mStatsRule.setTime(timestamp, timestamp); - BatteryStats.HistoryItem historyItem = new BatteryStats.HistoryItem(); - historyItem.time = mMonotonicClock.monotonicTime(); - historyItem.states = BatteryStats.HistoryItem.STATE_GPS_ON_FLAG; - historyItem.states2 = - signalLevel << BatteryStats.HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT; - return historyItem; + mHistoryItem.time = mMonotonicClock.monotonicTime(); + setGnssSignalLevel(signalLevel); + mHistoryItem.eventCode = BatteryStats.HistoryItem.EVENT_NONE; + mHistoryItem.eventTag = null; + return mHistoryItem; + } + + private void setGnssSignalLevel(int signalLevel) { + mHistoryItem.states2 = + (mHistoryItem.states2 & ~BatteryStats.HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK) + | signalLevel << BatteryStats.HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT; } private int[] states(int... states) { @@ -362,12 +456,14 @@ public class GnssPowerStatsTest { AggregatedPowerStats aggregatedPowerStats = new AggregatedPowerStats(config); PowerComponentAggregatedPowerStats powerComponentStats = aggregatedPowerStats.getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_GNSS); - powerComponentStats.start(0); - - powerComponentStats.setState(STATE_POWER, POWER_STATE_OTHER, 0); - powerComponentStats.setState(STATE_SCREEN, SCREEN_STATE_ON, 0); - powerComponentStats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_FOREGROUND, 0); - powerComponentStats.setUidState(APP_UID2, STATE_PROCESS_STATE, PROCESS_STATE_CACHED, 0); + powerComponentStats.start(START_TIME); + + powerComponentStats.setState(STATE_POWER, POWER_STATE_OTHER, START_TIME); + powerComponentStats.setState(STATE_SCREEN, SCREEN_STATE_ON, START_TIME); + powerComponentStats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_FOREGROUND, + START_TIME); + powerComponentStats.setUidState(APP_UID2, STATE_PROCESS_STATE, PROCESS_STATE_CACHED, + START_TIME); return powerComponentStats; } |