Loading core/java/android/os/BatteryStats.java +3 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading services/core/java/com/android/server/power/stats/BatteryStatsImpl.java +1 −2 Original line number Diff line number Diff line Loading @@ -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]; Loading Loading @@ -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)) { Loading services/core/java/com/android/server/power/stats/BinaryStatePowerStatsProcessor.java +6 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading services/core/java/com/android/server/power/stats/GnssPowerStatsProcessor.java +28 −15 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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) { void start(PowerComponentAggregatedPowerStats stats, long timestampMs) { super.start(stats, timestampMs); mGnssSignalLevelTimestamp = timestampMs; mGnssSignalLevel = GnssSignalQuality.GNSS_SIGNAL_QUALITY_UNKNOWN; return STATE_OFF; Arrays.fill(mGnssSignalDurations, 0); } noteGnssSignalLevel(item); return STATE_ON; @Override protected @BinaryState int getBinaryState(BatteryStats.HistoryItem item) { return (item.states & BatteryStats.HistoryItem.STATE_GPS_ON_FLAG) != 0 ? STATE_ON : STATE_OFF; } private void noteGnssSignalLevel(BatteryStats.HistoryItem item) { int signalLevel = (item.states2 & BatteryStats.HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK) @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) { Loading services/tests/powerstatstests/src/com/android/server/power/stats/GnssPowerStatsTest.java +135 −39 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading @@ -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( Loading @@ -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)); Loading @@ -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(); Loading Loading @@ -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)); Loading @@ -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)); Loading @@ -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(); Loading Loading @@ -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) { Loading @@ -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; } Loading Loading
core/java/android/os/BatteryStats.java +3 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading
services/core/java/com/android/server/power/stats/BatteryStatsImpl.java +1 −2 Original line number Diff line number Diff line Loading @@ -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]; Loading Loading @@ -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)) { Loading
services/core/java/com/android/server/power/stats/BinaryStatePowerStatsProcessor.java +6 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading
services/core/java/com/android/server/power/stats/GnssPowerStatsProcessor.java +28 −15 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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) { void start(PowerComponentAggregatedPowerStats stats, long timestampMs) { super.start(stats, timestampMs); mGnssSignalLevelTimestamp = timestampMs; mGnssSignalLevel = GnssSignalQuality.GNSS_SIGNAL_QUALITY_UNKNOWN; return STATE_OFF; Arrays.fill(mGnssSignalDurations, 0); } noteGnssSignalLevel(item); return STATE_ON; @Override protected @BinaryState int getBinaryState(BatteryStats.HistoryItem item) { return (item.states & BatteryStats.HistoryItem.STATE_GPS_ON_FLAG) != 0 ? STATE_ON : STATE_OFF; } private void noteGnssSignalLevel(BatteryStats.HistoryItem item) { int signalLevel = (item.states2 & BatteryStats.HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK) @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) { Loading
services/tests/powerstatstests/src/com/android/server/power/stats/GnssPowerStatsTest.java +135 −39 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading @@ -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( Loading @@ -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)); Loading @@ -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(); Loading Loading @@ -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)); Loading @@ -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)); Loading @@ -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(); Loading Loading @@ -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) { Loading @@ -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; } Loading