Loading proto/src/telephony.proto +48 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,9 @@ message TelephonyLog { // The last active subscription info for each slot. repeated ActiveSubscriptionInfo last_active_subscription_info = 10; // Bandwidth estimator stats optional BandwidthEstimatorStats bandwidth_estimator_stats = 11; } // The time information Loading Loading @@ -418,6 +421,20 @@ enum RadioAccessTechnology { RAT_NR = 20; } // NR (5G) operation mode enum NrMode { // The device is not in a NR network. NR_NONE = 1; // The device is in a NR non-standalone network at non-MMWAVE frequencies. NR_NSA = 2; // The device is in a NR non-standalone network at MMWAVE frequencies. NR_NSA_MMWAVE = 3; // The device is in a NR standalone network at non-MMWAVE frequencies. NR_SA = 4; // The device is in a NR standalone network at MMWAVE frequencies. NR_SA_MMWAVE = 5; } // The information about IMS errors // https://cs.corp.google.com/#android/frameworks/base/telephony/java/com/android/ims/ImsReasonInfo.java message ImsReasonInfo { Loading Loading @@ -2680,3 +2697,34 @@ message ModemPowerStats { // Actual monitored rail energy consumed by modem (mAh) optional double monitored_rail_energy_consumed_mah = 15; } // Bandwidth estimator stats message BandwidthEstimatorStats { // Bandwidth stats of each level message PerLevel { optional uint32 signal_level = 1; // Accumulated bandwidth sample count optional uint32 count = 2; // Average end-to-end bandwidth in kbps optional uint32 avg_bw_kbps = 3; // Normalized root mean square error (NRMSE) of static BW values in percent optional uint32 static_bw_nrmse_percent = 4; // Normalized root mean square error (NRMSE) of end-to-end BW estimation in percent optional uint32 bw_est_nrmse_percent = 5; } // Bandwidth stats of each RAT message PerRat { // radio access technology optional RadioAccessTechnology rat = 1; // NR (5g) operation mode optional NrMode nr_mode = 2; // bandwidth stats of signal levels repeated PerLevel per_level = 3; } // Tx Stats of visited RATs repeated PerRat per_rat_tx = 1; // Rx Stats of visited RATs repeated PerRat per_rat_rx = 2; } src/java/com/android/internal/telephony/dataconnection/LinkBandwidthEstimator.java +54 −72 Original line number Diff line number Diff line Loading @@ -55,6 +55,8 @@ import com.android.internal.telephony.DctConstants; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.TelephonyFacade; import com.android.internal.telephony.metrics.TelephonyMetrics; import com.android.internal.telephony.nano.TelephonyProto.NrMode; import com.android.internal.util.IndentingPrintWriter; import com.android.telephony.Rlog; Loading Loading @@ -134,15 +136,15 @@ public class LinkBandwidthEstimator extends Handler { "HSDPA:4300,620", "HSUPA:4300,1800", "HSPA:4300,1800", "CDMA - EvDo rev. B:1500,550", "CDMA - eHRPD:750,48", "HSPA+:13000,3400", "TD_SCDMA:115,115", "LTE:30000,15000", "NR_NSA:47000,18000", "NR_NSA_MMWAVE:145000,60000", "NR:145000,60000"}; "NR_NSA_MMWAVE:145000,60000", "NR:145000,60000", "NR_MMWAVE:145000,60000"}; private static final Map<String, Pair<Integer, Integer>> AVG_BW_PER_RAT_MAP = new ArrayMap<>(); // To be used in the long term avg, each count needs to be above the following value static final int BW_STATS_COUNT_THRESHOLD = 5; static final int NUM_SIGNAL_LEVEL = 5; static final int LINK_TX = 0; static final int LINK_RX = 1; private static final int NUM_LINK_DIRECTION = 2; public static final int BW_STATS_COUNT_THRESHOLD = 5; public static final int NUM_SIGNAL_LEVEL = 5; public static final int LINK_TX = 0; public static final int LINK_RX = 1; public static final int NUM_LINK_DIRECTION = 2; private final Phone mPhone; private final TelephonyFacade mTelephonyFacade; Loading Loading @@ -523,53 +525,11 @@ public class LinkBandwidthEstimator extends Handler { long mBwSampleValidTimeMs; int mStaticBwKbps; int mLastReportedBwKbps; private final Map<String, EstimationError> mErrorMap = new ArrayMap<>(); private class EstimationError { final String mRatName; final long[] mBwEstIntNse = new long[NUM_SIGNAL_LEVEL]; final long[] mBwEstExtNse = new long[NUM_SIGNAL_LEVEL]; final long[] mStaticBwNse = new long[NUM_SIGNAL_LEVEL]; final int[] mCount = new int[NUM_SIGNAL_LEVEL]; EstimationError(String ratName) { mRatName = ratName; } @Override public String toString() { StringBuilder sb = new StringBuilder(); return sb.append(mRatName) .append("\n Internal\n").append(printAvgError(mBwEstIntNse, mCount)) .append("\n External\n").append(printAvgError(mBwEstExtNse, mCount)) .append("\n StaticBw\n").append(printAvgError(mStaticBwNse, mCount)) .toString(); } private String printAvgError(long[] stats, int[] count) { StringBuilder sb = new StringBuilder(); for (int k = 0; k < NUM_SIGNAL_LEVEL; k++) { int avgStat = (count[k] >= BW_STATS_COUNT_THRESHOLD && stats[k] >= 0) ? (int) Math.sqrt(stats[k] / count[k]) : 0; sb.append(" " + avgStat); } return sb.toString(); } } BandwidthState(int link) { mLink = link; } private EstimationError lookupEstimationError(String dataRatName) { EstimationError ans = mErrorMap.get(dataRatName); if (ans == null) { ans = new EstimationError(dataRatName); mErrorMap.put(dataRatName, ans); } return ans; } private void updateBandwidthSample(long bytesDelta, long timeDeltaMs) { updateByteCountThr(); if (bytesDelta < mByteDeltaAccThr) { Loading Loading @@ -718,11 +678,11 @@ public class LinkBandwidthEstimator extends Handler { int bwEstAvgErrPercent = calculateErrorPercent(mAvgUsedKbps, mBwSampleKbps); int bwEstIntErrPercent = calculateErrorPercent(mFilterKbps, mBwSampleKbps); int coldStartErrPercent = calculateErrorPercent(mStaticBwKbps, mBwSampleKbps); EstimationError err = lookupEstimationError(getDataRatName(mDataRat)); err.mBwEstIntNse[mSignalLevel] += bwEstIntErrPercent * bwEstIntErrPercent; err.mBwEstExtNse[mSignalLevel] += bwEstExtErrPercent * bwEstExtErrPercent; err.mStaticBwNse[mSignalLevel] += coldStartErrPercent * coldStartErrPercent; err.mCount[mSignalLevel]++; TelephonyMetrics.getInstance().writeBandwidthStats(mLink, mDataRat, getNrMode(mDataRat), mSignalLevel, bwEstIntErrPercent, bwEstExtErrPercent, coldStartErrPercent, mAvgUsedKbps); StringBuilder sb = new StringBuilder(); logd(sb.append(mLink) .append(" sampKbps ").append(mBwSampleKbps) Loading Loading @@ -798,15 +758,49 @@ public class LinkBandwidthEstimator extends Handler { MSG_NR_FREQUENCY_CHANGED, null); } private String getDataRatName(int rat) { if (rat == TelephonyManager.NETWORK_TYPE_LTE && isNRConnected()) { /** * Get a string based on current RAT */ public String getDataRatName(int rat) { return getDataRatName(rat, getNrMode(rat)); } private int getNrMode(int rat) { if (rat == TelephonyManager.NETWORK_TYPE_LTE && isNrNsaConnected()) { return mPhone.getServiceState().getNrFrequencyRange() == ServiceState.FREQUENCY_RANGE_MMWAVE ? NrMode.NR_NSA_MMWAVE : NrMode.NR_NSA; } else if (rat == TelephonyManager.NETWORK_TYPE_NR) { return mPhone.getServiceState().getNrFrequencyRange() == ServiceState.FREQUENCY_RANGE_MMWAVE ? DctConstants.RAT_NAME_NR_NSA_MMWAVE : DctConstants.RAT_NAME_NR_NSA; ? NrMode.NR_SA_MMWAVE : NrMode.NR_SA; } return NrMode.NR_NONE; } /** * Get a string based on current RAT and NR operation mode. */ public static String getDataRatName(int rat, int nrMode) { if (rat == TelephonyManager.NETWORK_TYPE_LTE && (nrMode == NrMode.NR_NSA || nrMode == NrMode.NR_NSA_MMWAVE)) { return nrMode == NrMode.NR_NSA ? DctConstants.RAT_NAME_NR_NSA : DctConstants.RAT_NAME_NR_NSA_MMWAVE; } else if (rat == TelephonyManager.NETWORK_TYPE_NR) { return nrMode == NrMode.NR_SA ? TelephonyManager.getNetworkTypeName(rat) : DctConstants.RAT_NAME_NR_SA_MMWAVE; } return TelephonyManager.getNetworkTypeName(rat); } /** * Check if the device is connected to NR 5G Non-Standalone network */ private boolean isNrNsaConnected() { return mPhone.getServiceState().getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED; } // Update avg BW values. // It should be called whenever the RAT could be changed. // return true if avg value is changed; Loading Loading @@ -844,10 +838,9 @@ public class LinkBandwidthEstimator extends Handler { } } /** Check if the device is connected to NR 5G Non-Standalone network. */ private boolean isNRConnected() { return mPhone.getServiceState().getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED; private NetworkRegistrationInfo getDataNri() { return mPhone.getServiceState().getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); } private void updateDataRatCellIdentity() { Loading @@ -870,8 +863,7 @@ public class LinkBandwidthEstimator extends Handler { } boolean updatedRat = false; NetworkRegistrationInfo nri = mPhone.getServiceState().getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); NetworkRegistrationInfo nri = getDataNri(); if (nri != null) { int dataRat = nri.getAccessNetworkTechnology(); if (dataRat != mDataRat) { Loading Loading @@ -1082,16 +1074,6 @@ public class LinkBandwidthEstimator extends Handler { pw.println(network.toString()); } pw.println("Tx NRMSE"); for (BandwidthState.EstimationError err : mTxState.mErrorMap.values()) { pw.println(err.toString()); } pw.println("Rx NRMSE"); for (BandwidthState.EstimationError err : mRxState.mErrorMap.values()) { pw.println(err.toString()); } try { mLocalLog.dump(fd, pw, args); } catch (Exception e) { Loading src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java +151 −1 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IMS_SEND_S import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SEND_SMS; import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SEND_SMS_EXPECT_MORE; import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SETUP_DATA_CALL; import static com.android.internal.telephony.dataconnection.LinkBandwidthEstimator.NUM_SIGNAL_LEVEL; import static com.android.internal.telephony.nano.TelephonyProto.PdpType.PDP_TYPE_IP; import static com.android.internal.telephony.nano.TelephonyProto.PdpType.PDP_TYPE_IPV4V6; import static com.android.internal.telephony.nano.TelephonyProto.PdpType.PDP_TYPE_IPV6; Loading Loading @@ -69,6 +70,7 @@ import android.telephony.ims.feature.MmTelFeature; import android.telephony.ims.stub.ImsRegistrationImplBase; import android.telephony.ims.stub.ImsSmsImplBase; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Base64; import android.util.SparseArray; Loading @@ -82,10 +84,12 @@ import com.android.internal.telephony.RILConstants; import com.android.internal.telephony.SmsController; import com.android.internal.telephony.SmsResponse; import com.android.internal.telephony.UUSInfo; import com.android.internal.telephony.dataconnection.LinkBandwidthEstimator; import com.android.internal.telephony.emergency.EmergencyNumberTracker; import com.android.internal.telephony.imsphone.ImsPhoneCall; import com.android.internal.telephony.nano.TelephonyProto; import com.android.internal.telephony.nano.TelephonyProto.ActiveSubscriptionInfo; import com.android.internal.telephony.nano.TelephonyProto.BandwidthEstimatorStats; import com.android.internal.telephony.nano.TelephonyProto.EmergencyNumberInfo; import com.android.internal.telephony.nano.TelephonyProto.ImsCapabilities; import com.android.internal.telephony.nano.TelephonyProto.ImsConnectionState; Loading Loading @@ -127,6 +131,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Deque; import java.util.List; import java.util.Map; import java.util.concurrent.ThreadLocalRandom; /** Loading Loading @@ -230,6 +235,12 @@ public class TelephonyMetrics { private final SparseArray<SparseArray<RilDataCall>> mLastRilDataCallEvents = new SparseArray<>(); /** * List of Tx and Rx Bandwidth estimation stats maps */ private final List<Map<String, BwEstimationStats>> mBwEstStatsMapList = new ArrayList<>( Arrays.asList(new ArrayMap<>(), new ArrayMap<>())); /** The start system time of the TelephonyLog in milliseconds*/ private long mStartSystemTimeMs; Loading Loading @@ -629,6 +640,20 @@ public class TelephonyMetrics { + new DecimalFormat("#.##").format(s.monitoredRailEnergyConsumedMah)); pw.decreaseIndent(); pw.println("Hardware Version: " + SystemProperties.get("ro.boot.revision", "")); pw.decreaseIndent(); pw.println("LinkBandwidthEstimator stats:"); pw.increaseIndent(); pw.println("Tx"); for (BwEstimationStats stats : mBwEstStatsMapList.get(0).values()) { pw.println(stats.toString()); } pw.println("Rx"); for (BwEstimationStats stats : mBwEstStatsMapList.get(1).values()) { pw.println(stats.toString()); } } /** Loading @@ -649,6 +674,8 @@ public class TelephonyMetrics { mTelephonyEvents.clear(); mCompletedCallSessions.clear(); mCompletedSmsSessions.clear(); mBwEstStatsMapList.get(0).clear(); mBwEstStatsMapList.get(1).clear(); mTelephonyEventsDropped = false; Loading Loading @@ -721,6 +748,7 @@ public class TelephonyMetrics { .setDataCalls(dataCalls).build()); } } } /** Loading Loading @@ -794,7 +822,7 @@ public class TelephonyMetrics { } } log.lastActiveSubscriptionInfo = activeSubscriptionInfo; log.bandwidthEstimatorStats = buildBandwidthEstimatorStats(); return log; } Loading Loading @@ -2901,4 +2929,126 @@ public class TelephonyMetrics { return SimState.SIM_STATE_UNKNOWN; } } /** * Write bandwidth estimator stats */ public synchronized void writeBandwidthStats(int link, int rat, int nrMode, int signalLevel, int bwEstIntErrPercent, int bwEstExtErrPercent, int coldStartErrPercent, int avgUsedKbps) { BwEstimationStats stats = lookupEstimationStats(link, rat, nrMode); stats.mBwEstIntNse[signalLevel] += bwEstIntErrPercent * bwEstIntErrPercent; stats.mBwEstExtNse[signalLevel] += bwEstExtErrPercent * bwEstExtErrPercent; stats.mStaticBwNse[signalLevel] += coldStartErrPercent * coldStartErrPercent; stats.mAvgBwKbps[signalLevel] = avgUsedKbps; stats.mCount[signalLevel]++; } private BwEstimationStats lookupEstimationStats(int linkIndex, int dataRat, int nrMode) { String dataRatName = LinkBandwidthEstimator.getDataRatName(dataRat, nrMode); BwEstimationStats ans = mBwEstStatsMapList.get(linkIndex).get(dataRatName); if (ans == null) { ans = new BwEstimationStats(dataRat, nrMode); mBwEstStatsMapList.get(linkIndex).put(dataRatName, ans); } return ans; } private BandwidthEstimatorStats buildBandwidthEstimatorStats() { BandwidthEstimatorStats stats = new BandwidthEstimatorStats(); List<BandwidthEstimatorStats.PerRat> ratList; ratList = writeBandwidthEstimatorStatsRatList(mBwEstStatsMapList.get(0)); stats.perRatTx = ratList.toArray(new BandwidthEstimatorStats.PerRat[0]); ratList = writeBandwidthEstimatorStatsRatList(mBwEstStatsMapList.get(1)); stats.perRatRx = ratList.toArray(new BandwidthEstimatorStats.PerRat[0]); return stats; } private List<BandwidthEstimatorStats.PerRat> writeBandwidthEstimatorStatsRatList( Map<String, BwEstimationStats> bwEstStatsMap) { List<BandwidthEstimatorStats.PerRat> ratList = new ArrayList<>(); for (BwEstimationStats perRat : bwEstStatsMap.values()) { ratList.add(perRat.writeBandwidthStats()); } return ratList; } private static class BwEstimationStats { final int mRadioTechnology; final int mNrMode; final long[] mBwEstIntNse = new long[NUM_SIGNAL_LEVEL]; final long[] mBwEstExtNse = new long[NUM_SIGNAL_LEVEL]; final long[] mStaticBwNse = new long[NUM_SIGNAL_LEVEL]; final int[] mAvgBwKbps = new int[NUM_SIGNAL_LEVEL]; final int[] mCount = new int[NUM_SIGNAL_LEVEL]; BwEstimationStats(int radioTechnology, int nrMode) { mRadioTechnology = radioTechnology; mNrMode = nrMode; } @Override public String toString() { StringBuilder sb = new StringBuilder(); return sb.append(LinkBandwidthEstimator.getDataRatName(mRadioTechnology, mNrMode)) .append("\n Count\n").append(printValues(mCount)) .append("\n AvgKbps\n").append(printValues(mAvgBwKbps)) .append("\n Internal NRMSE\n").append(printAvgError(mBwEstIntNse, mCount)) .append("\n External NRMSE\n").append(printAvgError(mBwEstExtNse, mCount)) .append("\n StaticBw NRMSE\n").append(printAvgError(mStaticBwNse, mCount)) .toString(); } private String printValues(int[] values) { StringBuilder sb = new StringBuilder(); for (int k = 0; k < NUM_SIGNAL_LEVEL; k++) { sb.append(" " + values[k]); } return sb.toString(); } private String printAvgError(long[] stats, int[] count) { StringBuilder sb = new StringBuilder(); for (int k = 0; k < NUM_SIGNAL_LEVEL; k++) { int avgStat = (count[k] > 0 && stats[k] >= 0) ? (int) Math.sqrt(stats[k] / count[k]) : 0; sb.append(" " + avgStat); } return sb.toString(); } private BandwidthEstimatorStats.PerRat writeBandwidthStats() { BandwidthEstimatorStats.PerRat stats = new BandwidthEstimatorStats.PerRat(); List<BandwidthEstimatorStats.PerLevel> levelList = new ArrayList<>(); for (int level = 0; level < NUM_SIGNAL_LEVEL; level++) { BandwidthEstimatorStats.PerLevel currStats = writeBandwidthStatsPerLevel(level); if (currStats != null) { levelList.add(currStats); } } stats.rat = mRadioTechnology; stats.perLevel = levelList.toArray(new BandwidthEstimatorStats.PerLevel[0]); stats.nrMode = mNrMode; return stats; } private BandwidthEstimatorStats.PerLevel writeBandwidthStatsPerLevel(int level) { int count = mCount[level]; if (count > 0) { BandwidthEstimatorStats.PerLevel stats = new BandwidthEstimatorStats.PerLevel(); stats.signalLevel = level; stats.count = count; stats.avgBwKbps = mAvgBwKbps[level]; stats.staticBwNrmsePercent = calculateNrmse(mStaticBwNse[level], count); stats.bwEstNrmsePercent = calculateNrmse(mBwEstExtNse[level], count); return stats; } return null; } private int calculateNrmse(long nse, int count) { return (count > 0 && nse >= 0) ? (int) Math.sqrt(nse / count) : 0; } } } tests/telephonytests/src/com/android/internal/telephony/dataconnection/LinkBandwidthEstimatorTest.java +35 −0 Original line number Diff line number Diff line Loading @@ -121,6 +121,11 @@ public class LinkBandwidthEstimatorTest extends TelephonyTest { when(mTelephonyFacade.getMobileRxBytes()).thenReturn(mRxBytes); } private void subtractRxBytes(long rxBytes) { mRxBytes -= rxBytes; when(mTelephonyFacade.getMobileRxBytes()).thenReturn(mRxBytes); } @After public void tearDown() throws Exception { super.tearDown(); Loading Loading @@ -340,6 +345,10 @@ public class LinkBandwidthEstimatorTest extends TelephonyTest { assertEquals(47000, (int) values.first); values = mLBE.getStaticAvgBw(TelephonyManager.NETWORK_TYPE_NR); assertEquals(145_000, (int) values.first); when(mServiceState.getNrFrequencyRange()).thenReturn(ServiceState.FREQUENCY_RANGE_MMWAVE); values = mLBE.getStaticAvgBw(TelephonyManager.NETWORK_TYPE_NR); assertEquals("NR_MMWAVE", mLBE.getDataRatName(TelephonyManager.NETWORK_TYPE_NR)); assertEquals(145_000, (int) values.first); } @Test Loading Loading @@ -386,6 +395,32 @@ public class LinkBandwidthEstimatorTest extends TelephonyTest { verify(mDataConnection, times(1)).updateLinkBandwidthEstimation(eq(-1), eq(19_597)); } @Test public void testAbnormalTrafficCountTriggerLessBwUpdate() throws Exception { mLBE.obtainMessage(MSG_SCREEN_STATE_CHANGED, true).sendToTarget(); processAllMessages(); for (int i = 0; i < BW_STATS_COUNT_THRESHOLD + 2; i++) { if (i == 1) { addTxBytes(10_000L); subtractRxBytes(500_000L); } else { addTxBytes(10_000L); addRxBytes(500_000L); } addElapsedTime(5_100); moveTimeForward(5_100); processAllMessages(); mLBE.obtainMessage(MSG_MODEM_ACTIVITY_RETURNED, new ModemActivityInfo( i * 5_100L, 0, 0, TX_TIME_2_MS, i * RX_TIME_2_MS)).sendToTarget(); processAllMessages(); } verify(mTelephonyManager, times(BW_STATS_COUNT_THRESHOLD)) .requestModemActivityInfo(any(), any()); verify(mDataConnection, times(1)).updateLinkBandwidthEstimation(eq(-1), eq(-1)); } @Test public void testUseCurrentTacStatsWithEnoughData() throws Exception { mLBE.obtainMessage(MSG_SCREEN_STATE_CHANGED, true).sendToTarget(); Loading tests/telephonytests/src/com/android/internal/telephony/metrics/TelephonyMetricsTest.java +39 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_D import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_GATEWAY; import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_IFNAME; import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_PCSCF_ADDRESS; import static com.android.internal.telephony.dataconnection.LinkBandwidthEstimator.NUM_SIGNAL_LEVEL; import static com.android.internal.telephony.nano.TelephonyProto.PdpType.PDP_TYPE_IPV4V6; import static org.junit.Assert.assertArrayEquals; Loading Loading @@ -59,8 +60,11 @@ import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.SmsResponse; import com.android.internal.telephony.TelephonyTest; import com.android.internal.telephony.UUSInfo; import com.android.internal.telephony.dataconnection.LinkBandwidthEstimator; import com.android.internal.telephony.nano.TelephonyProto; import com.android.internal.telephony.nano.TelephonyProto.BandwidthEstimatorStats; import com.android.internal.telephony.nano.TelephonyProto.ImsConnectionState; import com.android.internal.telephony.nano.TelephonyProto.NrMode; import com.android.internal.telephony.nano.TelephonyProto.RadioAccessTechnology; import com.android.internal.telephony.nano.TelephonyProto.SmsSession; import com.android.internal.telephony.nano.TelephonyProto.TelephonyCallSession; Loading Loading @@ -872,4 +876,39 @@ public class TelephonyMetricsTest extends TelephonyTest { assertEquals(false, event.imsCapabilities.videoOverLte); assertEquals(false, event.imsCapabilities.utOverLte); } // Test write Bandwidth Stats @Test @SmallTest public void testWriteBandwidthStats() throws Exception { addBandwidthStats(LinkBandwidthEstimator.LINK_TX, TelephonyManager.NETWORK_TYPE_LTE, NrMode.NR_NSA_MMWAVE); addBandwidthStats(LinkBandwidthEstimator.LINK_RX, TelephonyManager.NETWORK_TYPE_LTE, NrMode.NR_NSA_MMWAVE); addBandwidthStats(LinkBandwidthEstimator.LINK_RX, TelephonyManager.NETWORK_TYPE_NR, NrMode.NR_SA_MMWAVE); TelephonyLog log = buildProto(); BandwidthEstimatorStats stats = log.bandwidthEstimatorStats; assertEquals(1, stats.perRatTx.length); assertEquals(2, stats.perRatRx.length); assertEquals(TelephonyManager.NETWORK_TYPE_LTE, stats.perRatTx[0].rat); assertEquals(NrMode.NR_NSA_MMWAVE, stats.perRatTx[0].nrMode); assertEquals(NUM_SIGNAL_LEVEL - 1, stats.perRatTx[0].perLevel.length); assertEquals(2, stats.perRatTx[0].perLevel[0].count); assertEquals(0, stats.perRatTx[0].perLevel[0].signalLevel); assertEquals(500_000, stats.perRatTx[0].perLevel[0].avgBwKbps); assertEquals(41, stats.perRatTx[0].perLevel[0].staticBwNrmsePercent); assertEquals(31, stats.perRatTx[0].perLevel[0].bwEstNrmsePercent); } private void addBandwidthStats(int link, int dataRat, int nrMode) { for (int i = 0; i < NUM_SIGNAL_LEVEL - 1; i++) { mMetrics.writeBandwidthStats(link, dataRat, nrMode, i, 10, 20, 30, 300_000); mMetrics.writeBandwidthStats(link, dataRat, nrMode, i, 30, 40, 50, 500_000); } } } Loading
proto/src/telephony.proto +48 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,9 @@ message TelephonyLog { // The last active subscription info for each slot. repeated ActiveSubscriptionInfo last_active_subscription_info = 10; // Bandwidth estimator stats optional BandwidthEstimatorStats bandwidth_estimator_stats = 11; } // The time information Loading Loading @@ -418,6 +421,20 @@ enum RadioAccessTechnology { RAT_NR = 20; } // NR (5G) operation mode enum NrMode { // The device is not in a NR network. NR_NONE = 1; // The device is in a NR non-standalone network at non-MMWAVE frequencies. NR_NSA = 2; // The device is in a NR non-standalone network at MMWAVE frequencies. NR_NSA_MMWAVE = 3; // The device is in a NR standalone network at non-MMWAVE frequencies. NR_SA = 4; // The device is in a NR standalone network at MMWAVE frequencies. NR_SA_MMWAVE = 5; } // The information about IMS errors // https://cs.corp.google.com/#android/frameworks/base/telephony/java/com/android/ims/ImsReasonInfo.java message ImsReasonInfo { Loading Loading @@ -2680,3 +2697,34 @@ message ModemPowerStats { // Actual monitored rail energy consumed by modem (mAh) optional double monitored_rail_energy_consumed_mah = 15; } // Bandwidth estimator stats message BandwidthEstimatorStats { // Bandwidth stats of each level message PerLevel { optional uint32 signal_level = 1; // Accumulated bandwidth sample count optional uint32 count = 2; // Average end-to-end bandwidth in kbps optional uint32 avg_bw_kbps = 3; // Normalized root mean square error (NRMSE) of static BW values in percent optional uint32 static_bw_nrmse_percent = 4; // Normalized root mean square error (NRMSE) of end-to-end BW estimation in percent optional uint32 bw_est_nrmse_percent = 5; } // Bandwidth stats of each RAT message PerRat { // radio access technology optional RadioAccessTechnology rat = 1; // NR (5g) operation mode optional NrMode nr_mode = 2; // bandwidth stats of signal levels repeated PerLevel per_level = 3; } // Tx Stats of visited RATs repeated PerRat per_rat_tx = 1; // Rx Stats of visited RATs repeated PerRat per_rat_rx = 2; }
src/java/com/android/internal/telephony/dataconnection/LinkBandwidthEstimator.java +54 −72 Original line number Diff line number Diff line Loading @@ -55,6 +55,8 @@ import com.android.internal.telephony.DctConstants; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.TelephonyFacade; import com.android.internal.telephony.metrics.TelephonyMetrics; import com.android.internal.telephony.nano.TelephonyProto.NrMode; import com.android.internal.util.IndentingPrintWriter; import com.android.telephony.Rlog; Loading Loading @@ -134,15 +136,15 @@ public class LinkBandwidthEstimator extends Handler { "HSDPA:4300,620", "HSUPA:4300,1800", "HSPA:4300,1800", "CDMA - EvDo rev. B:1500,550", "CDMA - eHRPD:750,48", "HSPA+:13000,3400", "TD_SCDMA:115,115", "LTE:30000,15000", "NR_NSA:47000,18000", "NR_NSA_MMWAVE:145000,60000", "NR:145000,60000"}; "NR_NSA_MMWAVE:145000,60000", "NR:145000,60000", "NR_MMWAVE:145000,60000"}; private static final Map<String, Pair<Integer, Integer>> AVG_BW_PER_RAT_MAP = new ArrayMap<>(); // To be used in the long term avg, each count needs to be above the following value static final int BW_STATS_COUNT_THRESHOLD = 5; static final int NUM_SIGNAL_LEVEL = 5; static final int LINK_TX = 0; static final int LINK_RX = 1; private static final int NUM_LINK_DIRECTION = 2; public static final int BW_STATS_COUNT_THRESHOLD = 5; public static final int NUM_SIGNAL_LEVEL = 5; public static final int LINK_TX = 0; public static final int LINK_RX = 1; public static final int NUM_LINK_DIRECTION = 2; private final Phone mPhone; private final TelephonyFacade mTelephonyFacade; Loading Loading @@ -523,53 +525,11 @@ public class LinkBandwidthEstimator extends Handler { long mBwSampleValidTimeMs; int mStaticBwKbps; int mLastReportedBwKbps; private final Map<String, EstimationError> mErrorMap = new ArrayMap<>(); private class EstimationError { final String mRatName; final long[] mBwEstIntNse = new long[NUM_SIGNAL_LEVEL]; final long[] mBwEstExtNse = new long[NUM_SIGNAL_LEVEL]; final long[] mStaticBwNse = new long[NUM_SIGNAL_LEVEL]; final int[] mCount = new int[NUM_SIGNAL_LEVEL]; EstimationError(String ratName) { mRatName = ratName; } @Override public String toString() { StringBuilder sb = new StringBuilder(); return sb.append(mRatName) .append("\n Internal\n").append(printAvgError(mBwEstIntNse, mCount)) .append("\n External\n").append(printAvgError(mBwEstExtNse, mCount)) .append("\n StaticBw\n").append(printAvgError(mStaticBwNse, mCount)) .toString(); } private String printAvgError(long[] stats, int[] count) { StringBuilder sb = new StringBuilder(); for (int k = 0; k < NUM_SIGNAL_LEVEL; k++) { int avgStat = (count[k] >= BW_STATS_COUNT_THRESHOLD && stats[k] >= 0) ? (int) Math.sqrt(stats[k] / count[k]) : 0; sb.append(" " + avgStat); } return sb.toString(); } } BandwidthState(int link) { mLink = link; } private EstimationError lookupEstimationError(String dataRatName) { EstimationError ans = mErrorMap.get(dataRatName); if (ans == null) { ans = new EstimationError(dataRatName); mErrorMap.put(dataRatName, ans); } return ans; } private void updateBandwidthSample(long bytesDelta, long timeDeltaMs) { updateByteCountThr(); if (bytesDelta < mByteDeltaAccThr) { Loading Loading @@ -718,11 +678,11 @@ public class LinkBandwidthEstimator extends Handler { int bwEstAvgErrPercent = calculateErrorPercent(mAvgUsedKbps, mBwSampleKbps); int bwEstIntErrPercent = calculateErrorPercent(mFilterKbps, mBwSampleKbps); int coldStartErrPercent = calculateErrorPercent(mStaticBwKbps, mBwSampleKbps); EstimationError err = lookupEstimationError(getDataRatName(mDataRat)); err.mBwEstIntNse[mSignalLevel] += bwEstIntErrPercent * bwEstIntErrPercent; err.mBwEstExtNse[mSignalLevel] += bwEstExtErrPercent * bwEstExtErrPercent; err.mStaticBwNse[mSignalLevel] += coldStartErrPercent * coldStartErrPercent; err.mCount[mSignalLevel]++; TelephonyMetrics.getInstance().writeBandwidthStats(mLink, mDataRat, getNrMode(mDataRat), mSignalLevel, bwEstIntErrPercent, bwEstExtErrPercent, coldStartErrPercent, mAvgUsedKbps); StringBuilder sb = new StringBuilder(); logd(sb.append(mLink) .append(" sampKbps ").append(mBwSampleKbps) Loading Loading @@ -798,15 +758,49 @@ public class LinkBandwidthEstimator extends Handler { MSG_NR_FREQUENCY_CHANGED, null); } private String getDataRatName(int rat) { if (rat == TelephonyManager.NETWORK_TYPE_LTE && isNRConnected()) { /** * Get a string based on current RAT */ public String getDataRatName(int rat) { return getDataRatName(rat, getNrMode(rat)); } private int getNrMode(int rat) { if (rat == TelephonyManager.NETWORK_TYPE_LTE && isNrNsaConnected()) { return mPhone.getServiceState().getNrFrequencyRange() == ServiceState.FREQUENCY_RANGE_MMWAVE ? NrMode.NR_NSA_MMWAVE : NrMode.NR_NSA; } else if (rat == TelephonyManager.NETWORK_TYPE_NR) { return mPhone.getServiceState().getNrFrequencyRange() == ServiceState.FREQUENCY_RANGE_MMWAVE ? DctConstants.RAT_NAME_NR_NSA_MMWAVE : DctConstants.RAT_NAME_NR_NSA; ? NrMode.NR_SA_MMWAVE : NrMode.NR_SA; } return NrMode.NR_NONE; } /** * Get a string based on current RAT and NR operation mode. */ public static String getDataRatName(int rat, int nrMode) { if (rat == TelephonyManager.NETWORK_TYPE_LTE && (nrMode == NrMode.NR_NSA || nrMode == NrMode.NR_NSA_MMWAVE)) { return nrMode == NrMode.NR_NSA ? DctConstants.RAT_NAME_NR_NSA : DctConstants.RAT_NAME_NR_NSA_MMWAVE; } else if (rat == TelephonyManager.NETWORK_TYPE_NR) { return nrMode == NrMode.NR_SA ? TelephonyManager.getNetworkTypeName(rat) : DctConstants.RAT_NAME_NR_SA_MMWAVE; } return TelephonyManager.getNetworkTypeName(rat); } /** * Check if the device is connected to NR 5G Non-Standalone network */ private boolean isNrNsaConnected() { return mPhone.getServiceState().getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED; } // Update avg BW values. // It should be called whenever the RAT could be changed. // return true if avg value is changed; Loading Loading @@ -844,10 +838,9 @@ public class LinkBandwidthEstimator extends Handler { } } /** Check if the device is connected to NR 5G Non-Standalone network. */ private boolean isNRConnected() { return mPhone.getServiceState().getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED; private NetworkRegistrationInfo getDataNri() { return mPhone.getServiceState().getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); } private void updateDataRatCellIdentity() { Loading @@ -870,8 +863,7 @@ public class LinkBandwidthEstimator extends Handler { } boolean updatedRat = false; NetworkRegistrationInfo nri = mPhone.getServiceState().getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); NetworkRegistrationInfo nri = getDataNri(); if (nri != null) { int dataRat = nri.getAccessNetworkTechnology(); if (dataRat != mDataRat) { Loading Loading @@ -1082,16 +1074,6 @@ public class LinkBandwidthEstimator extends Handler { pw.println(network.toString()); } pw.println("Tx NRMSE"); for (BandwidthState.EstimationError err : mTxState.mErrorMap.values()) { pw.println(err.toString()); } pw.println("Rx NRMSE"); for (BandwidthState.EstimationError err : mRxState.mErrorMap.values()) { pw.println(err.toString()); } try { mLocalLog.dump(fd, pw, args); } catch (Exception e) { Loading
src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java +151 −1 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IMS_SEND_S import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SEND_SMS; import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SEND_SMS_EXPECT_MORE; import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SETUP_DATA_CALL; import static com.android.internal.telephony.dataconnection.LinkBandwidthEstimator.NUM_SIGNAL_LEVEL; import static com.android.internal.telephony.nano.TelephonyProto.PdpType.PDP_TYPE_IP; import static com.android.internal.telephony.nano.TelephonyProto.PdpType.PDP_TYPE_IPV4V6; import static com.android.internal.telephony.nano.TelephonyProto.PdpType.PDP_TYPE_IPV6; Loading Loading @@ -69,6 +70,7 @@ import android.telephony.ims.feature.MmTelFeature; import android.telephony.ims.stub.ImsRegistrationImplBase; import android.telephony.ims.stub.ImsSmsImplBase; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Base64; import android.util.SparseArray; Loading @@ -82,10 +84,12 @@ import com.android.internal.telephony.RILConstants; import com.android.internal.telephony.SmsController; import com.android.internal.telephony.SmsResponse; import com.android.internal.telephony.UUSInfo; import com.android.internal.telephony.dataconnection.LinkBandwidthEstimator; import com.android.internal.telephony.emergency.EmergencyNumberTracker; import com.android.internal.telephony.imsphone.ImsPhoneCall; import com.android.internal.telephony.nano.TelephonyProto; import com.android.internal.telephony.nano.TelephonyProto.ActiveSubscriptionInfo; import com.android.internal.telephony.nano.TelephonyProto.BandwidthEstimatorStats; import com.android.internal.telephony.nano.TelephonyProto.EmergencyNumberInfo; import com.android.internal.telephony.nano.TelephonyProto.ImsCapabilities; import com.android.internal.telephony.nano.TelephonyProto.ImsConnectionState; Loading Loading @@ -127,6 +131,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Deque; import java.util.List; import java.util.Map; import java.util.concurrent.ThreadLocalRandom; /** Loading Loading @@ -230,6 +235,12 @@ public class TelephonyMetrics { private final SparseArray<SparseArray<RilDataCall>> mLastRilDataCallEvents = new SparseArray<>(); /** * List of Tx and Rx Bandwidth estimation stats maps */ private final List<Map<String, BwEstimationStats>> mBwEstStatsMapList = new ArrayList<>( Arrays.asList(new ArrayMap<>(), new ArrayMap<>())); /** The start system time of the TelephonyLog in milliseconds*/ private long mStartSystemTimeMs; Loading Loading @@ -629,6 +640,20 @@ public class TelephonyMetrics { + new DecimalFormat("#.##").format(s.monitoredRailEnergyConsumedMah)); pw.decreaseIndent(); pw.println("Hardware Version: " + SystemProperties.get("ro.boot.revision", "")); pw.decreaseIndent(); pw.println("LinkBandwidthEstimator stats:"); pw.increaseIndent(); pw.println("Tx"); for (BwEstimationStats stats : mBwEstStatsMapList.get(0).values()) { pw.println(stats.toString()); } pw.println("Rx"); for (BwEstimationStats stats : mBwEstStatsMapList.get(1).values()) { pw.println(stats.toString()); } } /** Loading @@ -649,6 +674,8 @@ public class TelephonyMetrics { mTelephonyEvents.clear(); mCompletedCallSessions.clear(); mCompletedSmsSessions.clear(); mBwEstStatsMapList.get(0).clear(); mBwEstStatsMapList.get(1).clear(); mTelephonyEventsDropped = false; Loading Loading @@ -721,6 +748,7 @@ public class TelephonyMetrics { .setDataCalls(dataCalls).build()); } } } /** Loading Loading @@ -794,7 +822,7 @@ public class TelephonyMetrics { } } log.lastActiveSubscriptionInfo = activeSubscriptionInfo; log.bandwidthEstimatorStats = buildBandwidthEstimatorStats(); return log; } Loading Loading @@ -2901,4 +2929,126 @@ public class TelephonyMetrics { return SimState.SIM_STATE_UNKNOWN; } } /** * Write bandwidth estimator stats */ public synchronized void writeBandwidthStats(int link, int rat, int nrMode, int signalLevel, int bwEstIntErrPercent, int bwEstExtErrPercent, int coldStartErrPercent, int avgUsedKbps) { BwEstimationStats stats = lookupEstimationStats(link, rat, nrMode); stats.mBwEstIntNse[signalLevel] += bwEstIntErrPercent * bwEstIntErrPercent; stats.mBwEstExtNse[signalLevel] += bwEstExtErrPercent * bwEstExtErrPercent; stats.mStaticBwNse[signalLevel] += coldStartErrPercent * coldStartErrPercent; stats.mAvgBwKbps[signalLevel] = avgUsedKbps; stats.mCount[signalLevel]++; } private BwEstimationStats lookupEstimationStats(int linkIndex, int dataRat, int nrMode) { String dataRatName = LinkBandwidthEstimator.getDataRatName(dataRat, nrMode); BwEstimationStats ans = mBwEstStatsMapList.get(linkIndex).get(dataRatName); if (ans == null) { ans = new BwEstimationStats(dataRat, nrMode); mBwEstStatsMapList.get(linkIndex).put(dataRatName, ans); } return ans; } private BandwidthEstimatorStats buildBandwidthEstimatorStats() { BandwidthEstimatorStats stats = new BandwidthEstimatorStats(); List<BandwidthEstimatorStats.PerRat> ratList; ratList = writeBandwidthEstimatorStatsRatList(mBwEstStatsMapList.get(0)); stats.perRatTx = ratList.toArray(new BandwidthEstimatorStats.PerRat[0]); ratList = writeBandwidthEstimatorStatsRatList(mBwEstStatsMapList.get(1)); stats.perRatRx = ratList.toArray(new BandwidthEstimatorStats.PerRat[0]); return stats; } private List<BandwidthEstimatorStats.PerRat> writeBandwidthEstimatorStatsRatList( Map<String, BwEstimationStats> bwEstStatsMap) { List<BandwidthEstimatorStats.PerRat> ratList = new ArrayList<>(); for (BwEstimationStats perRat : bwEstStatsMap.values()) { ratList.add(perRat.writeBandwidthStats()); } return ratList; } private static class BwEstimationStats { final int mRadioTechnology; final int mNrMode; final long[] mBwEstIntNse = new long[NUM_SIGNAL_LEVEL]; final long[] mBwEstExtNse = new long[NUM_SIGNAL_LEVEL]; final long[] mStaticBwNse = new long[NUM_SIGNAL_LEVEL]; final int[] mAvgBwKbps = new int[NUM_SIGNAL_LEVEL]; final int[] mCount = new int[NUM_SIGNAL_LEVEL]; BwEstimationStats(int radioTechnology, int nrMode) { mRadioTechnology = radioTechnology; mNrMode = nrMode; } @Override public String toString() { StringBuilder sb = new StringBuilder(); return sb.append(LinkBandwidthEstimator.getDataRatName(mRadioTechnology, mNrMode)) .append("\n Count\n").append(printValues(mCount)) .append("\n AvgKbps\n").append(printValues(mAvgBwKbps)) .append("\n Internal NRMSE\n").append(printAvgError(mBwEstIntNse, mCount)) .append("\n External NRMSE\n").append(printAvgError(mBwEstExtNse, mCount)) .append("\n StaticBw NRMSE\n").append(printAvgError(mStaticBwNse, mCount)) .toString(); } private String printValues(int[] values) { StringBuilder sb = new StringBuilder(); for (int k = 0; k < NUM_SIGNAL_LEVEL; k++) { sb.append(" " + values[k]); } return sb.toString(); } private String printAvgError(long[] stats, int[] count) { StringBuilder sb = new StringBuilder(); for (int k = 0; k < NUM_SIGNAL_LEVEL; k++) { int avgStat = (count[k] > 0 && stats[k] >= 0) ? (int) Math.sqrt(stats[k] / count[k]) : 0; sb.append(" " + avgStat); } return sb.toString(); } private BandwidthEstimatorStats.PerRat writeBandwidthStats() { BandwidthEstimatorStats.PerRat stats = new BandwidthEstimatorStats.PerRat(); List<BandwidthEstimatorStats.PerLevel> levelList = new ArrayList<>(); for (int level = 0; level < NUM_SIGNAL_LEVEL; level++) { BandwidthEstimatorStats.PerLevel currStats = writeBandwidthStatsPerLevel(level); if (currStats != null) { levelList.add(currStats); } } stats.rat = mRadioTechnology; stats.perLevel = levelList.toArray(new BandwidthEstimatorStats.PerLevel[0]); stats.nrMode = mNrMode; return stats; } private BandwidthEstimatorStats.PerLevel writeBandwidthStatsPerLevel(int level) { int count = mCount[level]; if (count > 0) { BandwidthEstimatorStats.PerLevel stats = new BandwidthEstimatorStats.PerLevel(); stats.signalLevel = level; stats.count = count; stats.avgBwKbps = mAvgBwKbps[level]; stats.staticBwNrmsePercent = calculateNrmse(mStaticBwNse[level], count); stats.bwEstNrmsePercent = calculateNrmse(mBwEstExtNse[level], count); return stats; } return null; } private int calculateNrmse(long nse, int count) { return (count > 0 && nse >= 0) ? (int) Math.sqrt(nse / count) : 0; } } }
tests/telephonytests/src/com/android/internal/telephony/dataconnection/LinkBandwidthEstimatorTest.java +35 −0 Original line number Diff line number Diff line Loading @@ -121,6 +121,11 @@ public class LinkBandwidthEstimatorTest extends TelephonyTest { when(mTelephonyFacade.getMobileRxBytes()).thenReturn(mRxBytes); } private void subtractRxBytes(long rxBytes) { mRxBytes -= rxBytes; when(mTelephonyFacade.getMobileRxBytes()).thenReturn(mRxBytes); } @After public void tearDown() throws Exception { super.tearDown(); Loading Loading @@ -340,6 +345,10 @@ public class LinkBandwidthEstimatorTest extends TelephonyTest { assertEquals(47000, (int) values.first); values = mLBE.getStaticAvgBw(TelephonyManager.NETWORK_TYPE_NR); assertEquals(145_000, (int) values.first); when(mServiceState.getNrFrequencyRange()).thenReturn(ServiceState.FREQUENCY_RANGE_MMWAVE); values = mLBE.getStaticAvgBw(TelephonyManager.NETWORK_TYPE_NR); assertEquals("NR_MMWAVE", mLBE.getDataRatName(TelephonyManager.NETWORK_TYPE_NR)); assertEquals(145_000, (int) values.first); } @Test Loading Loading @@ -386,6 +395,32 @@ public class LinkBandwidthEstimatorTest extends TelephonyTest { verify(mDataConnection, times(1)).updateLinkBandwidthEstimation(eq(-1), eq(19_597)); } @Test public void testAbnormalTrafficCountTriggerLessBwUpdate() throws Exception { mLBE.obtainMessage(MSG_SCREEN_STATE_CHANGED, true).sendToTarget(); processAllMessages(); for (int i = 0; i < BW_STATS_COUNT_THRESHOLD + 2; i++) { if (i == 1) { addTxBytes(10_000L); subtractRxBytes(500_000L); } else { addTxBytes(10_000L); addRxBytes(500_000L); } addElapsedTime(5_100); moveTimeForward(5_100); processAllMessages(); mLBE.obtainMessage(MSG_MODEM_ACTIVITY_RETURNED, new ModemActivityInfo( i * 5_100L, 0, 0, TX_TIME_2_MS, i * RX_TIME_2_MS)).sendToTarget(); processAllMessages(); } verify(mTelephonyManager, times(BW_STATS_COUNT_THRESHOLD)) .requestModemActivityInfo(any(), any()); verify(mDataConnection, times(1)).updateLinkBandwidthEstimation(eq(-1), eq(-1)); } @Test public void testUseCurrentTacStatsWithEnoughData() throws Exception { mLBE.obtainMessage(MSG_SCREEN_STATE_CHANGED, true).sendToTarget(); Loading
tests/telephonytests/src/com/android/internal/telephony/metrics/TelephonyMetricsTest.java +39 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_D import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_GATEWAY; import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_IFNAME; import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_PCSCF_ADDRESS; import static com.android.internal.telephony.dataconnection.LinkBandwidthEstimator.NUM_SIGNAL_LEVEL; import static com.android.internal.telephony.nano.TelephonyProto.PdpType.PDP_TYPE_IPV4V6; import static org.junit.Assert.assertArrayEquals; Loading Loading @@ -59,8 +60,11 @@ import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.SmsResponse; import com.android.internal.telephony.TelephonyTest; import com.android.internal.telephony.UUSInfo; import com.android.internal.telephony.dataconnection.LinkBandwidthEstimator; import com.android.internal.telephony.nano.TelephonyProto; import com.android.internal.telephony.nano.TelephonyProto.BandwidthEstimatorStats; import com.android.internal.telephony.nano.TelephonyProto.ImsConnectionState; import com.android.internal.telephony.nano.TelephonyProto.NrMode; import com.android.internal.telephony.nano.TelephonyProto.RadioAccessTechnology; import com.android.internal.telephony.nano.TelephonyProto.SmsSession; import com.android.internal.telephony.nano.TelephonyProto.TelephonyCallSession; Loading Loading @@ -872,4 +876,39 @@ public class TelephonyMetricsTest extends TelephonyTest { assertEquals(false, event.imsCapabilities.videoOverLte); assertEquals(false, event.imsCapabilities.utOverLte); } // Test write Bandwidth Stats @Test @SmallTest public void testWriteBandwidthStats() throws Exception { addBandwidthStats(LinkBandwidthEstimator.LINK_TX, TelephonyManager.NETWORK_TYPE_LTE, NrMode.NR_NSA_MMWAVE); addBandwidthStats(LinkBandwidthEstimator.LINK_RX, TelephonyManager.NETWORK_TYPE_LTE, NrMode.NR_NSA_MMWAVE); addBandwidthStats(LinkBandwidthEstimator.LINK_RX, TelephonyManager.NETWORK_TYPE_NR, NrMode.NR_SA_MMWAVE); TelephonyLog log = buildProto(); BandwidthEstimatorStats stats = log.bandwidthEstimatorStats; assertEquals(1, stats.perRatTx.length); assertEquals(2, stats.perRatRx.length); assertEquals(TelephonyManager.NETWORK_TYPE_LTE, stats.perRatTx[0].rat); assertEquals(NrMode.NR_NSA_MMWAVE, stats.perRatTx[0].nrMode); assertEquals(NUM_SIGNAL_LEVEL - 1, stats.perRatTx[0].perLevel.length); assertEquals(2, stats.perRatTx[0].perLevel[0].count); assertEquals(0, stats.perRatTx[0].perLevel[0].signalLevel); assertEquals(500_000, stats.perRatTx[0].perLevel[0].avgBwKbps); assertEquals(41, stats.perRatTx[0].perLevel[0].staticBwNrmsePercent); assertEquals(31, stats.perRatTx[0].perLevel[0].bwEstNrmsePercent); } private void addBandwidthStats(int link, int dataRat, int nrMode) { for (int i = 0; i < NUM_SIGNAL_LEVEL - 1; i++) { mMetrics.writeBandwidthStats(link, dataRat, nrMode, i, 10, 20, 30, 300_000); mMetrics.writeBandwidthStats(link, dataRat, nrMode, i, 30, 40, 50, 500_000); } } }