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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user