564 lines
20 KiB
Java
564 lines
20 KiB
Java
/*
|
|
* Copyright (C) 2021 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.internal.power;
|
|
|
|
import android.annotation.IntDef;
|
|
import android.os.BatteryStats;
|
|
import android.telephony.ModemActivityInfo;
|
|
import android.telephony.ServiceState;
|
|
import android.telephony.TelephonyManager;
|
|
import android.util.Log;
|
|
import android.util.Slog;
|
|
import android.util.SparseArray;
|
|
import android.util.SparseDoubleArray;
|
|
|
|
import com.android.internal.os.PowerProfile;
|
|
import com.android.internal.util.XmlUtils;
|
|
|
|
import org.xmlpull.v1.XmlPullParser;
|
|
import org.xmlpull.v1.XmlPullParserException;
|
|
|
|
import java.io.IOException;
|
|
import java.io.PrintWriter;
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
import java.util.Arrays;
|
|
|
|
/**
|
|
* ModemPowerProfile for handling the modem element in the power_profile.xml
|
|
*/
|
|
@android.ravenwood.annotation.RavenwoodKeepWholeClass
|
|
public class ModemPowerProfile {
|
|
private static final String TAG = "ModemPowerProfile";
|
|
|
|
private static final String TAG_SLEEP = "sleep";
|
|
private static final String TAG_IDLE = "idle";
|
|
private static final String TAG_ACTIVE = "active";
|
|
private static final String TAG_RECEIVE = "receive";
|
|
private static final String TAG_TRANSMIT = "transmit";
|
|
private static final String ATTR_RAT = "rat";
|
|
private static final String ATTR_NR_FREQUENCY = "nrFrequency";
|
|
private static final String ATTR_LEVEL = "level";
|
|
|
|
/**
|
|
* A flattened list of the modem power constant extracted from the given XML parser.
|
|
*
|
|
* The bitfields of a key describes what its corresponding power constant represents:
|
|
* [31:28] - {@link ModemDrainType} (max count = 16).
|
|
* [27:24] - {@link ModemTxLevel} (only for {@link MODEM_DRAIN_TYPE_TX}) (max count = 16).
|
|
* [23:20] - {@link ModemRatType} (max count = 16).
|
|
* [19:16] - {@link ModemNrFrequencyRange} (only for {@link MODEM_RAT_TYPE_NR})
|
|
* (max count = 16).
|
|
* [15:0] - RESERVED
|
|
*/
|
|
private final SparseDoubleArray mPowerConstants = new SparseDoubleArray();
|
|
|
|
private static final int MODEM_DRAIN_TYPE_MASK = 0xF000_0000;
|
|
private static final int MODEM_TX_LEVEL_MASK = 0x0F00_0000;
|
|
private static final int MODEM_RAT_TYPE_MASK = 0x00F0_0000;
|
|
private static final int MODEM_NR_FREQUENCY_RANGE_MASK = 0x000F_0000;
|
|
|
|
/**
|
|
* Corresponds to the overall modem battery drain while asleep.
|
|
*/
|
|
public static final int MODEM_DRAIN_TYPE_SLEEP = 0x0000_0000;
|
|
|
|
/**
|
|
* Corresponds to the overall modem battery drain while idle.
|
|
*/
|
|
public static final int MODEM_DRAIN_TYPE_IDLE = 0x1000_0000;
|
|
|
|
/**
|
|
* Corresponds to the modem battery drain while receiving data. A specific Rx battery drain
|
|
* power constant can be selected using a bitwise OR (|) with {@link ModemRatType} and
|
|
* {@link ModemNrFrequencyRange} (when applicable).
|
|
*/
|
|
public static final int MODEM_DRAIN_TYPE_RX = 0x2000_0000;
|
|
|
|
/**
|
|
* Corresponds to the modem battery drain while receiving data.
|
|
* {@link ModemTxLevel} must be specified with this drain type.
|
|
* Specific Tx battery drain power constanta can be selected using a bitwise OR (|) with
|
|
* {@link ModemRatType} and {@link ModemNrFrequencyRange} (when applicable).
|
|
*/
|
|
public static final int MODEM_DRAIN_TYPE_TX = 0x3000_0000;
|
|
|
|
private static final int IGNORE = -1;
|
|
|
|
@IntDef(prefix = {"MODEM_DRAIN_TYPE_"}, value = {
|
|
MODEM_DRAIN_TYPE_SLEEP,
|
|
MODEM_DRAIN_TYPE_IDLE,
|
|
MODEM_DRAIN_TYPE_RX,
|
|
MODEM_DRAIN_TYPE_TX,
|
|
})
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
public @interface ModemDrainType {
|
|
}
|
|
|
|
|
|
private static final SparseArray<String> MODEM_DRAIN_TYPE_NAMES = new SparseArray<>(4);
|
|
static {
|
|
MODEM_DRAIN_TYPE_NAMES.put(MODEM_DRAIN_TYPE_SLEEP, "SLEEP");
|
|
MODEM_DRAIN_TYPE_NAMES.put(MODEM_DRAIN_TYPE_IDLE, "IDLE");
|
|
MODEM_DRAIN_TYPE_NAMES.put(MODEM_DRAIN_TYPE_RX, "RX");
|
|
MODEM_DRAIN_TYPE_NAMES.put(MODEM_DRAIN_TYPE_TX, "TX");
|
|
}
|
|
|
|
/**
|
|
* Corresponds to {@link ModemActivityInfo#TX_POWER_LEVEL_0}.
|
|
*/
|
|
|
|
public static final int MODEM_TX_LEVEL_0 = 0x0000_0000;
|
|
|
|
/**
|
|
* Corresponds to {@link ModemActivityInfo#TX_POWER_LEVEL_1}.
|
|
*/
|
|
|
|
public static final int MODEM_TX_LEVEL_1 = 0x0100_0000;
|
|
|
|
/**
|
|
* Corresponds to {@link ModemActivityInfo#TX_POWER_LEVEL_2}.
|
|
*/
|
|
|
|
public static final int MODEM_TX_LEVEL_2 = 0x0200_0000;
|
|
|
|
/**
|
|
* Corresponds to {@link ModemActivityInfo#TX_POWER_LEVEL_3}.
|
|
*/
|
|
|
|
public static final int MODEM_TX_LEVEL_3 = 0x0300_0000;
|
|
|
|
/**
|
|
* Corresponds to {@link ModemActivityInfo#TX_POWER_LEVEL_4}.
|
|
*/
|
|
|
|
public static final int MODEM_TX_LEVEL_4 = 0x0400_0000;
|
|
|
|
private static final int MODEM_TX_LEVEL_COUNT = 5;
|
|
|
|
@IntDef(prefix = {"MODEM_TX_LEVEL_"}, value = {
|
|
MODEM_TX_LEVEL_0,
|
|
MODEM_TX_LEVEL_1,
|
|
MODEM_TX_LEVEL_2,
|
|
MODEM_TX_LEVEL_3,
|
|
MODEM_TX_LEVEL_4,
|
|
})
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
public @interface ModemTxLevel {
|
|
}
|
|
|
|
private static final SparseArray<String> MODEM_TX_LEVEL_NAMES = new SparseArray<>(5);
|
|
static {
|
|
MODEM_TX_LEVEL_NAMES.put(MODEM_TX_LEVEL_0, "0");
|
|
MODEM_TX_LEVEL_NAMES.put(MODEM_TX_LEVEL_1, "1");
|
|
MODEM_TX_LEVEL_NAMES.put(MODEM_TX_LEVEL_2, "2");
|
|
MODEM_TX_LEVEL_NAMES.put(MODEM_TX_LEVEL_3, "3");
|
|
MODEM_TX_LEVEL_NAMES.put(MODEM_TX_LEVEL_4, "4");
|
|
}
|
|
|
|
private static final int[] MODEM_TX_LEVEL_MAP = new int[]{
|
|
MODEM_TX_LEVEL_0,
|
|
MODEM_TX_LEVEL_1,
|
|
MODEM_TX_LEVEL_2,
|
|
MODEM_TX_LEVEL_3,
|
|
MODEM_TX_LEVEL_4};
|
|
|
|
/**
|
|
* Fallback for any active modem usage that does not match specified Radio Access Technology
|
|
* (RAT) power constants.
|
|
*/
|
|
public static final int MODEM_RAT_TYPE_DEFAULT = 0x0000_0000;
|
|
|
|
/**
|
|
* Corresponds to active modem usage on 4G {@link TelephonyManager#NETWORK_TYPE_LTE} RAT.
|
|
*/
|
|
public static final int MODEM_RAT_TYPE_LTE = 0x0010_0000;
|
|
|
|
/**
|
|
* Corresponds to active modem usage on 5G {@link TelephonyManager#NETWORK_TYPE_NR} RAT.
|
|
*/
|
|
public static final int MODEM_RAT_TYPE_NR = 0x0020_0000;
|
|
|
|
@IntDef(prefix = {"MODEM_RAT_TYPE_"}, value = {
|
|
MODEM_RAT_TYPE_DEFAULT,
|
|
MODEM_RAT_TYPE_LTE,
|
|
MODEM_RAT_TYPE_NR,
|
|
})
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
public @interface ModemRatType {
|
|
}
|
|
|
|
private static final SparseArray<String> MODEM_RAT_TYPE_NAMES = new SparseArray<>(3);
|
|
static {
|
|
MODEM_RAT_TYPE_NAMES.put(MODEM_RAT_TYPE_DEFAULT, "DEFAULT");
|
|
MODEM_RAT_TYPE_NAMES.put(MODEM_RAT_TYPE_LTE, "LTE");
|
|
MODEM_RAT_TYPE_NAMES.put(MODEM_RAT_TYPE_NR, "NR");
|
|
}
|
|
|
|
/**
|
|
* Fallback for any active 5G modem usage that does not match specified NR frequency power
|
|
* constants.
|
|
*/
|
|
public static final int MODEM_NR_FREQUENCY_RANGE_DEFAULT = 0x0000_0000;
|
|
|
|
/**
|
|
* Corresponds to active NR modem usage on {@link ServiceState#FREQUENCY_RANGE_LOW}.
|
|
*/
|
|
public static final int MODEM_NR_FREQUENCY_RANGE_LOW = 0x0001_0000;
|
|
|
|
/**
|
|
* Corresponds to active NR modem usage on {@link ServiceState#FREQUENCY_RANGE_MID}.
|
|
*/
|
|
public static final int MODEM_NR_FREQUENCY_RANGE_MID = 0x0002_0000;
|
|
|
|
/**
|
|
* Corresponds to active NR modem usage on {@link ServiceState#FREQUENCY_RANGE_HIGH}.
|
|
*/
|
|
public static final int MODEM_NR_FREQUENCY_RANGE_HIGH = 0x0003_0000;
|
|
|
|
/**
|
|
* Corresponds to active NR modem usage on {@link ServiceState#FREQUENCY_RANGE_MMWAVE}.
|
|
*/
|
|
public static final int MODEM_NR_FREQUENCY_RANGE_MMWAVE = 0x0004_0000;
|
|
|
|
@IntDef(prefix = {"MODEM_NR_FREQUENCY_RANGE_"}, value = {
|
|
MODEM_RAT_TYPE_DEFAULT,
|
|
MODEM_NR_FREQUENCY_RANGE_LOW,
|
|
MODEM_NR_FREQUENCY_RANGE_MID,
|
|
MODEM_NR_FREQUENCY_RANGE_HIGH,
|
|
MODEM_NR_FREQUENCY_RANGE_MMWAVE,
|
|
})
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
public @interface ModemNrFrequencyRange {
|
|
}
|
|
private static final SparseArray<String> MODEM_NR_FREQUENCY_RANGE_NAMES = new SparseArray<>(5);
|
|
static {
|
|
MODEM_NR_FREQUENCY_RANGE_NAMES.put(MODEM_NR_FREQUENCY_RANGE_DEFAULT, "DEFAULT");
|
|
MODEM_NR_FREQUENCY_RANGE_NAMES.put(MODEM_NR_FREQUENCY_RANGE_LOW, "LOW");
|
|
MODEM_NR_FREQUENCY_RANGE_NAMES.put(MODEM_NR_FREQUENCY_RANGE_MID, "MID");
|
|
MODEM_NR_FREQUENCY_RANGE_NAMES.put(MODEM_NR_FREQUENCY_RANGE_HIGH, "HIGH");
|
|
MODEM_NR_FREQUENCY_RANGE_NAMES.put(MODEM_NR_FREQUENCY_RANGE_MMWAVE, "MMWAVE");
|
|
}
|
|
|
|
public ModemPowerProfile() {
|
|
}
|
|
|
|
/**
|
|
* Generates a ModemPowerProfile object from the <modem /> element of a power_profile.xml
|
|
*/
|
|
public void parseFromXml(XmlPullParser parser) throws IOException,
|
|
XmlPullParserException {
|
|
final int depth = parser.getDepth();
|
|
while (XmlUtils.nextElementWithin(parser, depth)) {
|
|
final String name = parser.getName();
|
|
switch (name) {
|
|
case TAG_SLEEP:
|
|
if (parser.next() != XmlPullParser.TEXT) {
|
|
continue;
|
|
}
|
|
final String sleepDrain = parser.getText();
|
|
setPowerConstant(MODEM_DRAIN_TYPE_SLEEP, sleepDrain);
|
|
break;
|
|
case TAG_IDLE:
|
|
if (parser.next() != XmlPullParser.TEXT) {
|
|
continue;
|
|
}
|
|
final String idleDrain = parser.getText();
|
|
setPowerConstant(MODEM_DRAIN_TYPE_IDLE, idleDrain);
|
|
break;
|
|
case TAG_ACTIVE:
|
|
parseActivePowerConstantsFromXml(parser);
|
|
break;
|
|
default:
|
|
Slog.e(TAG, "Unexpected element parsed: " + name);
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Parse the <active /> XML element */
|
|
private void parseActivePowerConstantsFromXml(XmlPullParser parser)
|
|
throws IOException, XmlPullParserException {
|
|
// Parse attributes to get the type of active modem usage the power constants are for.
|
|
final int ratType;
|
|
final int nrfType;
|
|
try {
|
|
ratType = getTypeFromAttribute(parser, ATTR_RAT, MODEM_RAT_TYPE_NAMES);
|
|
if (ratType == MODEM_RAT_TYPE_NR) {
|
|
nrfType = getTypeFromAttribute(parser, ATTR_NR_FREQUENCY,
|
|
MODEM_NR_FREQUENCY_RANGE_NAMES);
|
|
} else {
|
|
nrfType = 0;
|
|
}
|
|
} catch (IllegalArgumentException iae) {
|
|
Slog.e(TAG, "Failed parse to active modem power constants", iae);
|
|
return;
|
|
}
|
|
|
|
// Parse and populate the active modem use power constants.
|
|
final int depth = parser.getDepth();
|
|
while (XmlUtils.nextElementWithin(parser, depth)) {
|
|
final String name = parser.getName();
|
|
switch (name) {
|
|
case TAG_RECEIVE:
|
|
if (parser.next() != XmlPullParser.TEXT) {
|
|
continue;
|
|
}
|
|
final String rxDrain = parser.getText();
|
|
final int rxKey = MODEM_DRAIN_TYPE_RX | ratType | nrfType;
|
|
setPowerConstant(rxKey, rxDrain);
|
|
break;
|
|
case TAG_TRANSMIT:
|
|
final int level = XmlUtils.readIntAttribute(parser, ATTR_LEVEL, -1);
|
|
if (parser.next() != XmlPullParser.TEXT) {
|
|
continue;
|
|
}
|
|
final String txDrain = parser.getText();
|
|
if (level < 0 || level >= MODEM_TX_LEVEL_COUNT) {
|
|
Slog.e(TAG,
|
|
"Unexpected tx level: " + level + ". Must be between 0 and " + (
|
|
MODEM_TX_LEVEL_COUNT - 1));
|
|
continue;
|
|
}
|
|
final int modemTxLevel = MODEM_TX_LEVEL_MAP[level];
|
|
final int txKey = MODEM_DRAIN_TYPE_TX | modemTxLevel | ratType | nrfType;
|
|
setPowerConstant(txKey, txDrain);
|
|
break;
|
|
default:
|
|
Slog.e(TAG, "Unexpected element parsed: " + name);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static int getTypeFromAttribute(XmlPullParser parser, String attr,
|
|
SparseArray<String> names) {
|
|
final String value = XmlUtils.readStringAttribute(parser, attr);
|
|
if (value == null) {
|
|
// Attribute was not specified, just use the default.
|
|
return 0;
|
|
}
|
|
int index = -1;
|
|
final int size = names.size();
|
|
// Manual linear search for string. (SparseArray uses == not equals.)
|
|
for (int i = 0; i < size; i++) {
|
|
if (value.equals(names.valueAt(i))) {
|
|
index = i;
|
|
}
|
|
}
|
|
if (index < 0) {
|
|
final String[] stringNames = new String[size];
|
|
for (int i = 0; i < size; i++) {
|
|
stringNames[i] = names.valueAt(i);
|
|
}
|
|
throw new IllegalArgumentException(
|
|
"Unexpected " + attr + " value : " + value + ". Acceptable values are "
|
|
+ Arrays.toString(stringNames));
|
|
}
|
|
return names.keyAt(index);
|
|
}
|
|
|
|
/**
|
|
* Set the average battery drain in milli-amps of the modem for a given drain type.
|
|
*
|
|
* @param key a key built from the union of {@link ModemDrainType}, {@link ModemTxLevel},
|
|
* {@link ModemRatType}, and {@link ModemNrFrequencyRange}.key
|
|
* @param value the battery dram in milli-amps for the given key.
|
|
*/
|
|
public void setPowerConstant(int key, String value) {
|
|
try {
|
|
mPowerConstants.put(key, Double.valueOf(value));
|
|
} catch (Exception e) {
|
|
Slog.e(TAG, "Failed to set power constant 0x" + Integer.toHexString(
|
|
key) + "(" + keyToString(key) + ") to " + value, e);
|
|
}
|
|
}
|
|
|
|
public static long getAverageBatteryDrainKey(@ModemDrainType int drainType,
|
|
@BatteryStats.RadioAccessTechnology int rat, @ServiceState.FrequencyRange int freqRange,
|
|
int txLevel) {
|
|
long key = PowerProfile.SUBSYSTEM_MODEM;
|
|
|
|
// Attach Modem drain type to the key if specified.
|
|
if (drainType != IGNORE) {
|
|
key |= drainType;
|
|
}
|
|
|
|
// Attach RadioAccessTechnology to the key if specified.
|
|
switch (rat) {
|
|
case IGNORE:
|
|
// do nothing
|
|
break;
|
|
case BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER:
|
|
key |= MODEM_RAT_TYPE_DEFAULT;
|
|
break;
|
|
case BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE:
|
|
key |= MODEM_RAT_TYPE_LTE;
|
|
break;
|
|
case BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR:
|
|
key |= MODEM_RAT_TYPE_NR;
|
|
break;
|
|
default:
|
|
Log.w(TAG, "Unexpected RadioAccessTechnology : " + rat);
|
|
}
|
|
|
|
// Attach NR Frequency Range to the key if specified.
|
|
switch (freqRange) {
|
|
case IGNORE:
|
|
// do nothing
|
|
break;
|
|
case ServiceState.FREQUENCY_RANGE_UNKNOWN:
|
|
key |= MODEM_NR_FREQUENCY_RANGE_DEFAULT;
|
|
break;
|
|
case ServiceState.FREQUENCY_RANGE_LOW:
|
|
key |= MODEM_NR_FREQUENCY_RANGE_LOW;
|
|
break;
|
|
case ServiceState.FREQUENCY_RANGE_MID:
|
|
key |= MODEM_NR_FREQUENCY_RANGE_MID;
|
|
break;
|
|
case ServiceState.FREQUENCY_RANGE_HIGH:
|
|
key |= MODEM_NR_FREQUENCY_RANGE_HIGH;
|
|
break;
|
|
case ServiceState.FREQUENCY_RANGE_MMWAVE:
|
|
key |= MODEM_NR_FREQUENCY_RANGE_MMWAVE;
|
|
break;
|
|
default:
|
|
Log.w(TAG, "Unexpected NR frequency range : " + freqRange);
|
|
}
|
|
|
|
// Attach transmission level to the key if specified.
|
|
switch (txLevel) {
|
|
case IGNORE:
|
|
// do nothing
|
|
break;
|
|
case 0:
|
|
key |= MODEM_TX_LEVEL_0;
|
|
break;
|
|
case 1:
|
|
key |= MODEM_TX_LEVEL_1;
|
|
break;
|
|
case 2:
|
|
key |= MODEM_TX_LEVEL_2;
|
|
break;
|
|
case 3:
|
|
key |= MODEM_TX_LEVEL_3;
|
|
break;
|
|
case 4:
|
|
key |= MODEM_TX_LEVEL_4;
|
|
break;
|
|
default:
|
|
Log.w(TAG, "Unexpected transmission level : " + txLevel);
|
|
}
|
|
return key;
|
|
}
|
|
|
|
/**
|
|
* Returns the average battery drain in milli-amps of the modem for a given drain type.
|
|
* Returns {@link Double.NaN} if a suitable value is not found for the given key.
|
|
*
|
|
* @param key a key built from the union of {@link ModemDrainType}, {@link ModemTxLevel},
|
|
* {@link ModemRatType}, and {@link ModemNrFrequencyRange}.
|
|
*/
|
|
public double getAverageBatteryDrainMa(int key) {
|
|
int bestKey = key;
|
|
double value;
|
|
value = mPowerConstants.get(bestKey, Double.NaN);
|
|
if (!Double.isNaN(value)) return value;
|
|
// The power constant for given key was not explicitly set. Try to fallback to possible
|
|
// defaults.
|
|
|
|
if ((bestKey & MODEM_NR_FREQUENCY_RANGE_MASK) != MODEM_NR_FREQUENCY_RANGE_DEFAULT) {
|
|
// Fallback to NR Frequency default value
|
|
bestKey &= ~MODEM_NR_FREQUENCY_RANGE_MASK;
|
|
bestKey |= MODEM_NR_FREQUENCY_RANGE_DEFAULT;
|
|
value = mPowerConstants.get(bestKey, Double.NaN);
|
|
if (!Double.isNaN(value)) return value;
|
|
}
|
|
|
|
if ((bestKey & MODEM_RAT_TYPE_MASK) != MODEM_RAT_TYPE_DEFAULT) {
|
|
// Fallback to RAT default value
|
|
bestKey &= ~MODEM_RAT_TYPE_MASK;
|
|
bestKey |= MODEM_RAT_TYPE_DEFAULT;
|
|
value = mPowerConstants.get(bestKey, Double.NaN);
|
|
if (!Double.isNaN(value)) return value;
|
|
}
|
|
|
|
Slog.w(TAG,
|
|
"getAverageBatteryDrainMaH called with unexpected key: 0x" + Integer.toHexString(
|
|
key) + ", " + keyToString(key));
|
|
return Double.NaN;
|
|
}
|
|
|
|
/**
|
|
* Returns a human readable version of a key.
|
|
*/
|
|
public static String keyToString(int key) {
|
|
StringBuilder sb = new StringBuilder();
|
|
final int drainType = key & MODEM_DRAIN_TYPE_MASK;
|
|
appendFieldToString(sb, "drain", MODEM_DRAIN_TYPE_NAMES, drainType);
|
|
sb.append(",");
|
|
|
|
if (drainType == MODEM_DRAIN_TYPE_TX) {
|
|
final int txLevel = key & MODEM_TX_LEVEL_MASK;
|
|
appendFieldToString(sb, "level", MODEM_TX_LEVEL_NAMES, txLevel);
|
|
sb.append(",");
|
|
}
|
|
|
|
final int ratType = key & MODEM_RAT_TYPE_MASK;
|
|
appendFieldToString(sb, "RAT", MODEM_RAT_TYPE_NAMES, ratType);
|
|
|
|
if (ratType == MODEM_RAT_TYPE_NR) {
|
|
sb.append(",");
|
|
final int nrFreq = key & MODEM_NR_FREQUENCY_RANGE_MASK;
|
|
appendFieldToString(sb, "nrFreq", MODEM_NR_FREQUENCY_RANGE_NAMES, nrFreq);
|
|
}
|
|
return sb.toString();
|
|
}
|
|
|
|
private static void appendFieldToString(StringBuilder sb, String fieldName,
|
|
SparseArray<String> names, int key) {
|
|
sb.append(fieldName);
|
|
sb.append(":");
|
|
final String name = names.get(key, null);
|
|
if (name == null) {
|
|
sb.append("UNKNOWN(0x");
|
|
sb.append(Integer.toHexString(key));
|
|
sb.append(")");
|
|
} else {
|
|
sb.append(name);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear this ModemPowerProfile power constants.
|
|
*/
|
|
public void clear() {
|
|
mPowerConstants.clear();
|
|
}
|
|
|
|
|
|
/**
|
|
* Dump this ModemPowerProfile power constants.
|
|
*/
|
|
public void dump(PrintWriter pw) {
|
|
final int size = mPowerConstants.size();
|
|
for (int i = 0; i < size; i++) {
|
|
pw.print(keyToString(mPowerConstants.keyAt(i)));
|
|
pw.print("=");
|
|
pw.println(mPowerConstants.valueAt(i));
|
|
}
|
|
}
|
|
}
|