Smear ModemActivityInfo across multiple stats

If ModemActivityInfo is available on a device, smear the provided
transmit and received times across RadioAccessTechnology and frequency
(for NR RAT).

Bug: 207697945
Test: atest BatteryStatsNoteTest
Change-Id: Ifb4e30dc3fa5ac5dd4824a87a7a86c4a0d14d019
(cherry picked from commit e85ac3239e)
This commit is contained in:
Michael Wachenschwanz
2022-02-15 00:16:01 -08:00
parent e2f5e4acb4
commit be79640cb0
3 changed files with 795 additions and 79 deletions

View File

@@ -2700,6 +2700,46 @@ public abstract class BatteryStats implements Parcelable {
@ServiceState.FrequencyRange int frequencyRange, int signalStrength,
long elapsedRealtimeMs);
/**
* Returns the time in microseconds that the mobile radio has been actively transmitting data on
* a given Radio Access Technology (RAT), at a given frequency (NR RAT only), for a given
* transmission power level.
*
* @param rat Radio Access Technology {@see RadioAccessTechnology}
* @param frequencyRange frequency range {@see ServiceState.FrequencyRange}, only needed for
* RADIO_ACCESS_TECHNOLOGY_NR. Use
* {@link ServiceState.FREQUENCY_RANGE_UNKNOWN} for other Radio Access
* Technologies.
* @param signalStrength the cellular signal strength. {@see CellSignalStrength#getLevel()}
* @param elapsedRealtimeMs current elapsed realtime
* @return time (in milliseconds) the mobile radio spent actively transmitting data in the
* specified state, while on battery. Returns {@link DURATION_UNAVAILABLE} if
* data unavailable.
* @hide
*/
public abstract long getActiveTxRadioDurationMs(@RadioAccessTechnology int rat,
@ServiceState.FrequencyRange int frequencyRange, int signalStrength,
long elapsedRealtimeMs);
/**
* Returns the time in microseconds that the mobile radio has been actively receiving data on a
* given Radio Access Technology (RAT), at a given frequency (NR RAT only), for a given
* transmission power level.
*
* @param rat Radio Access Technology {@see RadioAccessTechnology}
* @param frequencyRange frequency range {@see ServiceState.FrequencyRange}, only needed for
* RADIO_ACCESS_TECHNOLOGY_NR. Use
* {@link ServiceState.FREQUENCY_RANGE_UNKNOWN} for other Radio Access
* Technologies.
* @param elapsedRealtimeMs current elapsed realtime
* @return time (in milliseconds) the mobile radio spent actively receiving data in the
* specified state, while on battery. Returns {@link DURATION_UNAVAILABLE} if
* data unavailable.
* @hide
*/
public abstract long getActiveRxRadioDurationMs(@RadioAccessTechnology int rat,
@ServiceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs);
static final String[] WIFI_SUPPL_STATE_NAMES = {
"invalid", "disconn", "disabled", "inactive", "scanning",
"authenticating", "associating", "associated", "4-way-handshake",
@@ -2719,6 +2759,13 @@ public abstract class BatteryStats implements Parcelable {
*/
public static final long POWER_DATA_UNAVAILABLE = -1L;
/**
* Returned value if duration data is unavailable.
*
* {@hide}
*/
public static final long DURATION_UNAVAILABLE = -1L;
/**
* Returns the battery consumption (in microcoulombs) of bluetooth, derived from on
* device power measurement data.
@@ -4093,6 +4140,10 @@ public abstract class BatteryStats implements Parcelable {
" Mmwave frequency (greater than 6GHz):\n"};
final String signalStrengthHeader =
" Signal Strength Time:\n";
final String txHeader =
" Tx Time:\n";
final String rxHeader =
" Rx Time: ";
final String[] signalStrengthDescription = new String[]{
" unknown: ",
" poor: ",
@@ -4144,6 +4195,29 @@ public abstract class BatteryStats implements Parcelable {
sb.append(")\n");
}
sb.append(prefix);
sb.append(txHeader);
for (int strength = 0; strength < numSignalStrength; strength++) {
final long timeMs = getActiveTxRadioDurationMs(rat, freqLvl, strength,
rawRealtimeMs);
if (timeMs <= 0) continue;
hasFreqData = true;
sb.append(prefix);
sb.append(signalStrengthDescription[strength]);
formatTimeMs(sb, timeMs);
sb.append("(");
sb.append(formatRatioLocked(timeMs, totalActiveTimesMs));
sb.append(")\n");
}
sb.append(prefix);
sb.append(rxHeader);
final long rxTimeMs = getActiveRxRadioDurationMs(rat, freqLvl, rawRealtimeMs);
formatTimeMs(sb, rxTimeMs);
sb.append("(");
sb.append(formatRatioLocked(rxTimeMs, totalActiveTimesMs));
sb.append(")\n");
if (hasFreqData) {
hasData = true;
pw.print(sb);

View File

@@ -166,7 +166,7 @@ public class BatteryStatsImpl extends BatteryStats {
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
static final int VERSION = 206;
static final int VERSION = 207;
// The maximum number of names wakelocks we will keep track of
// per uid; once the limit is reached, we batch the remaining wakelocks
@@ -964,6 +964,16 @@ public class BatteryStatsImpl extends BatteryStats {
* Timers for each combination of frequency range and signal strength.
*/
public final StopwatchTimer[][] perStateTimers;
/**
* Counters tracking the time (in milliseconds) spent transmitting data in a given state.
*/
@Nullable
private LongSamplingCounter[][] mPerStateTxDurationMs = null;
/**
* Counters tracking the time (in milliseconds) spent receiving data in at given frequency.
*/
@Nullable
private LongSamplingCounter[] mPerFrequencyRxDurationMs = null;
RadioAccessTechnologyBatteryStats(int freqCount, Clock clock, TimeBase timeBase) {
perStateTimers =
@@ -1024,15 +1034,198 @@ public class BatteryStatsImpl extends BatteryStats {
}
/**
* Reset display timers.
* Returns the duration in milliseconds spent in a given state since the last mark.
*/
public long getTimeSinceMark(@ServiceState.FrequencyRange int frequencyRange,
int signalStrength, long elapsedRealtimeMs) {
return perStateTimers[frequencyRange][signalStrength].getTimeSinceMarkLocked(
elapsedRealtimeMs * 1000) / 1000;
}
/**
* Set mark for all timers.
*/
public void setMark(long elapsedRealtimeMs) {
final int size = perStateTimers.length;
for (int i = 0; i < size; i++) {
for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
perStateTimers[i][j].setMark(elapsedRealtimeMs);
}
}
}
/**
* Returns numbers of frequencies tracked for this RAT.
*/
public int getFrequencyRangeCount() {
return perStateTimers.length;
}
/**
* Add TX time for a given state.
*/
public void incrementTxDuration(@ServiceState.FrequencyRange int frequencyRange,
int signalStrength, long durationMs) {
getTxDurationCounter(frequencyRange, signalStrength, true).addCountLocked(durationMs);
}
/**
* Add TX time for a given frequency.
*/
public void incrementRxDuration(@ServiceState.FrequencyRange int frequencyRange,
long durationMs) {
getRxDurationCounter(frequencyRange, true).addCountLocked(durationMs);
}
/**
* Reset radio access technology timers and counts.
*/
public void reset(long elapsedRealtimeUs) {
final int size = perStateTimers.length;
for (int i = 0; i < size; i++) {
for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
perStateTimers[i][j].reset(false, elapsedRealtimeUs);
if (mPerStateTxDurationMs == null) continue;
mPerStateTxDurationMs[i][j].reset(false, elapsedRealtimeUs);
}
if (mPerFrequencyRxDurationMs == null) continue;
mPerFrequencyRxDurationMs[i].reset(false, elapsedRealtimeUs);
}
}
/**
* Write data to summary parcel
*/
public void writeSummaryToParcel(Parcel out, long elapsedRealtimeUs) {
final int freqCount = perStateTimers.length;
out.writeInt(freqCount);
out.writeInt(CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS);
for (int i = 0; i < freqCount; i++) {
for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
perStateTimers[i][j].writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
}
}
if (mPerStateTxDurationMs == null) {
out.writeInt(0);
} else {
out.writeInt(1);
for (int i = 0; i < freqCount; i++) {
for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
mPerStateTxDurationMs[i][j].writeSummaryFromParcelLocked(out);
}
}
}
if (mPerFrequencyRxDurationMs == null) {
out.writeInt(0);
} else {
out.writeInt(1);
for (int i = 0; i < freqCount; i++) {
mPerFrequencyRxDurationMs[i].writeSummaryFromParcelLocked(out);
}
}
}
/**
* Read data from summary parcel
*/
public void readSummaryFromParcel(Parcel in) {
final int oldFreqCount = in.readInt();
final int oldSignalStrengthCount = in.readInt();
final int currFreqCount = perStateTimers.length;
final int currSignalStrengthCount = CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS;
for (int freq = 0; freq < oldFreqCount; freq++) {
for (int strength = 0; strength < oldSignalStrengthCount; strength++) {
if (freq >= currFreqCount || strength >= currSignalStrengthCount) {
// Mismatch with the summary parcel. Consume the data but don't use it.
final StopwatchTimer temp = new StopwatchTimer(null, null, -1, null,
new TimeBase());
// Consume perStateTimers data.
temp.readSummaryFromParcelLocked(in);
} else {
perStateTimers[freq][strength].readSummaryFromParcelLocked(in);
}
}
}
if (in.readInt() == 1) {
for (int freq = 0; freq < oldFreqCount; freq++) {
for (int strength = 0; strength < oldSignalStrengthCount; strength++) {
if (freq >= currFreqCount || strength >= currSignalStrengthCount) {
// Mismatch with the summary parcel. Consume the data but don't use it.
final StopwatchTimer temp = new StopwatchTimer(null, null, -1, null,
new TimeBase());
// Consume mPerStateTxDurationMs data.
temp.readSummaryFromParcelLocked(in);
}
getTxDurationCounter(freq, strength, true).readSummaryFromParcelLocked(in);
}
}
}
if (in.readInt() == 1) {
for (int freq = 0; freq < oldFreqCount; freq++) {
if (freq >= currFreqCount) {
// Mismatch with the summary parcel. Consume the data but don't use it.
final StopwatchTimer
temp = new StopwatchTimer(null, null, -1, null, new TimeBase());
// Consume mPerFrequencyRxDurationMs data.
temp.readSummaryFromParcelLocked(in);
continue;
}
getRxDurationCounter(freq, true).readSummaryFromParcelLocked(in);
}
}
}
private LongSamplingCounter getTxDurationCounter(
@ServiceState.FrequencyRange int frequencyRange, int signalStrength, boolean make) {
if (mPerStateTxDurationMs == null) {
if (!make) return null;
final int freqCount = getFrequencyRangeCount();
final int signalStrengthCount = perStateTimers[0].length;
final TimeBase timeBase = perStateTimers[0][0].mTimeBase;
mPerStateTxDurationMs = new LongSamplingCounter[freqCount][signalStrengthCount];
for (int freq = 0; freq < freqCount; freq++) {
for (int strength = 0; strength < signalStrengthCount; strength++) {
mPerStateTxDurationMs[freq][strength] = new LongSamplingCounter(timeBase);
}
}
}
if (frequencyRange < 0 || frequencyRange >= getFrequencyRangeCount()) {
Slog.w(TAG, "Unexpected frequency range (" + frequencyRange
+ ") requested in getTxDurationCounter");
return null;
}
if (signalStrength < 0 || signalStrength >= perStateTimers[0].length) {
Slog.w(TAG, "Unexpected signal strength (" + signalStrength
+ ") requested in getTxDurationCounter");
return null;
}
return mPerStateTxDurationMs[frequencyRange][signalStrength];
}
private LongSamplingCounter getRxDurationCounter(
@ServiceState.FrequencyRange int frequencyRange, boolean make) {
if (mPerFrequencyRxDurationMs == null) {
if (!make) return null;
final int freqCount = getFrequencyRangeCount();
final TimeBase timeBase = perStateTimers[0][0].mTimeBase;
mPerFrequencyRxDurationMs = new LongSamplingCounter[freqCount];
for (int freq = 0; freq < freqCount; freq++) {
mPerFrequencyRxDurationMs[freq] = new LongSamplingCounter(timeBase);
}
}
if (frequencyRange < 0 || frequencyRange >= getFrequencyRangeCount()) {
Slog.w(TAG, "Unexpected frequency range (" + frequencyRange
+ ") requested in getRxDurationCounter");
return null;
}
return mPerFrequencyRxDurationMs[frequencyRange];
}
}
@@ -8000,6 +8193,32 @@ public class BatteryStatsImpl extends BatteryStats {
elapsedRealtimeMs * 1000, STATS_SINCE_CHARGED) / 1000;
}
@Override
public long getActiveTxRadioDurationMs(@RadioAccessTechnology int rat,
@ServiceState.FrequencyRange int frequencyRange, int signalStrength,
long elapsedRealtimeMs) {
final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
if (stats == null) return DURATION_UNAVAILABLE;
final LongSamplingCounter counter = stats.getTxDurationCounter(frequencyRange,
signalStrength, false);
if (counter == null) return DURATION_UNAVAILABLE;
return counter.getCountLocked(STATS_SINCE_CHARGED);
}
@Override
public long getActiveRxRadioDurationMs(@RadioAccessTechnology int rat,
@ServiceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs) {
final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
if (stats == null) return DURATION_UNAVAILABLE;
final LongSamplingCounter counter = stats.getRxDurationCounter(frequencyRange, false);
if (counter == null) return DURATION_UNAVAILABLE;
return counter.getCountLocked(STATS_SINCE_CHARGED);
}
@UnsupportedAppUsage
@Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
@@ -13482,6 +13701,67 @@ public class BatteryStatsImpl extends BatteryStats {
addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mTmpRailStats.resetCellularTotalEnergyUsed();
}
// Proportionally smear Rx and Tx times across each RAt
final int levelCount = CellSignalStrength.getNumSignalStrengthLevels();
long[] perSignalStrengthActiveTimeMs = new long[levelCount];
long totalActiveTimeMs = 0;
for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
if (ratStats == null) continue;
final int freqCount = ratStats.getFrequencyRangeCount();
for (int freq = 0; freq < freqCount; freq++) {
for (int level = 0; level < levelCount; level++) {
final long durationMs = ratStats.getTimeSinceMark(freq, level,
elapsedRealtimeMs);
perSignalStrengthActiveTimeMs[level] += durationMs;
totalActiveTimeMs += durationMs;
}
}
}
if (totalActiveTimeMs != 0) {
// Smear the provided Tx/Rx durations across each RAT, frequency, and signal
// strength.
for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
if (ratStats == null) continue;
final int freqCount = ratStats.getFrequencyRangeCount();
for (int freq = 0; freq < freqCount; freq++) {
long frequencyDurationMs = 0;
for (int level = 0; level < levelCount; level++) {
final long durationMs = ratStats.getTimeSinceMark(freq, level,
elapsedRealtimeMs);
final long totalLvlDurationMs =
perSignalStrengthActiveTimeMs[level];
if (totalLvlDurationMs == 0) continue;
final long totalTxLvlDurations =
deltaInfo.getTransmitDurationMillisAtPowerLevel(level);
// Smear HAL provided Tx power level duration based on active modem
// duration in a given state. (Add totalLvlDurationMs / 2 before
// the integer division with totalLvlDurationMs for rounding.)
final long proportionalTxDurationMs =
(durationMs * totalTxLvlDurations
+ (totalLvlDurationMs / 2)) / totalLvlDurationMs;
ratStats.incrementTxDuration(freq, level, proportionalTxDurationMs);
frequencyDurationMs += durationMs;
}
final long totalRxDuration = deltaInfo.getReceiveTimeMillis();
// Smear HAL provided Rx power duration based on active modem
// duration in a given state. (Add totalActiveTimeMs / 2 before the
// integer division with totalActiveTimeMs for rounding.)
final long proportionalRxDurationMs =
(frequencyDurationMs * totalRxDuration + (totalActiveTimeMs
/ 2)) / totalActiveTimeMs;
ratStats.incrementRxDuration(freq, proportionalRxDurationMs);
}
ratStats.setMark(elapsedRealtimeMs);
}
}
}
long totalAppRadioTimeUs = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
elapsedRealtimeMs * 1000);
@@ -16926,6 +17206,13 @@ public class BatteryStatsImpl extends BatteryStats {
mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
}
final int numRat = in.readInt();
for (int i = 0; i < numRat; i++) {
if (in.readInt() == 0) continue;
getRatBatteryStatsLocked(i).readSummaryFromParcel(in);
}
mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
@@ -17431,6 +17718,17 @@ public class BatteryStatsImpl extends BatteryStats {
mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
}
final int numRat = mPerRatBatteryStats.length;
out.writeInt(numRat);
for (int i = 0; i < numRat; i++) {
final RadioAccessTechnologyBatteryStats ratStat = mPerRatBatteryStats[i];
if (ratStat == null) {
out.writeInt(0);
continue;
}
out.writeInt(1);
ratStat.writeSummaryToParcel(out, nowRealtime);
}
mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, nowRealtime);
mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, nowRealtime);
mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);

