Merge "Collect fine grain time-in-state Modem durations"
This commit is contained in:
committed by
Android (Google) Code Review
commit
288b4bc054
@@ -34,6 +34,7 @@ import android.server.ServerProtoEnums;
|
||||
import android.service.batterystats.BatteryStatsServiceDumpHistoryProto;
|
||||
import android.service.batterystats.BatteryStatsServiceDumpProto;
|
||||
import android.telephony.CellSignalStrength;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.format.DateFormat;
|
||||
import android.util.ArrayMap;
|
||||
@@ -2654,6 +2655,46 @@ public abstract class BatteryStats implements Parcelable {
|
||||
*/
|
||||
public abstract Timer getPhoneDataConnectionTimer(int dataType);
|
||||
|
||||
/** @hide */
|
||||
public static final int RADIO_ACCESS_TECHNOLOGY_OTHER = 0;
|
||||
/** @hide */
|
||||
public static final int RADIO_ACCESS_TECHNOLOGY_LTE = 1;
|
||||
/** @hide */
|
||||
public static final int RADIO_ACCESS_TECHNOLOGY_NR = 2;
|
||||
/** @hide */
|
||||
public static final int RADIO_ACCESS_TECHNOLOGY_COUNT = 3;
|
||||
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(prefix = "RADIO_ACCESS_TECHNOLOGY_",
|
||||
value = {RADIO_ACCESS_TECHNOLOGY_OTHER, RADIO_ACCESS_TECHNOLOGY_LTE,
|
||||
RADIO_ACCESS_TECHNOLOGY_NR})
|
||||
public @interface RadioAccessTechnology {
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static final String[] RADIO_ACCESS_TECHNOLOGY_NAMES = {"Other", "LTE", "NR"};
|
||||
|
||||
/**
|
||||
* Returns the time in microseconds that the mobile radio has been active 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 active in the specified state,
|
||||
* while on battery.
|
||||
* @hide
|
||||
*/
|
||||
public abstract long getActiveRadioDurationMs(@RadioAccessTechnology int rat,
|
||||
@ServiceState.FrequencyRange int frequencyRange, int signalStrength,
|
||||
long elapsedRealtimeMs);
|
||||
|
||||
static final String[] WIFI_SUPPL_STATE_NAMES = {
|
||||
"invalid", "disconn", "disabled", "inactive", "scanning",
|
||||
"authenticating", "associating", "associated", "4-way-handshake",
|
||||
@@ -3997,6 +4038,89 @@ public abstract class BatteryStats implements Parcelable {
|
||||
}
|
||||
}
|
||||
|
||||
private void printCellularPerRatBreakdown(PrintWriter pw, StringBuilder sb, String prefix,
|
||||
long rawRealtimeMs) {
|
||||
final String allFrequenciesHeader =
|
||||
" All frequencies:\n";
|
||||
final String[] nrFrequencyRangeDescription = new String[]{
|
||||
" Unknown frequency:\n",
|
||||
" Low frequency (less than 1GHz):\n",
|
||||
" Middle frequency (1GHz to 3GHz):\n",
|
||||
" High frequency (3GHz to 6GHz):\n",
|
||||
" Mmwave frequency (greater than 6GHz):\n"};
|
||||
final String signalStrengthHeader =
|
||||
" Signal Strength Time:\n";
|
||||
final String[] signalStrengthDescription = new String[]{
|
||||
" unknown: ",
|
||||
" poor: ",
|
||||
" moderate: ",
|
||||
" good: ",
|
||||
" great: "};
|
||||
|
||||
final long totalActiveTimesMs = getMobileRadioActiveTime(rawRealtimeMs * 1000,
|
||||
STATS_SINCE_CHARGED) / 1000;
|
||||
|
||||
sb.setLength(0);
|
||||
sb.append(prefix);
|
||||
sb.append("Active Cellular Radio Access Technology Breakdown:");
|
||||
pw.println(sb);
|
||||
|
||||
boolean hasData = false;
|
||||
final int numSignalStrength = CellSignalStrength.getNumSignalStrengthLevels();
|
||||
for (int rat = RADIO_ACCESS_TECHNOLOGY_COUNT - 1; rat >= 0; rat--) {
|
||||
sb.setLength(0);
|
||||
sb.append(prefix);
|
||||
sb.append(" ");
|
||||
sb.append(RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
|
||||
sb.append(":\n");
|
||||
sb.append(prefix);
|
||||
|
||||
final int numFreqLvl =
|
||||
rat == RADIO_ACCESS_TECHNOLOGY_NR ? nrFrequencyRangeDescription.length : 1;
|
||||
for (int freqLvl = numFreqLvl - 1; freqLvl >= 0; freqLvl--) {
|
||||
final int freqDescriptionStart = sb.length();
|
||||
boolean hasFreqData = false;
|
||||
if (rat == RADIO_ACCESS_TECHNOLOGY_NR) {
|
||||
sb.append(nrFrequencyRangeDescription[freqLvl]);
|
||||
} else {
|
||||
sb.append(allFrequenciesHeader);
|
||||
}
|
||||
|
||||
sb.append(prefix);
|
||||
sb.append(signalStrengthHeader);
|
||||
for (int strength = 0; strength < numSignalStrength; strength++) {
|
||||
final long timeMs = getActiveRadioDurationMs(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");
|
||||
}
|
||||
|
||||
if (hasFreqData) {
|
||||
hasData = true;
|
||||
pw.print(sb);
|
||||
sb.setLength(0);
|
||||
sb.append(prefix);
|
||||
} else {
|
||||
// No useful data was printed, rewind sb to before the start of this frequency.
|
||||
sb.setLength(freqDescriptionStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasData) {
|
||||
sb.setLength(0);
|
||||
sb.append(prefix);
|
||||
sb.append(" (no activity)");
|
||||
pw.println(sb);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporary for settings.
|
||||
*/
|
||||
@@ -5269,6 +5393,8 @@ public abstract class BatteryStats implements Parcelable {
|
||||
printControllerActivity(pw, sb, prefix, CELLULAR_CONTROLLER_NAME,
|
||||
getModemControllerActivity(), which);
|
||||
|
||||
printCellularPerRatBreakdown(pw, sb, prefix + " ", rawRealtimeMs);
|
||||
|
||||
pw.print(" Cellular data received: "); pw.println(formatBytesLocked(mobileRxTotalBytes));
|
||||
pw.print(" Cellular data sent: "); pw.println(formatBytesLocked(mobileTxTotalBytes));
|
||||
pw.print(" Cellular packets received: "); pw.println(mobileRxTotalPackets);
|
||||
|
||||
@@ -113,7 +113,7 @@ interface IBatteryStats {
|
||||
void notePhoneOn();
|
||||
void notePhoneOff();
|
||||
void notePhoneSignalStrength(in SignalStrength signalStrength);
|
||||
void notePhoneDataConnectionState(int dataType, boolean hasData, int serviceType);
|
||||
void notePhoneDataConnectionState(int dataType, boolean hasData, int serviceType, int nrFrequency);
|
||||
void notePhoneState(int phoneState);
|
||||
void noteWifiOn();
|
||||
void noteWifiOff();
|
||||
|
||||
@@ -69,10 +69,14 @@ import android.os.connectivity.GpsBatteryStats;
|
||||
import android.os.connectivity.WifiActivityEnergyInfo;
|
||||
import android.os.connectivity.WifiBatteryStats;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.Annotation.NetworkType;
|
||||
import android.telephony.CellSignalStrength;
|
||||
import android.telephony.CellSignalStrengthLte;
|
||||
import android.telephony.CellSignalStrengthNr;
|
||||
import android.telephony.DataConnectionRealTimeInfo;
|
||||
import android.telephony.ModemActivityInfo;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.ServiceState.RegState;
|
||||
import android.telephony.SignalStrength;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
@@ -935,6 +939,119 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
final StopwatchTimer[] mPhoneDataConnectionsTimer =
|
||||
new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
|
||||
|
||||
@RadioAccessTechnology
|
||||
int mActiveRat = RADIO_ACCESS_TECHNOLOGY_OTHER;
|
||||
|
||||
private static class RadioAccessTechnologyBatteryStats {
|
||||
/**
|
||||
* This RAT is currently being used.
|
||||
*/
|
||||
private boolean mActive = false;
|
||||
/**
|
||||
* Current active frequency range for this RAT.
|
||||
*/
|
||||
@ServiceState.FrequencyRange
|
||||
private int mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
|
||||
/**
|
||||
* Current signal strength for this RAT.
|
||||
*/
|
||||
private int mSignalStrength = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
|
||||
/**
|
||||
* Timers for each combination of frequency range and signal strength.
|
||||
*/
|
||||
public final StopwatchTimer[][] perStateTimers;
|
||||
|
||||
RadioAccessTechnologyBatteryStats(int freqCount, Clock clock, TimeBase timeBase) {
|
||||
perStateTimers =
|
||||
new StopwatchTimer[freqCount][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] = new StopwatchTimer(clock, null, -1, null, timeBase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Note this RAT is currently being used.
|
||||
*/
|
||||
public void noteActive(boolean active, long elapsedRealtimeMs) {
|
||||
if (mActive == active) return;
|
||||
mActive = active;
|
||||
if (mActive) {
|
||||
perStateTimers[mFrequencyRange][mSignalStrength].startRunningLocked(
|
||||
elapsedRealtimeMs);
|
||||
} else {
|
||||
perStateTimers[mFrequencyRange][mSignalStrength].stopRunningLocked(
|
||||
elapsedRealtimeMs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Note current frequency range has changed.
|
||||
*/
|
||||
public void noteFrequencyRange(@ServiceState.FrequencyRange int frequencyRange,
|
||||
long elapsedRealtimeMs) {
|
||||
if (mFrequencyRange == frequencyRange) return;
|
||||
|
||||
if (!mActive) {
|
||||
// RAT not in use, note the frequency change and move on.
|
||||
mFrequencyRange = frequencyRange;
|
||||
return;
|
||||
}
|
||||
perStateTimers[mFrequencyRange][mSignalStrength].stopRunningLocked(elapsedRealtimeMs);
|
||||
perStateTimers[frequencyRange][mSignalStrength].startRunningLocked(elapsedRealtimeMs);
|
||||
mFrequencyRange = frequencyRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note current signal strength has changed.
|
||||
*/
|
||||
public void noteSignalStrength(int signalStrength, long elapsedRealtimeMs) {
|
||||
if (mSignalStrength == signalStrength) return;
|
||||
|
||||
if (!mActive) {
|
||||
// RAT not in use, note the signal strength change and move on.
|
||||
mSignalStrength = signalStrength;
|
||||
return;
|
||||
}
|
||||
perStateTimers[mFrequencyRange][mSignalStrength].stopRunningLocked(elapsedRealtimeMs);
|
||||
perStateTimers[mFrequencyRange][signalStrength].startRunningLocked(elapsedRealtimeMs);
|
||||
mSignalStrength = signalStrength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset display timers.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of frequency ranges, keep in sync with {@link ServiceState.FrequencyRange}
|
||||
*/
|
||||
private static final int NR_FREQUENCY_COUNT = 5;
|
||||
|
||||
RadioAccessTechnologyBatteryStats[] mPerRatBatteryStats =
|
||||
new RadioAccessTechnologyBatteryStats[RADIO_ACCESS_TECHNOLOGY_COUNT];
|
||||
|
||||
@GuardedBy("this")
|
||||
private RadioAccessTechnologyBatteryStats getRatBatteryStatsLocked(
|
||||
@RadioAccessTechnology int rat) {
|
||||
RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
|
||||
if (stats == null) {
|
||||
final int freqCount = rat == RADIO_ACCESS_TECHNOLOGY_NR ? NR_FREQUENCY_COUNT : 1;
|
||||
stats = new RadioAccessTechnologyBatteryStats(freqCount, mClock, mOnBatteryTimeBase);
|
||||
mPerRatBatteryStats[rat] = stats;
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
||||
final LongSamplingCounter[] mNetworkByteActivityCounters =
|
||||
new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
|
||||
|
||||
@@ -5886,6 +6003,10 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
+ Integer.toHexString(mHistoryCur.states));
|
||||
addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
|
||||
mMobileRadioPowerState = powerState;
|
||||
|
||||
// Inform current RatBatteryStats that the modem active state might have changed.
|
||||
getRatBatteryStatsLocked(mActiveRat).noteActive(active, elapsedRealtimeMs);
|
||||
|
||||
if (active) {
|
||||
mMobileRadioActiveTimer.startRunningLocked(elapsedRealtimeMs);
|
||||
mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtimeMs);
|
||||
@@ -6307,21 +6428,86 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
@GuardedBy("this")
|
||||
public void notePhoneSignalStrengthLocked(SignalStrength signalStrength,
|
||||
long elapsedRealtimeMs, long uptimeMs) {
|
||||
// Bin the strength.
|
||||
int bin = signalStrength.getLevel();
|
||||
updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin,
|
||||
final int overallSignalStrength = signalStrength.getLevel();
|
||||
final SparseIntArray perRatSignalStrength = new SparseIntArray(
|
||||
BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT);
|
||||
|
||||
// Extract signal strength level for each RAT.
|
||||
final List<CellSignalStrength> cellSignalStrengths =
|
||||
signalStrength.getCellSignalStrengths();
|
||||
final int size = cellSignalStrengths.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
CellSignalStrength cellSignalStrength = cellSignalStrengths.get(i);
|
||||
// Map each CellSignalStrength to a BatteryStats.RadioAccessTechnology
|
||||
final int ratType;
|
||||
final int level;
|
||||
if (cellSignalStrength instanceof CellSignalStrengthNr) {
|
||||
ratType = RADIO_ACCESS_TECHNOLOGY_NR;
|
||||
level = cellSignalStrength.getLevel();
|
||||
} else if (cellSignalStrength instanceof CellSignalStrengthLte) {
|
||||
ratType = RADIO_ACCESS_TECHNOLOGY_LTE;
|
||||
level = cellSignalStrength.getLevel();
|
||||
} else {
|
||||
ratType = RADIO_ACCESS_TECHNOLOGY_OTHER;
|
||||
level = cellSignalStrength.getLevel();
|
||||
}
|
||||
|
||||
// According to SignalStrength#getCellSignalStrengths(), multiple of the same
|
||||
// cellSignalStrength can be present. Just take the highest level one for each RAT.
|
||||
if (perRatSignalStrength.get(ratType, -1) < level) {
|
||||
perRatSignalStrength.put(ratType, level);
|
||||
}
|
||||
}
|
||||
|
||||
notePhoneSignalStrengthLocked(overallSignalStrength, perRatSignalStrength,
|
||||
elapsedRealtimeMs, uptimeMs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note phone signal strength change, including per RAT signal strength.
|
||||
*
|
||||
* @param signalStrength overall signal strength {@see SignalStrength#getLevel()}
|
||||
* @param perRatSignalStrength signal strength of available RATs
|
||||
*/
|
||||
@GuardedBy("this")
|
||||
public void notePhoneSignalStrengthLocked(int signalStrength,
|
||||
SparseIntArray perRatSignalStrength) {
|
||||
notePhoneSignalStrengthLocked(signalStrength, perRatSignalStrength,
|
||||
mClock.elapsedRealtime(), mClock.uptimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* Note phone signal strength change, including per RAT signal strength.
|
||||
*
|
||||
* @param signalStrength overall signal strength {@see SignalStrength#getLevel()}
|
||||
* @param perRatSignalStrength signal strength of available RATs
|
||||
*/
|
||||
@GuardedBy("this")
|
||||
public void notePhoneSignalStrengthLocked(int signalStrength,
|
||||
SparseIntArray perRatSignalStrength,
|
||||
long elapsedRealtimeMs, long uptimeMs) {
|
||||
// Note each RAT's signal strength.
|
||||
final int size = perRatSignalStrength.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final int rat = perRatSignalStrength.keyAt(i);
|
||||
final int ratSignalStrength = perRatSignalStrength.valueAt(i);
|
||||
getRatBatteryStatsLocked(rat).noteSignalStrength(ratSignalStrength, elapsedRealtimeMs);
|
||||
}
|
||||
updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, signalStrength,
|
||||
elapsedRealtimeMs, uptimeMs);
|
||||
}
|
||||
|
||||
@UnsupportedAppUsage
|
||||
@GuardedBy("this")
|
||||
public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType) {
|
||||
notePhoneDataConnectionStateLocked(dataType, hasData, serviceType,
|
||||
public void notePhoneDataConnectionStateLocked(@NetworkType int dataType, boolean hasData,
|
||||
@RegState int serviceType, @ServiceState.FrequencyRange int nrFrequency) {
|
||||
notePhoneDataConnectionStateLocked(dataType, hasData, serviceType, nrFrequency,
|
||||
mClock.elapsedRealtime(), mClock.uptimeMillis());
|
||||
}
|
||||
|
||||
@GuardedBy("this")
|
||||
public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType,
|
||||
public void notePhoneDataConnectionStateLocked(@NetworkType int dataType, boolean hasData,
|
||||
@RegState int serviceType, @ServiceState.FrequencyRange int nrFrequency,
|
||||
long elapsedRealtimeMs, long uptimeMs) {
|
||||
// BatteryStats uses 0 to represent no network type.
|
||||
// Telephony does not have a concept of no network type, and uses 0 to represent unknown.
|
||||
@@ -6344,6 +6530,13 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final int newRat = mapNetworkTypeToRadioAccessTechnology(bin);
|
||||
if (newRat == RADIO_ACCESS_TECHNOLOGY_NR) {
|
||||
// Note possible frequency change for the NR RAT.
|
||||
getRatBatteryStatsLocked(newRat).noteFrequencyRange(nrFrequency, elapsedRealtimeMs);
|
||||
}
|
||||
|
||||
if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
|
||||
if (mPhoneDataConnectionType != bin) {
|
||||
mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
|
||||
@@ -6357,6 +6550,45 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
}
|
||||
mPhoneDataConnectionType = bin;
|
||||
mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtimeMs);
|
||||
|
||||
if (mActiveRat != newRat) {
|
||||
getRatBatteryStatsLocked(mActiveRat).noteActive(false, elapsedRealtimeMs);
|
||||
mActiveRat = newRat;
|
||||
}
|
||||
final boolean modemActive = mMobileRadioActiveTimer.isRunningLocked();
|
||||
getRatBatteryStatsLocked(newRat).noteActive(modemActive, elapsedRealtimeMs);
|
||||
}
|
||||
}
|
||||
|
||||
@RadioAccessTechnology
|
||||
private static int mapNetworkTypeToRadioAccessTechnology(@NetworkType int dataType) {
|
||||
switch (dataType) {
|
||||
case TelephonyManager.NETWORK_TYPE_NR:
|
||||
return RADIO_ACCESS_TECHNOLOGY_NR;
|
||||
case TelephonyManager.NETWORK_TYPE_LTE:
|
||||
return RADIO_ACCESS_TECHNOLOGY_LTE;
|
||||
case TelephonyManager.NETWORK_TYPE_UNKNOWN: //fallthrough
|
||||
case TelephonyManager.NETWORK_TYPE_GPRS: //fallthrough
|
||||
case TelephonyManager.NETWORK_TYPE_EDGE: //fallthrough
|
||||
case TelephonyManager.NETWORK_TYPE_UMTS: //fallthrough
|
||||
case TelephonyManager.NETWORK_TYPE_CDMA: //fallthrough
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_0: //fallthrough
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_A: //fallthrough
|
||||
case TelephonyManager.NETWORK_TYPE_1xRTT: //fallthrough
|
||||
case TelephonyManager.NETWORK_TYPE_HSDPA: //fallthrough
|
||||
case TelephonyManager.NETWORK_TYPE_HSUPA: //fallthrough
|
||||
case TelephonyManager.NETWORK_TYPE_HSPA: //fallthrough
|
||||
case TelephonyManager.NETWORK_TYPE_IDEN: //fallthrough
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_B: //fallthrough
|
||||
case TelephonyManager.NETWORK_TYPE_EHRPD: //fallthrough
|
||||
case TelephonyManager.NETWORK_TYPE_HSPAP: //fallthrough
|
||||
case TelephonyManager.NETWORK_TYPE_GSM: //fallthrough
|
||||
case TelephonyManager.NETWORK_TYPE_TD_SCDMA: //fallthrough
|
||||
case TelephonyManager.NETWORK_TYPE_IWLAN: //fallthrough
|
||||
return RADIO_ACCESS_TECHNOLOGY_OTHER;
|
||||
default:
|
||||
Slog.w(TAG, "Unhandled NetworkType (" + dataType + "), mapping to OTHER");
|
||||
return RADIO_ACCESS_TECHNOLOGY_OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7731,6 +7963,23 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
return mPhoneDataConnectionsTimer[dataType];
|
||||
}
|
||||
|
||||
@Override public long getActiveRadioDurationMs(@RadioAccessTechnology int rat,
|
||||
@ServiceState.FrequencyRange int frequencyRange, int signalStrength,
|
||||
long elapsedRealtimeMs) {
|
||||
final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
|
||||
if (stats == null) return 0L;
|
||||
|
||||
final int freqCount = stats.perStateTimers.length;
|
||||
if (frequencyRange < 0 || frequencyRange >= freqCount) return 0L;
|
||||
|
||||
final StopwatchTimer[] strengthTimers = stats.perStateTimers[frequencyRange];
|
||||
final int strengthCount = strengthTimers.length;
|
||||
if (signalStrength < 0 || signalStrength >= strengthCount) return 0L;
|
||||
|
||||
return stats.perStateTimers[frequencyRange][signalStrength].getTotalTimeLocked(
|
||||
elapsedRealtimeMs * 1000, STATS_SINCE_CHARGED) / 1000;
|
||||
}
|
||||
|
||||
@UnsupportedAppUsage
|
||||
@Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
|
||||
return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
|
||||
@@ -12553,6 +12802,11 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
mNetworkByteActivityCounters[i].reset(false, elapsedRealtimeUs);
|
||||
mNetworkPacketActivityCounters[i].reset(false, elapsedRealtimeUs);
|
||||
}
|
||||
for (int i = 0; i < RADIO_ACCESS_TECHNOLOGY_COUNT; i++) {
|
||||
final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[i];
|
||||
if (stats == null) continue;
|
||||
stats.reset(elapsedRealtimeUs);
|
||||
}
|
||||
mMobileRadioActiveTimer.reset(false, elapsedRealtimeUs);
|
||||
mMobileRadioActivePerAppTimer.reset(false, elapsedRealtimeUs);
|
||||
mMobileRadioActiveAdjustedTime.reset(false, elapsedRealtimeUs);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.internal.os;
|
||||
|
||||
import static android.os.BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS;
|
||||
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;
|
||||
|
||||
@@ -30,6 +31,12 @@ import android.os.BatteryStats.Uid.Sensor;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import android.os.WorkSource;
|
||||
import android.telephony.Annotation;
|
||||
import android.telephony.CellSignalStrength;
|
||||
import android.telephony.DataConnectionRealTimeInfo;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.SparseIntArray;
|
||||
import android.util.SparseLongArray;
|
||||
import android.view.Display;
|
||||
|
||||
@@ -1165,6 +1172,185 @@ public class BatteryStatsNoteTest extends TestCase {
|
||||
"D", totalBlameA, totalBlameB, uid1, blame1A, blame1B, uid2, blame2A, blame2B, bi);
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testGetPerStateActiveRadioDurationMs() {
|
||||
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 frequencyCount = ServiceState.FREQUENCY_RANGE_MMWAVE + 1;
|
||||
final int txLevelCount = CellSignalStrength.getNumSignalStrengthLevels();
|
||||
|
||||
final long[][][] expectedDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
|
||||
for (int rat = 0; rat < ratCount; rat++) {
|
||||
for (int freq = 0; freq < frequencyCount; freq++) {
|
||||
for (int txLvl = 0; txLvl < txLevelCount; txLvl++) {
|
||||
expectedDurationsMs[rat][freq][txLvl] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
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 currentRat = state.currentRat;
|
||||
final int currentFrequencyRange =
|
||||
currentRat == RADIO_ACCESS_TECHNOLOGY_NR ? state.currentFrequencyRange : 0;
|
||||
int currentSignalStrength = state.currentSignalStrengths.get(currentRat);
|
||||
expectedDurationsMs[currentRat][currentFrequencyRange][currentSignalStrength] += inc;
|
||||
};
|
||||
|
||||
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, bi, state.currentTimeMs);
|
||||
|
||||
// While not on battery, the timers should not increase.
|
||||
state.setModemActive(true);
|
||||
incrementTime.accept(100);
|
||||
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
|
||||
|
||||
state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
|
||||
incrementTime.accept(200);
|
||||
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
|
||||
|
||||
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR,
|
||||
CellSignalStrength.SIGNAL_STRENGTH_GOOD);
|
||||
incrementTime.accept(500);
|
||||
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
|
||||
|
||||
state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_MMWAVE);
|
||||
incrementTime.accept(300);
|
||||
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
|
||||
|
||||
state.setRatType(TelephonyManager.NETWORK_TYPE_LTE,
|
||||
BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE);
|
||||
incrementTime.accept(400);
|
||||
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
|
||||
|
||||
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
|
||||
CellSignalStrength.SIGNAL_STRENGTH_MODERATE);
|
||||
incrementTime.accept(500);
|
||||
checkPerStateActiveRadioDurations(expectedDurationsMs, 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);
|
||||
|
||||
// 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);
|
||||
|
||||
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
|
||||
CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
|
||||
incrementTime.accept(800);
|
||||
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
|
||||
|
||||
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
|
||||
CellSignalStrength.SIGNAL_STRENGTH_GOOD);
|
||||
incrementTime.accept(900);
|
||||
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
|
||||
|
||||
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
|
||||
CellSignalStrength.SIGNAL_STRENGTH_GREAT);
|
||||
incrementTime.accept(1000);
|
||||
checkPerStateActiveRadioDurations(expectedDurationsMs, 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// Noting frequency change should not affect non NR Rat.
|
||||
state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_HIGH);
|
||||
incrementTime.accept(1300);
|
||||
checkPerStateActiveRadioDurations(expectedDurationsMs, 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);
|
||||
|
||||
// Noting frequency change should not affect non NR Rat.
|
||||
state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_LOW);
|
||||
incrementTime.accept(1500);
|
||||
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
|
||||
|
||||
// Modem no longer active, should not be tracking any more.
|
||||
state.setModemActive(false);
|
||||
incrementTime.accept(1500);
|
||||
checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
|
||||
|
||||
}
|
||||
|
||||
private void setFgState(int uid, boolean fgOn, MockBatteryStatsImpl bi) {
|
||||
// Note that noteUidProcessStateLocked uses ActivityManager process states.
|
||||
if (fgOn) {
|
||||
@@ -1238,4 +1424,30 @@ public class BatteryStatsNoteTest extends TestCase {
|
||||
bi.getScreenBrightnessTime(bin, currentTimeMs * 1000, STATS_SINCE_CHARGED));
|
||||
}
|
||||
}
|
||||
|
||||
private void checkPerStateActiveRadioDurations(long[][][] expectedDurationsMs,
|
||||
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[] expectedFreqDurationsMs = expectedRatDurationsMs[freq];
|
||||
for (int strength = 0; strength < expectedFreqDurationsMs.length; strength++) {
|
||||
final long expectedSignalStrengthDurationMs = expectedFreqDurationsMs[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);
|
||||
|
||||
assertEquals(sb.toString(), expectedSignalStrengthDurationMs, actualDurationMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1365,7 +1365,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
||||
}
|
||||
|
||||
public void notePhoneDataConnectionState(final int dataType, final boolean hasData,
|
||||
final int serviceType) {
|
||||
final int serviceType, final int nrFrequency) {
|
||||
enforceCallingPermission();
|
||||
synchronized (mLock) {
|
||||
final long elapsedRealtime = SystemClock.elapsedRealtime();
|
||||
@@ -1373,7 +1373,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
||||
mHandler.post(() -> {
|
||||
synchronized (mStats) {
|
||||
mStats.notePhoneDataConnectionStateLocked(dataType, hasData, serviceType,
|
||||
elapsedRealtime, uptime);
|
||||
nrFrequency, elapsedRealtime, uptime);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ public class DataConnectionStats extends BroadcastReceiver {
|
||||
}
|
||||
try {
|
||||
mBatteryStats.notePhoneDataConnectionState(networkType, visible,
|
||||
mServiceState.getState());
|
||||
mServiceState.getState(), mServiceState.getNrFrequencyRange());
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Error noting data connection state", e);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user