From 0870ea92175d2509ab19a23595efdb5f55c36dfc Mon Sep 17 00:00:00 2001 From: Xin Guan Date: Fri, 23 Jun 2023 14:23:13 +0000 Subject: [PATCH] Ignore the first modem activity when system_server start Don't count up the first reported modem activity as the modem power stats updates to battery stats. Bug: 283337636 Test: atest BatteryStatsNoteTest MobileRadioPowerCalculatorTest Change-Id: I5894eb70b9b014bea831b5ea3d00e5405eae59ac --- .../server/power/stats/BatteryStatsImpl.java | 3 +- .../power/stats/BatteryStatsNoteTest.java | 142 ++++++++++++++++++ .../stats/MobileRadioPowerCalculatorTest.java | 24 +++ 3 files changed, 168 insertions(+), 1 deletion(-) 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 7076b4745a97e..32104f68c0914 100644 --- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java +++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java @@ -12159,7 +12159,8 @@ public class BatteryStatsImpl extends BatteryStats { if (DEBUG_ENERGY) { Slog.d(TAG, "Updating mobile radio stats with " + activityInfo); } - ModemActivityInfo deltaInfo = mLastModemActivityInfo == null ? activityInfo + ModemActivityInfo deltaInfo = mLastModemActivityInfo == null + ? (activityInfo == null ? null : activityInfo.getDelta(activityInfo)) : mLastModemActivityInfo.getDelta(activityInfo); mLastModemActivityInfo = activityInfo; diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsNoteTest.java b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsNoteTest.java index e6454e4ce0400..090c8c8c2c3c2 100644 --- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsNoteTest.java +++ b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsNoteTest.java @@ -1456,6 +1456,148 @@ public class BatteryStatsNoteTest extends TestCase { expectedTxDurationsMs, bi, state.currentTimeMs); } + @SmallTest + public void testGetPerStateActiveRadioDurationMs_initialModemActivity() { + final MockClock clock = new MockClock(); // holds realtime and uptime in ms + final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clock); + bi.setPowerProfile(mock(PowerProfile.class)); + + final int ratCount = RADIO_ACCESS_TECHNOLOGY_COUNT; + final int frequencyCount = ServiceState.FREQUENCY_RANGE_MMWAVE + 1; + final int txLevelCount = CellSignalStrength.getNumSignalStrengthLevels(); + + List specificInfoList = new ArrayList(); + + final long[][][] expectedDurationsMs = new long[ratCount][frequencyCount][txLevelCount]; + final long[][] expectedRxDurationsMs = new long[ratCount][frequencyCount]; + final long[][][] expectedTxDurationsMs = new long[ratCount][frequencyCount][txLevelCount]; + for (int rat = 0; rat < ratCount; rat++) { + for (int freq = 0; freq < frequencyCount; freq++) { + if (rat == RADIO_ACCESS_TECHNOLOGY_NR + || freq == ServiceState.FREQUENCY_RANGE_UNKNOWN) { + // Only the NR RAT should have per frequency data. + expectedRxDurationsMs[rat][freq] = 0; + } else { + expectedRxDurationsMs[rat][freq] = POWER_DATA_UNAVAILABLE; + } + for (int txLvl = 0; txLvl < txLevelCount; txLvl++) { + if (rat == RADIO_ACCESS_TECHNOLOGY_NR + || freq == ServiceState.FREQUENCY_RANGE_UNKNOWN) { + // Only the NR RAT should have per frequency data. + expectedTxDurationsMs[rat][freq][txLvl] = 0; + } else { + expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE; + } + } + } + } + + // The first modem activity pulled from modem with activity stats for each RATs. + specificInfoList.add(new ActivityStatsTechSpecificInfo( + AccessNetworkConstants.AccessNetworkType.UNKNOWN, + ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 101)); + specificInfoList.add(new ActivityStatsTechSpecificInfo( + AccessNetworkConstants.AccessNetworkType.GERAN, + ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 202)); + specificInfoList.add(new ActivityStatsTechSpecificInfo( + AccessNetworkConstants.AccessNetworkType.UTRAN, + ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 303)); + specificInfoList.add(new ActivityStatsTechSpecificInfo( + AccessNetworkConstants.AccessNetworkType.EUTRAN, + ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[]{3, 9, 133, 48, 218}, 404)); + specificInfoList.add(new ActivityStatsTechSpecificInfo( + AccessNetworkConstants.AccessNetworkType.CDMA2000, + ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 505)); + specificInfoList.add(new ActivityStatsTechSpecificInfo( + AccessNetworkConstants.AccessNetworkType.IWLAN, + ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 606)); + specificInfoList.add(new ActivityStatsTechSpecificInfo( + AccessNetworkConstants.AccessNetworkType.NGRAN, + ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 707)); + specificInfoList.add(new ActivityStatsTechSpecificInfo( + AccessNetworkConstants.AccessNetworkType.NGRAN, + ServiceState.FREQUENCY_RANGE_LOW, new int[txLevelCount], 808)); + specificInfoList.add(new ActivityStatsTechSpecificInfo( + AccessNetworkConstants.AccessNetworkType.NGRAN, + ServiceState.FREQUENCY_RANGE_MID, new int[txLevelCount], 909)); + specificInfoList.add(new ActivityStatsTechSpecificInfo( + AccessNetworkConstants.AccessNetworkType.NGRAN, + ServiceState.FREQUENCY_RANGE_HIGH, new int[txLevelCount], 1010)); + specificInfoList.add(new ActivityStatsTechSpecificInfo( + AccessNetworkConstants.AccessNetworkType.NGRAN, + ServiceState.FREQUENCY_RANGE_MMWAVE, new int[txLevelCount], 1111)); + + + final ActivityStatsTechSpecificInfo[] specificInfos = specificInfoList.toArray( + new ActivityStatsTechSpecificInfo[specificInfoList.size()]); + final ModemActivityInfo mai = new ModemActivityInfo(0L, 2002L, 3003L, specificInfos); + final ModemAndBatteryState state = new ModemAndBatteryState(bi, mai, specificInfos); + + + IntConsumer incrementTime = inc -> { + state.currentTimeMs += inc; + clock.realtime = clock.uptime = state.currentTimeMs; + + final int currRat = state.currentRat; + final int currRant = state.currentRadioAccessNetworkType; + final int currFreqRange = + currRat == RADIO_ACCESS_TECHNOLOGY_NR ? state.currentFrequencyRange : 0; + int currSignalStrength = state.currentSignalStrengths.get(currRat); + + if (state.modemActive) { + // Don't count the duration if the modem is not active + expectedDurationsMs[currRat][currFreqRange][currSignalStrength] += inc; + } + + // Evaluate the HAL provided time in states. + final ActivityStatsTechSpecificInfo info = state.getSpecificInfo(currRant, + currFreqRange); + switch (state.modemState) { + case SLEEP: + long sleepMs = state.modemActivityInfo.getSleepTimeMillis(); + state.modemActivityInfo.setSleepTimeMillis(sleepMs + inc); + break; + case IDLE: + long idleMs = state.modemActivityInfo.getIdleTimeMillis(); + state.modemActivityInfo.setIdleTimeMillis(idleMs + inc); + break; + case RECEIVING: + long rxMs = info.getReceiveTimeMillis(); + info.setReceiveTimeMillis(rxMs + inc); + expectedRxDurationsMs[currRat][currFreqRange] += inc; + break; + case TRANSMITTING: + int[] txMs = info.getTransmitTimeMillis().clone(); + txMs[currSignalStrength] += inc; + info.setTransmitTimeMillis(txMs); + expectedTxDurationsMs[currRat][currFreqRange][currSignalStrength] += inc; + break; + } + }; + + // On battery, but the modem is not active + bi.updateTimeBasesLocked(true, Display.STATE_OFF, state.currentTimeMs * 1000, + state.currentTimeMs * 1000); + bi.setOnBatteryInternal(true); + state.noteModemControllerActivity(); + // Ensure the first modem activity should not be counted up. + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); + // Start counting. + state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR, + AccessNetworkConstants.AccessNetworkType.NGRAN); + // Frequency changed to low. + state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_LOW); + incrementTime.accept(300); + state.setModemState(ModemState.RECEIVING); + incrementTime.accept(500); + state.setModemState(ModemState.TRANSMITTING); + incrementTime.accept(600); + state.noteModemControllerActivity(); + checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs, + expectedTxDurationsMs, bi, state.currentTimeMs); + } + @SmallTest public void testGetPerStateActiveRadioDurationMs_withModemActivity() { final MockClock clock = new MockClock(); // holds realtime and uptime in ms diff --git a/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java b/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java index 62e56f9eeed13..d3ec0d7e3f6e0 100644 --- a/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java +++ b/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java @@ -76,6 +76,9 @@ public class MobileRadioPowerCalculatorTest { .initMeasuredEnergyStatsLocked(); BatteryStatsImpl stats = mStatsRule.getBatteryStats(); + // The first ModemActivityInfo doesn't count up. + setInitialEmptyModemActivityInfo(stats); + // Scan for a cell stats.notePhoneStateLocked(ServiceState.STATE_OUT_OF_SERVICE, TelephonyManager.SIM_STATE_READY, @@ -193,6 +196,9 @@ public class MobileRadioPowerCalculatorTest { .initMeasuredEnergyStatsLocked(); BatteryStatsImpl stats = mStatsRule.getBatteryStats(); + // The first ModemActivityInfo doesn't count up. + setInitialEmptyModemActivityInfo(stats); + // Scan for a cell stats.notePhoneStateLocked(ServiceState.STATE_OUT_OF_SERVICE, TelephonyManager.SIM_STATE_READY, @@ -347,6 +353,9 @@ public class MobileRadioPowerCalculatorTest { .initMeasuredEnergyStatsLocked(); BatteryStatsImpl stats = mStatsRule.getBatteryStats(); + // The first ModemActivityInfo doesn't count up. + setInitialEmptyModemActivityInfo(stats); + // Scan for a cell stats.notePhoneStateLocked(ServiceState.STATE_OUT_OF_SERVICE, TelephonyManager.SIM_STATE_READY, @@ -583,6 +592,9 @@ public class MobileRadioPowerCalculatorTest { .initMeasuredEnergyStatsLocked(); BatteryStatsImpl stats = mStatsRule.getBatteryStats(); + // The first ModemActivityInfo doesn't count up. + setInitialEmptyModemActivityInfo(stats); + // Scan for a cell stats.notePhoneStateLocked(ServiceState.STATE_OUT_OF_SERVICE, TelephonyManager.SIM_STATE_READY, @@ -660,6 +672,9 @@ public class MobileRadioPowerCalculatorTest { .initMeasuredEnergyStatsLocked(); BatteryStatsImpl stats = mStatsRule.getBatteryStats(); + // The first ModemActivityInfo doesn't count up. + setInitialEmptyModemActivityInfo(stats); + stats.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH, 0, -1, 0, 0); @@ -841,6 +856,9 @@ public class MobileRadioPowerCalculatorTest { .initMeasuredEnergyStatsLocked(); BatteryStatsImpl stats = mStatsRule.getBatteryStats(); + // The first ModemActivityInfo doesn't count up. + setInitialEmptyModemActivityInfo(stats); + stats.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH, 0, -1, 0, 0); @@ -1023,4 +1041,10 @@ public class MobileRadioPowerCalculatorTest { assertThat(uidConsumer.getConsumedPower(background)).isWithin(PRECISION).of(2.08130); assertThat(uidConsumer.getConsumedPower(fgs)).isWithin(PRECISION).of(0); } + + public void setInitialEmptyModemActivityInfo(BatteryStatsImpl stats) { + // Initial empty ModemActivityInfo. + final ModemActivityInfo emptyMai = new ModemActivityInfo(0L, 0L, 0L, new int[5], 0L); + stats.noteModemControllerActivity(emptyMai, 0, 0, 0, mNetworkStatsManager); + } }