View File

@@ -17,6 +17,8 @@
package com.android.internal.os;
import static android.os.BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS;
import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
import static android.os.BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT;
import static android.os.BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR;
import static android.os.BatteryStats.STATS_SINCE_CHARGED;
import static android.os.BatteryStats.WAKE_TYPE_PARTIAL;
@@ -24,7 +26,10 @@ import static android.os.BatteryStats.WAKE_TYPE_PARTIAL;
import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_CPU;
import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_DISPLAY;
import static org.mockito.Mockito.mock;
import android.app.ActivityManager;
import android.app.usage.NetworkStatsManager;
import android.os.BatteryStats;
import android.os.BatteryStats.HistoryItem;
import android.os.BatteryStats.Uid.Sensor;
@@ -34,6 +39,7 @@ import android.os.WorkSource;
import android.telephony.Annotation;
import android.telephony.CellSignalStrength;
import android.telephony.DataConnectionRealTimeInfo;
import android.telephony.ModemActivityInfo;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.util.SparseIntArray;
@@ -48,6 +54,8 @@ import com.android.internal.power.MeasuredEnergyStats;
import junit.framework.TestCase;
import org.mockito.Mock;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -72,6 +80,13 @@ public class BatteryStatsNoteTest extends TestCase {
private static final int ISOLATED_UID = UserHandle.getUid(0, ISOLATED_APP_ID);
private static final WorkSource WS = new WorkSource(UID);
enum ModemState {
SLEEP, IDLE, RECEIVING, TRANSMITTING
}
@Mock
NetworkStatsManager mNetworkStatsManager;
/**
* Test BatteryStatsImpl.Uid.noteBluetoothScanResultLocked.
*/
@@ -1173,69 +1188,29 @@ public class BatteryStatsNoteTest extends TestCase {
}
@SmallTest
public void testGetPerStateActiveRadioDurationMs() {
public void testGetPerStateActiveRadioDurationMs_noModemActivity() {
final MockClock clock = new MockClock(); // holds realtime and uptime in ms
final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clock);
final int ratCount = BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT;
final int ratCount = RADIO_ACCESS_TECHNOLOGY_COUNT;
final int frequencyCount = ServiceState.FREQUENCY_RANGE_MMWAVE + 1;
final int txLevelCount = CellSignalStrength.getNumSignalStrengthLevels();
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++) {
// Should have no RX data without Modem Activity Info
expectedRxDurationsMs[rat][freq] = POWER_DATA_UNAVAILABLE;
for (int txLvl = 0; txLvl < txLevelCount; txLvl++) {
expectedDurationsMs[rat][freq][txLvl] = 0;
// Should have no TX data without Modem Activity Info
expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE;
}
}
}
class ModemAndBatteryState {
public long currentTimeMs = 100;
public boolean onBattery = false;
public boolean modemActive = false;
@Annotation.NetworkType
public int currentNetworkDataType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
@BatteryStats.RadioAccessTechnology
public int currentRat = BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER;
@ServiceState.FrequencyRange
public int currentFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
public SparseIntArray currentSignalStrengths = new SparseIntArray();
void setOnBattery(boolean onBattery) {
this.onBattery = onBattery;
bi.updateTimeBasesLocked(onBattery, Display.STATE_OFF, currentTimeMs * 1000,
currentTimeMs * 1000);
}
void setModemActive(boolean active) {
modemActive = active;
final int state = active ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
: DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
bi.noteMobileRadioPowerStateLocked(state, currentTimeMs * 1000_000L, UID);
}
void setRatType(@Annotation.NetworkType int dataType,
@BatteryStats.RadioAccessTechnology int rat) {
currentNetworkDataType = dataType;
currentRat = rat;
bi.notePhoneDataConnectionStateLocked(dataType, true, ServiceState.STATE_IN_SERVICE,
currentFrequencyRange);
}
void setFrequencyRange(@ServiceState.FrequencyRange int frequency) {
currentFrequencyRange = frequency;
bi.notePhoneDataConnectionStateLocked(currentNetworkDataType, true,
ServiceState.STATE_IN_SERVICE, frequency);
}
void setSignalStrength(@BatteryStats.RadioAccessTechnology int rat, int strength) {
currentSignalStrengths.put(rat, strength);
final int size = currentSignalStrengths.size();
final int newestGenSignalStrength = currentSignalStrengths.valueAt(size - 1);
bi.notePhoneSignalStrengthLocked(newestGenSignalStrength, currentSignalStrengths);
}
}
final ModemAndBatteryState state = new ModemAndBatteryState();
final ModemAndBatteryState state = new ModemAndBatteryState(bi, null);
IntConsumer incrementTime = inc -> {
state.currentTimeMs += inc;
@@ -1253,6 +1228,7 @@ public class BatteryStatsNoteTest extends TestCase {
expectedDurationsMs[currentRat][currentFrequencyRange][currentSignalStrength] += inc;
};
state.setOnBattery(false);
state.setModemActive(false);
state.setRatType(TelephonyManager.NETWORK_TYPE_UNKNOWN,
@@ -1260,95 +1236,367 @@ public class BatteryStatsNoteTest extends TestCase {
state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_UNKNOWN);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
// While not on battery, the timers should not increase.
state.setModemActive(true);
incrementTime.accept(100);
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
incrementTime.accept(200);
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR,
CellSignalStrength.SIGNAL_STRENGTH_GOOD);
incrementTime.accept(500);
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_MMWAVE);
incrementTime.accept(300);
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
state.setRatType(TelephonyManager.NETWORK_TYPE_LTE,
BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE);
incrementTime.accept(400);
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
CellSignalStrength.SIGNAL_STRENGTH_MODERATE);
incrementTime.accept(500);
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
// When set on battery, currently active state (RAT:LTE, Signal Strength:Moderate) should
// start counting up.
state.setOnBattery(true);
incrementTime.accept(600);
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
// Changing LTE signal strength should be tracked.
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
CellSignalStrength.SIGNAL_STRENGTH_POOR);
incrementTime.accept(700);
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
incrementTime.accept(800);
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
CellSignalStrength.SIGNAL_STRENGTH_GOOD);
incrementTime.accept(900);
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
CellSignalStrength.SIGNAL_STRENGTH_GREAT);
incrementTime.accept(1000);
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
// Change in the signal strength of nonactive RAT should not affect anything.
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
CellSignalStrength.SIGNAL_STRENGTH_POOR);
incrementTime.accept(1100);
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
// Changing to OTHER Rat should start tracking the poor signal strength.
state.setRatType(TelephonyManager.NETWORK_TYPE_CDMA,
BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER);
incrementTime.accept(1200);
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
// Noting frequency change should not affect non NR Rat.
state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_HIGH);
incrementTime.accept(1300);
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
// Now the NR Rat, HIGH frequency range, good signal strength should start counting.
state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
incrementTime.accept(1400);
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
// Noting frequency change should not affect non NR Rat.
state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_LOW);
incrementTime.accept(1500);
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
// Modem no longer active, should not be tracking any more.
state.setModemActive(false);
incrementTime.accept(1500);
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
}
@SmallTest
public void testGetPerStateActiveRadioDurationMs_withModemActivity() {
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();
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] = POWER_DATA_UNAVAILABLE;
} else {
expectedRxDurationsMs[rat][freq] = 0;
}
expectedRxDurationsMs[rat][freq] = POWER_DATA_UNAVAILABLE;
for (int txLvl = 0; txLvl < txLevelCount; txLvl++) {
expectedDurationsMs[rat][freq][txLvl] = 0;
if (rat != RADIO_ACCESS_TECHNOLOGY_NR
&& freq != ServiceState.FREQUENCY_RANGE_UNKNOWN) {
// Only the NR RAT should have per frequency data.
expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE;
} else {
expectedTxDurationsMs[rat][freq][txLvl] = 0;
}
expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE;
}
}
}
final ModemActivityInfo mai = new ModemActivityInfo(0L, 0L, 0L, new int[txLevelCount], 0L);
final ModemAndBatteryState state = new ModemAndBatteryState(bi, mai);
IntConsumer incrementTime = inc -> {
state.currentTimeMs += inc;
clock.realtime = clock.uptime = state.currentTimeMs;
// If the device is not on battery, no timers should increment.
if (!state.onBattery) return;
// If the modem is not active, no timers should increment.
if (!state.modemActive) return;
final int currRat = state.currentRat;
final int currFreqRange =
currRat == RADIO_ACCESS_TECHNOLOGY_NR ? state.currentFrequencyRange : 0;
int currSignalStrength = state.currentSignalStrengths.get(currRat);
expectedDurationsMs[currRat][currFreqRange][currSignalStrength] += inc;
// Evaluate the HAL provided time in states.
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 = state.modemActivityInfo.getReceiveTimeMillis();
state.modemActivityInfo.setReceiveTimeMillis(rxMs + inc);
expectedRxDurationsMs[currRat][currFreqRange] += inc;
break;
case TRANSMITTING:
int[] txMs = state.modemActivityInfo.getTransmitTimeMillis();
txMs[currSignalStrength] += inc;
state.modemActivityInfo.setTransmitTimeMillis(txMs);
expectedTxDurationsMs[currRat][currFreqRange][currSignalStrength] += inc;
break;
}
};
state.setOnBattery(false);
state.setModemActive(false);
state.setRatType(TelephonyManager.NETWORK_TYPE_UNKNOWN,
BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER);
state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_UNKNOWN);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
// While not on battery, the timers should not increase.
state.setModemActive(true);
incrementTime.accept(100);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
incrementTime.accept(200);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR,
CellSignalStrength.SIGNAL_STRENGTH_GOOD);
incrementTime.accept(500);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_MMWAVE);
incrementTime.accept(300);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
state.setRatType(TelephonyManager.NETWORK_TYPE_LTE,
BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE);
incrementTime.accept(400);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
CellSignalStrength.SIGNAL_STRENGTH_MODERATE);
incrementTime.accept(500);
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
// Data will now be available.
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;
}
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;
}
}
}
}
// When set on battery, currently active state (RAT:LTE, Signal Strength:Moderate) should
// start counting up.
state.setOnBattery(true);
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);
// Changing LTE signal strength should be tracked.
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
CellSignalStrength.SIGNAL_STRENGTH_POOR);
incrementTime.accept(300);
state.setModemState(ModemState.SLEEP);
incrementTime.accept(1000);
state.setModemState(ModemState.RECEIVING);
incrementTime.accept(700);
state.noteModemControllerActivity();
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
incrementTime.accept(800);
state.setModemState(ModemState.TRANSMITTING);
incrementTime.accept(222);
state.setModemState(ModemState.IDLE);
incrementTime.accept(111);
state.setModemState(ModemState.RECEIVING);
incrementTime.accept(7777);
state.noteModemControllerActivity();
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
CellSignalStrength.SIGNAL_STRENGTH_GOOD);
incrementTime.accept(88);
state.setModemState(ModemState.TRANSMITTING);
incrementTime.accept(900);
state.noteModemControllerActivity();
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
CellSignalStrength.SIGNAL_STRENGTH_GREAT);
incrementTime.accept(123);
state.setModemState(ModemState.RECEIVING);
incrementTime.accept(333);
state.setModemState(ModemState.TRANSMITTING);
incrementTime.accept(1000);
state.setModemState(ModemState.RECEIVING);
incrementTime.accept(555);
state.noteModemControllerActivity();
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
// Change in the signal strength of nonactive RAT should not affect anything.
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
CellSignalStrength.SIGNAL_STRENGTH_POOR);
incrementTime.accept(631);
state.setModemState(ModemState.TRANSMITTING);
incrementTime.accept(321);
state.setModemState(ModemState.RECEIVING);
incrementTime.accept(99);
state.noteModemControllerActivity();
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
// Changing to OTHER Rat should start tracking the poor signal strength.
state.setRatType(TelephonyManager.NETWORK_TYPE_CDMA,
BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER);
incrementTime.accept(1200);
state.noteModemControllerActivity();
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
// Noting frequency change should not affect non NR Rat.
state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_HIGH);
incrementTime.accept(444);
state.setModemState(ModemState.TRANSMITTING);
incrementTime.accept(1300);
state.noteModemControllerActivity();
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
// Now the NR Rat, HIGH frequency range, good signal strength should start counting.
state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
incrementTime.accept(1400);
state.noteModemControllerActivity();
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
// Frequency changed to low.
state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_LOW);
incrementTime.accept(852);
state.setModemState(ModemState.RECEIVING);
incrementTime.accept(157);
state.setModemState(ModemState.TRANSMITTING);
incrementTime.accept(1500);
state.noteModemControllerActivity();
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
// Modem no longer active, should not be tracking any more.
state.setModemActive(false);
incrementTime.accept(1500);
state.noteModemControllerActivity();
checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
expectedTxDurationsMs, bi, state.currentTimeMs);
}
private void setFgState(int uid, boolean fgOn, MockBatteryStatsImpl bi) {
@@ -1426,28 +1674,124 @@ public class BatteryStatsNoteTest extends TestCase {
}
private void checkPerStateActiveRadioDurations(long[][][] expectedDurationsMs,
long[][] expectedRxDurationsMs, long[][][] expectedTxDurationsMs,
BatteryStatsImpl bi, long currentTimeMs) {
for (int rat = 0; rat < expectedDurationsMs.length; rat++) {
final long[][] expectedRatDurationsMs = expectedDurationsMs[rat];
for (int freq = 0; freq < expectedRatDurationsMs.length; freq++) {
final long expectedRxDurationMs = expectedRxDurationsMs[rat][freq];
// Build a verbose fail message, just in case.
final StringBuilder rxFailSb = new StringBuilder();
rxFailSb.append("Wrong time in Rx state for RAT:");
rxFailSb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
rxFailSb.append(", frequency:");
rxFailSb.append(ServiceState.frequencyRangeToString(freq));
assertEquals(rxFailSb.toString(), expectedRxDurationMs,
bi.getActiveRxRadioDurationMs(rat, freq, currentTimeMs));
final long[] expectedFreqDurationsMs = expectedRatDurationsMs[freq];
for (int strength = 0; strength < expectedFreqDurationsMs.length; strength++) {
final long expectedSignalStrengthDurationMs = expectedFreqDurationsMs[strength];
final long expectedTxDurationMs = expectedTxDurationsMs[rat][freq][strength];
final long actualDurationMs = bi.getActiveRadioDurationMs(rat, freq,
strength, currentTimeMs);
// Build a verbose fail message, just in case.
final StringBuilder sb = new StringBuilder();
sb.append("Wrong time in state for RAT:");
sb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
sb.append(", frequency:");
sb.append(ServiceState.frequencyRangeToString(freq));
sb.append(", strength:");
sb.append(strength);
final StringBuilder failSb = new StringBuilder();
failSb.append("Wrong time in state for RAT:");
failSb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
failSb.append(", frequency:");
failSb.append(ServiceState.frequencyRangeToString(freq));
failSb.append(", strength:");
failSb.append(strength);
assertEquals(failSb.toString(), expectedSignalStrengthDurationMs,
actualDurationMs);
assertEquals(sb.toString(), expectedSignalStrengthDurationMs, actualDurationMs);
final StringBuilder txFailSb = new StringBuilder();
txFailSb.append("Wrong time in Tx state for RAT:");
txFailSb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
txFailSb.append(", frequency:");
txFailSb.append(ServiceState.frequencyRangeToString(freq));
txFailSb.append(", strength:");
txFailSb.append(strength);
assertEquals(txFailSb.toString(), expectedTxDurationMs,
bi.getActiveTxRadioDurationMs(rat, freq, strength, currentTimeMs));
}
}
}
}
private class ModemAndBatteryState {
public long currentTimeMs = 100;
public boolean onBattery = false;
public boolean modemActive = false;
@Annotation.NetworkType
public int currentNetworkDataType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
@BatteryStats.RadioAccessTechnology
public int currentRat = BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER;
@ServiceState.FrequencyRange
public int currentFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
public SparseIntArray currentSignalStrengths = new SparseIntArray();
public ModemState modemState = ModemState.SLEEP;
public ModemActivityInfo modemActivityInfo;
private final MockBatteryStatsImpl mBsi;
ModemAndBatteryState(MockBatteryStatsImpl bsi, ModemActivityInfo mai) {
mBsi = bsi;
modemActivityInfo = mai;
}
void setOnBattery(boolean onBattery) {
this.onBattery = onBattery;
mBsi.updateTimeBasesLocked(onBattery, Display.STATE_OFF, currentTimeMs * 1000,
currentTimeMs * 1000);
mBsi.setOnBatteryInternal(onBattery);
noteModemControllerActivity();
}
void setModemActive(boolean active) {
modemActive = active;
final int state = active ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
: DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
mBsi.noteMobileRadioPowerStateLocked(state, currentTimeMs * 1000_000L, UID);
noteModemControllerActivity();
}
void setRatType(@Annotation.NetworkType int dataType,
@BatteryStats.RadioAccessTechnology int rat) {
currentNetworkDataType = dataType;
currentRat = rat;
mBsi.notePhoneDataConnectionStateLocked(dataType, true, ServiceState.STATE_IN_SERVICE,
currentFrequencyRange);
}
void setFrequencyRange(@ServiceState.FrequencyRange int frequency) {
currentFrequencyRange = frequency;
mBsi.notePhoneDataConnectionStateLocked(currentNetworkDataType, true,
ServiceState.STATE_IN_SERVICE, frequency);
}
void setSignalStrength(@BatteryStats.RadioAccessTechnology int rat, int strength) {
currentSignalStrengths.put(rat, strength);
final int size = currentSignalStrengths.size();
final int newestGenSignalStrength = currentSignalStrengths.valueAt(size - 1);
mBsi.notePhoneSignalStrengthLocked(newestGenSignalStrength, currentSignalStrengths);
}
void setModemState(ModemState state) {
modemState = state;
}
void noteModemControllerActivity() {
if (modemActivityInfo == null) return;
modemActivityInfo.setTimestamp(currentTimeMs);
ModemActivityInfo copy = new ModemActivityInfo(modemActivityInfo.getTimestampMillis(),
modemActivityInfo.getSleepTimeMillis(), modemActivityInfo.getIdleTimeMillis(),
modemActivityInfo.getTransmitTimeMillis().clone(),
modemActivityInfo.getReceiveTimeMillis());
mBsi.noteModemControllerActivity(copy, POWER_DATA_UNAVAILABLE,
currentTimeMs, currentTimeMs, mNetworkStatsManager);
}
}
}