Loading proto/src/telephony.proto +4 −4 Original line number Diff line number Diff line Loading @@ -2707,10 +2707,10 @@ message BandwidthEstimatorStats { 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; // Normalized error of static BW values in percent optional uint32 static_bw_error_percent = 4; // Normalized error of end-to-end BW estimation in percent optional uint32 bw_est_error_percent = 5; } // Bandwidth stats of each RAT Loading src/java/com/android/internal/telephony/dataconnection/DataConnection.java +16 −10 Original line number Diff line number Diff line Loading @@ -1668,12 +1668,6 @@ public class DataConnection extends StateMachine { } } /** Update Tx and Rx link bandwidth estimation values */ public void updateLinkBandwidthEstimation(int uplinkBandwidthKbps, int downlinkBandwidthKbps) { sendMessage(DataConnection.EVENT_LINK_BANDWIDTH_ESTIMATOR_UPDATE, new Pair<Integer, Integer>(uplinkBandwidthKbps, downlinkBandwidthKbps)); } private boolean isBandwidthSourceKey(String source) { return source.equals(mPhone.getContext().getResources().getString( com.android.internal.R.string.config_bandwidthEstimateSource)); Loading Loading @@ -2211,6 +2205,10 @@ public class DataConnection extends StateMachine { DataConnection.EVENT_NR_FREQUENCY_CHANGED, null); mPhone.getServiceStateTracker().registerForCssIndicatorChanged(getHandler(), DataConnection.EVENT_CSS_INDICATOR_CHANGED, null); if (isBandwidthSourceKey(DctConstants.BANDWIDTH_SOURCE_BANDWIDTH_ESTIMATOR_KEY)) { mPhone.getLinkBandwidthEstimator().registerForBandwidthChanged(getHandler(), DataConnection.EVENT_LINK_BANDWIDTH_ESTIMATOR_UPDATE, null); } // Add ourselves to the list of data connections mDcController.addDc(DataConnection.this); Loading @@ -2228,6 +2226,9 @@ public class DataConnection extends StateMachine { mPhone.getServiceStateTracker().unregisterForNrStateChanged(getHandler()); mPhone.getServiceStateTracker().unregisterForNrFrequencyChanged(getHandler()); mPhone.getServiceStateTracker().unregisterForCssIndicatorChanged(getHandler()); if (isBandwidthSourceKey(DctConstants.BANDWIDTH_SOURCE_BANDWIDTH_ESTIMATOR_KEY)) { mPhone.getLinkBandwidthEstimator().unregisterForBandwidthChanged(getHandler()); } // Remove ourselves from the DC lists mDcController.removeDc(DataConnection.this); Loading Loading @@ -3235,11 +3236,16 @@ public class DataConnection extends StateMachine { break; } case EVENT_LINK_BANDWIDTH_ESTIMATOR_UPDATE: { Pair<Integer, Integer> pair = (Pair<Integer, Integer>) msg.obj; AsyncResult ar = (AsyncResult) msg.obj; if (ar.exception != null) { loge("EVENT_LINK_BANDWIDTH_ESTIMATOR_UPDATE e=" + ar.exception); } else { Pair<Integer, Integer> pair = (Pair<Integer, Integer>) ar.result; if (isBandwidthSourceKey( DctConstants.BANDWIDTH_SOURCE_BANDWIDTH_ESTIMATOR_KEY)) { updateLinkBandwidthsFromBandwidthEstimator(pair.first, pair.second); } } retVal = HANDLED; break; } Loading src/java/com/android/internal/telephony/dataconnection/LinkBandwidthEstimator.java +110 −48 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ import android.os.Handler; import android.os.HandlerExecutor; import android.os.Message; import android.os.OutcomeReceiver; import android.os.Registrant; import android.os.RegistrantList; import android.preference.PreferenceManager; import android.telephony.AccessNetworkConstants; import android.telephony.CellIdentity; Loading @@ -53,7 +55,6 @@ import android.view.Display; import com.android.internal.annotations.VisibleForTesting; 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; Loading Loading @@ -86,6 +87,8 @@ public class LinkBandwidthEstimator extends Handler { static final int MSG_NR_FREQUENCY_CHANGED = 6; @VisibleForTesting static final int MSG_NR_STATE_CHANGED = 7; @VisibleForTesting static final int MSG_ACTIVE_PHONE_CHANGED = 8; // TODO: move the following parameters to xml file private static final int TRAFFIC_STATS_POLL_INTERVAL_MS = 1_000; Loading Loading @@ -138,6 +141,7 @@ public class LinkBandwidthEstimator extends Handler { "LTE:30000,15000", "NR_NSA:47000,18000", "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<>(); private static final String UNKNOWN_PLMN = ""; // To be used in the long term avg, each count needs to be above the following value public static final int BW_STATS_COUNT_THRESHOLD = 5; Loading @@ -146,6 +150,7 @@ public class LinkBandwidthEstimator extends Handler { public static final int LINK_RX = 1; public static final int NUM_LINK_DIRECTION = 2; // One common timestamp for all sim to avoid frequent modem polling private final Phone mPhone; private final TelephonyFacade mTelephonyFacade; private final TelephonyManager mTelephonyManager; Loading @@ -153,6 +158,7 @@ public class LinkBandwidthEstimator extends Handler { private final LocalLog mLocalLog = new LocalLog(512); private boolean mScreenOn = false; private boolean mIsOnDefaultRoute = false; private boolean mIsOnActiveData = false; private long mLastModemPollTimeMs; private boolean mLastTrafficValid = true; private long mLastMobileTxBytes; Loading @@ -166,19 +172,20 @@ public class LinkBandwidthEstimator extends Handler { private int mSignalLevel; private int mDataRat = TelephonyManager.NETWORK_TYPE_UNKNOWN; private int mTac; private String mPlmn = ""; private String mPlmn = UNKNOWN_PLMN; private NetworkCapabilities mNetworkCapabilities; private NetworkBandwidth mPlaceholderNetwork; private long mFilterUpdateTimeMs; private int mBandwidthUpdateSignalDbm = -1; private int mBandwidthUpdateSignalLevel = -1; private int mBandwidthUpdateDataRat = TelephonyManager.NETWORK_TYPE_UNKNOWN; private String mBandwidthUpdatePlmn = ""; private String mBandwidthUpdatePlmn = UNKNOWN_PLMN; private BandwidthState mTxState = new BandwidthState(LINK_TX); private BandwidthState mRxState = new BandwidthState(LINK_RX); private RegistrantList mBandwidthChangedRegistrants = new RegistrantList(); private static void initAvgBwPerRatTable() { for (String config : AVG_BW_PER_RAT) { int rxKbps = 14; Loading Loading @@ -256,9 +263,9 @@ public class LinkBandwidthEstimator extends Handler { mConnectivityManager.registerDefaultNetworkCallback(mDefaultNetworkCallback, this); mTelephonyManager.registerTelephonyCallback(new HandlerExecutor(this), mTelephonyCallback); mPlaceholderNetwork = new NetworkBandwidth(""); mPlaceholderNetwork = new NetworkBandwidth(UNKNOWN_PLMN); initAvgBwPerRatTable(); registerDataServiceState(); registerNrStateFrequencyChange(); } @Override Loading @@ -285,12 +292,35 @@ public class LinkBandwidthEstimator extends Handler { case MSG_NR_STATE_CHANGED: updateStaticBwValueResetFilter(); break; case MSG_ACTIVE_PHONE_CHANGED: handleActivePhoneChanged((int) msg.obj); break; default: Rlog.e(TAG, "invalid message " + msg.what); break; } } /** * Registers for bandwidth estimation change. The bandwidth will be returned * * {@link AsyncResult#result} as a {@link Pair} Object. * * The {@link AsyncResult} will be in the notification {@link Message#obj}. * @param h handler to notify * @param what what code of message when delivered * @param obj placed in Message.obj */ public void registerForBandwidthChanged(Handler h, int what, Object obj) { Registrant r = new Registrant(h, what, obj); mBandwidthChangedRegistrants.add(r); } /** * Unregisters for bandwidth estimation change. * @param h handler to notify */ public void unregisterForBandwidthChanged(Handler h) { mBandwidthChangedRegistrants.remove(h); } /** * @return True if one the device's screen (e.g. main screen, wifi display, HDMI display etc...) * is on. Loading Loading @@ -340,15 +370,26 @@ public class LinkBandwidthEstimator extends Handler { handleTrafficStatsPollConditionChanged(); } private void handleActivePhoneChanged(int activeDataSubId) { boolean isOnActiveData = activeDataSubId == mPhone.getSubId(); if (mIsOnActiveData == isOnActiveData) { return; } mIsOnActiveData = isOnActiveData; logd("mIsOnActiveData " + mIsOnActiveData + " activeDataSubId " + activeDataSubId); handleTrafficStatsPollConditionChanged(); } private void handleTrafficStatsPollConditionChanged() { removeMessages(MSG_TRAFFIC_STATS_POLL); if (mScreenOn && mIsOnDefaultRoute) { updateDataRatCellIdentity(); if (mScreenOn && mIsOnDefaultRoute && mIsOnActiveData) { updateDataRatCellIdentityBandwidth(); handleTrafficStatsPoll(); } } private void handleTrafficStatsPoll() { invalidateTxRxSamples(); long mobileTxBytes = mTelephonyFacade.getMobileTxBytes(); long mobileRxBytes = mTelephonyFacade.getMobileRxBytes(); long txBytesDelta = mobileTxBytes - mLastMobileTxBytes; Loading Loading @@ -396,7 +437,7 @@ public class LinkBandwidthEstimator extends Handler { .append(" txByteDeltaAcc ").append(mTxBytesDeltaAcc) .append(" rxByteDeltaAcc ").append(mRxBytesDeltaAcc) .append(" trigger modem activity request").toString()); updateDataRatCellIdentity(); updateDataRatCellIdentityBandwidth(); // Filter update will happen after the request makeRequestModemActivity(); return; Loading @@ -405,10 +446,12 @@ public class LinkBandwidthEstimator extends Handler { long timeSinceLastFilterUpdateMs = currTimeMs - mFilterUpdateTimeMs; // Update filter if (timeSinceLastFilterUpdateMs >= FILTER_UPDATE_MAX_INTERVAL_MS) { updateDataRatCellIdentity(); boolean updatedBandwidth = updateDataRatCellIdentityBandwidth(); if (!updatedBandwidth) { updateTxRxBandwidthFilterSendToDataConnection(); } } } private void makeRequestModemActivity() { mLastModemPollTimeMs = mTelephonyFacade.getElapsedSinceBootMillis(); Loading @@ -422,7 +465,6 @@ public class LinkBandwidthEstimator extends Handler { mLastModemActivityInfo = result; // Update for next poll resetByteDeltaAcc(); invalidateTxRxSamples(); } private void resetByteDeltaAcc() { Loading Loading @@ -495,11 +537,12 @@ public class LinkBandwidthEstimator extends Handler { mTxState.updateBandwidthFilter(); mRxState.updateBandwidthFilter(); if (mTxState.hasLargeBwChange() boolean isNetworkChanged = mTxState.hasLargeBwChange() || mRxState.hasLargeBwChange() || mBandwidthUpdateDataRat != mDataRat || mBandwidthUpdateSignalLevel != mSignalLevel || !mBandwidthUpdatePlmn.equals(mPlmn)) { || !mBandwidthUpdatePlmn.equals(mPlmn); if (isValidNetwork() && isNetworkChanged) { mTxState.mLastReportedBwKbps = mTxState.mAvgUsedKbps < 0 ? -1 : mTxState.mFilterKbps; mRxState.mLastReportedBwKbps = mRxState.mAvgUsedKbps < 0 ? -1 : mRxState.mFilterKbps; sendLinkBandwidthToDataConnection( Loading @@ -515,6 +558,10 @@ public class LinkBandwidthEstimator extends Handler { mRxState.calculateError(); } private boolean isValidNetwork() { return !mPlmn.equals(UNKNOWN_PLMN) && mDataRat != TelephonyManager.NETWORK_TYPE_UNKNOWN; } private class BandwidthState { private final int mLink; int mFilterKbps; Loading @@ -538,7 +585,11 @@ public class LinkBandwidthEstimator extends Handler { if (timeDeltaMs < TX_RX_TIME_MIN_MS) { return; } int linkBandwidthKbps = (int) (bytesDelta * 8 * 1000 / timeDeltaMs / 1024); long linkBandwidthLongKbps = bytesDelta * 8 / timeDeltaMs * 1000 / 1024; if (linkBandwidthLongKbps > Integer.MAX_VALUE || linkBandwidthLongKbps < 0) { return; } int linkBandwidthKbps = (int) linkBandwidthLongKbps; mBwSampleValid = true; mBwSampleKbps = linkBandwidthKbps; Loading Loading @@ -578,14 +629,20 @@ public class LinkBandwidthEstimator extends Handler { } if (filterInKbps == mFilterKbps) { logv(mLink + " skip filter because the same input / current = " + filterInKbps); return; } int alpha = timeDeltaSec > LARGE_TIME_DECAY_RATIO * timeConstantSec ? 0 : (int) (FILTER_SCALE * Math.exp(-1.0 * timeDeltaSec / timeConstantSec)); mFilterKbps = alpha == 0 ? filterInKbps : ((mFilterKbps * alpha + filterInKbps * FILTER_SCALE - filterInKbps * alpha) / FILTER_SCALE); if (alpha == 0) { mFilterKbps = filterInKbps; return; } long filterOutKbps = (long) mFilterKbps * alpha + filterInKbps * FILTER_SCALE - filterInKbps * alpha; filterOutKbps = filterOutKbps / FILTER_SCALE; mFilterKbps = (int) Math.min(filterOutKbps, Integer.MAX_VALUE); StringBuilder sb = new StringBuilder(); logv(sb.append(mLink) .append(" lastSampleWeight=").append(alpha) Loading Loading @@ -631,6 +688,7 @@ public class LinkBandwidthEstimator extends Handler { } private void resetBandwidthFilter() { mBwSampleValid = false; mFilterKbps = getAvgLinkBandwidthKbps(); } Loading Loading @@ -660,8 +718,9 @@ public class LinkBandwidthEstimator extends Handler { // Calculate a byte count threshold for the given avg BW and observation window size private int calculateByteCountThreshold(int avgBwKbps, int durationMs) { int avgBytes = avgBwKbps / 8 * durationMs; return avgBytes * LOW_BW_TO_AVG_BW_RATIO_NUM / LOW_BW_TO_AVG_BW_RATIO_DEN; long avgBytes = (long) avgBwKbps / 8 * durationMs; long result = avgBytes * LOW_BW_TO_AVG_BW_RATIO_NUM / LOW_BW_TO_AVG_BW_RATIO_DEN; return (int) Math.min(result, Integer.MAX_VALUE); } public boolean hasLargeBwChange() { Loading @@ -671,7 +730,8 @@ public class LinkBandwidthEstimator extends Handler { } public void calculateError() { if (!mBwSampleValid || getCurrentCount() <= BW_STATS_COUNT_THRESHOLD + 1) { if (!mBwSampleValid || getCurrentCount() <= BW_STATS_COUNT_THRESHOLD + 1 || mAvgUsedKbps <= 0) { return; } int bwEstExtErrPercent = calculateErrorPercent(mLastReportedBwKbps, mBwSampleKbps); Loading @@ -680,8 +740,7 @@ public class LinkBandwidthEstimator extends Handler { int coldStartErrPercent = calculateErrorPercent(mStaticBwKbps, mBwSampleKbps); TelephonyMetrics.getInstance().writeBandwidthStats(mLink, mDataRat, getNrMode(mDataRat), mSignalLevel, bwEstIntErrPercent, bwEstExtErrPercent, coldStartErrPercent, mAvgUsedKbps); mSignalLevel, bwEstExtErrPercent, coldStartErrPercent, mAvgUsedKbps); StringBuilder sb = new StringBuilder(); logd(sb.append(mLink) Loading @@ -698,9 +757,8 @@ public class LinkBandwidthEstimator extends Handler { } private int calculateErrorPercent(int inKbps, int bwSampleKbps) { int errorKbps = inKbps - bwSampleKbps; int errorPercent = bwSampleKbps > 0 ? (errorKbps * 100 / bwSampleKbps) : 0; return Math.max(-MAX_ERROR_PERCENT, Math.min(errorPercent, MAX_ERROR_PERCENT)); long errorPercent = 100L * (inKbps - bwSampleKbps) / bwSampleKbps; return (int) Math.max(-MAX_ERROR_PERCENT, Math.min(errorPercent, MAX_ERROR_PERCENT)); } } Loading @@ -718,22 +776,15 @@ public class LinkBandwidthEstimator extends Handler { // Reset BW filter to a long term avg value (PLMN/RAT/TAC dependent) or static BW value. // It should be called whenever PLMN/RAT or static BW value is changed; private void resetBandwidthFilter() { StringBuilder sb = new StringBuilder(); mTxState.resetBandwidthFilter(); mRxState.resetBandwidthFilter(); } private void sendLinkBandwidthToDataConnection(int linkBandwidthTxKps, int linkBandwidthRxKps) { DcTracker dt = mPhone.getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN); if (dt == null) { return; } DataConnection dc = dt.getDataConnectionByApnType(PhoneConstants.APN_TYPE_DEFAULT); if (dc == null) { return; } logv("send to DC tx " + linkBandwidthTxKps + " rx " + linkBandwidthRxKps); dc.updateLinkBandwidthEstimation(linkBandwidthTxKps, linkBandwidthRxKps); Pair<Integer, Integer> bandwidthInfo = new Pair<Integer, Integer>(linkBandwidthTxKps, linkBandwidthRxKps); mBandwidthChangedRegistrants.notifyRegistrants(new AsyncResult(null, bandwidthInfo, null)); } private void handleSignalStrengthChanged(SignalStrength signalStrength) { Loading @@ -741,17 +792,20 @@ public class LinkBandwidthEstimator extends Handler { return; } updateDataRatCellIdentity(); mSignalStrengthDbm = signalStrength.getDbm(); mSignalLevel = signalStrength.getLevel(); if (Math.abs(mBandwidthUpdateSignalDbm - mSignalStrengthDbm) > RSSI_DELTA_THRESHOLD_DB) { updateByteCountThr(); boolean updatedBandwidth = updateDataRatCellIdentityBandwidth(); if (updatedBandwidth) { return; } if (Math.abs(mBandwidthUpdateSignalDbm - mSignalStrengthDbm) > RSSI_DELTA_THRESHOLD_DB) { updateTxRxBandwidthFilterSendToDataConnection(); } } private void registerDataServiceState() { private void registerNrStateFrequencyChange() { mPhone.getServiceStateTracker().registerForNrStateChanged(this, MSG_NR_STATE_CHANGED, null); mPhone.getServiceStateTracker().registerForNrFrequencyChanged(this, Loading Loading @@ -843,18 +897,19 @@ public class LinkBandwidthEstimator extends Handler { NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); } private void updateDataRatCellIdentity() { private boolean updateDataRatCellIdentityBandwidth() { boolean updatedPlmn = false; CellIdentity cellIdentity = mPhone.getCurrentCellIdentity(); mTac = getTac(cellIdentity); String plmn; if (mPhone.getServiceState().getOperatorNumeric() != null) { plmn = mPhone.getServiceState().getOperatorNumeric(); } else { if (cellIdentity.getPlmn() != null) { plmn = cellIdentity.getPlmn(); } else { if (cellIdentity.getOperatorAlphaShort() != null) { plmn = cellIdentity.getOperatorAlphaShort().toString(); } else { plmn = ""; plmn = UNKNOWN_PLMN; } } if (mPlmn == null || !plmn.equals(mPlmn)) { Loading @@ -874,10 +929,12 @@ public class LinkBandwidthEstimator extends Handler { } } if (updatedPlmn || updatedRat) { boolean updatedPlmnOrRat = updatedPlmn || updatedRat; if (updatedPlmnOrRat) { resetBandwidthFilter(); updateTxRxBandwidthFilterSendToDataConnection(); } return updatedPlmnOrRat; } private int getTac(@NonNull CellIdentity cellIdentity) { Loading @@ -900,11 +957,16 @@ public class LinkBandwidthEstimator extends Handler { } private class TelephonyCallbackImpl extends TelephonyCallback implements TelephonyCallback.SignalStrengthsListener { TelephonyCallback.SignalStrengthsListener, TelephonyCallback.ActiveDataSubscriptionIdListener { @Override public void onSignalStrengthsChanged(SignalStrength signalStrength) { obtainMessage(MSG_SIGNAL_STRENGTH_CHANGED, signalStrength).sendToTarget(); } @Override public void onActiveDataSubscriptionIdChanged(int subId) { obtainMessage(MSG_ACTIVE_PHONE_CHANGED, subId).sendToTarget(); } } void logv(String msg) { Loading src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java +12 −17 Original line number Diff line number Diff line Loading @@ -2934,12 +2934,10 @@ public class TelephonyMetrics { * Write bandwidth estimator stats */ public synchronized void writeBandwidthStats(int link, int rat, int nrMode, int signalLevel, int bwEstIntErrPercent, int bwEstExtErrPercent, int coldStartErrPercent, int avgUsedKbps) { int signalLevel, 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.mBwEstErrorAcc[signalLevel] += Math.abs(bwEstExtErrPercent); stats.mStaticBwErrorAcc[signalLevel] += Math.abs(coldStartErrPercent); stats.mAvgBwKbps[signalLevel] = avgUsedKbps; stats.mCount[signalLevel]++; } Loading Loading @@ -2976,9 +2974,8 @@ public class TelephonyMetrics { 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 long[] mBwEstErrorAcc = new long[NUM_SIGNAL_LEVEL]; final long[] mStaticBwErrorAcc = new long[NUM_SIGNAL_LEVEL]; final int[] mAvgBwKbps = new int[NUM_SIGNAL_LEVEL]; final int[] mCount = new int[NUM_SIGNAL_LEVEL]; Loading @@ -2993,9 +2990,8 @@ public class TelephonyMetrics { 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)) .append("\n BwEst Error\n").append(printAvgError(mBwEstErrorAcc, mCount)) .append("\n StaticBw Error\n").append(printAvgError(mStaticBwErrorAcc, mCount)) .toString(); } Loading @@ -3010,8 +3006,7 @@ public class TelephonyMetrics { 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; int avgStat = calculateAvgError(stats[k], count[k]); sb.append(" " + avgStat); } return sb.toString(); Loading Loading @@ -3039,15 +3034,15 @@ public class TelephonyMetrics { stats.signalLevel = level; stats.count = count; stats.avgBwKbps = mAvgBwKbps[level]; stats.staticBwNrmsePercent = calculateNrmse(mStaticBwNse[level], count); stats.bwEstNrmsePercent = calculateNrmse(mBwEstExtNse[level], count); stats.staticBwErrorPercent = calculateAvgError(mStaticBwErrorAcc[level], count); stats.bwEstErrorPercent = calculateAvgError(mBwEstErrorAcc[level], count); return stats; } return null; } private int calculateNrmse(long nse, int count) { return (count > 0 && nse >= 0) ? (int) Math.sqrt(nse / count) : 0; private int calculateAvgError(long errorAccPercent, int count) { return (count > 0) ? (int) (errorAccPercent / count) : 0; } } Loading tests/telephonytests/src/com/android/internal/telephony/dataconnection/LinkBandwidthEstimatorTest.java +98 −23 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
proto/src/telephony.proto +4 −4 Original line number Diff line number Diff line Loading @@ -2707,10 +2707,10 @@ message BandwidthEstimatorStats { 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; // Normalized error of static BW values in percent optional uint32 static_bw_error_percent = 4; // Normalized error of end-to-end BW estimation in percent optional uint32 bw_est_error_percent = 5; } // Bandwidth stats of each RAT Loading
src/java/com/android/internal/telephony/dataconnection/DataConnection.java +16 −10 Original line number Diff line number Diff line Loading @@ -1668,12 +1668,6 @@ public class DataConnection extends StateMachine { } } /** Update Tx and Rx link bandwidth estimation values */ public void updateLinkBandwidthEstimation(int uplinkBandwidthKbps, int downlinkBandwidthKbps) { sendMessage(DataConnection.EVENT_LINK_BANDWIDTH_ESTIMATOR_UPDATE, new Pair<Integer, Integer>(uplinkBandwidthKbps, downlinkBandwidthKbps)); } private boolean isBandwidthSourceKey(String source) { return source.equals(mPhone.getContext().getResources().getString( com.android.internal.R.string.config_bandwidthEstimateSource)); Loading Loading @@ -2211,6 +2205,10 @@ public class DataConnection extends StateMachine { DataConnection.EVENT_NR_FREQUENCY_CHANGED, null); mPhone.getServiceStateTracker().registerForCssIndicatorChanged(getHandler(), DataConnection.EVENT_CSS_INDICATOR_CHANGED, null); if (isBandwidthSourceKey(DctConstants.BANDWIDTH_SOURCE_BANDWIDTH_ESTIMATOR_KEY)) { mPhone.getLinkBandwidthEstimator().registerForBandwidthChanged(getHandler(), DataConnection.EVENT_LINK_BANDWIDTH_ESTIMATOR_UPDATE, null); } // Add ourselves to the list of data connections mDcController.addDc(DataConnection.this); Loading @@ -2228,6 +2226,9 @@ public class DataConnection extends StateMachine { mPhone.getServiceStateTracker().unregisterForNrStateChanged(getHandler()); mPhone.getServiceStateTracker().unregisterForNrFrequencyChanged(getHandler()); mPhone.getServiceStateTracker().unregisterForCssIndicatorChanged(getHandler()); if (isBandwidthSourceKey(DctConstants.BANDWIDTH_SOURCE_BANDWIDTH_ESTIMATOR_KEY)) { mPhone.getLinkBandwidthEstimator().unregisterForBandwidthChanged(getHandler()); } // Remove ourselves from the DC lists mDcController.removeDc(DataConnection.this); Loading Loading @@ -3235,11 +3236,16 @@ public class DataConnection extends StateMachine { break; } case EVENT_LINK_BANDWIDTH_ESTIMATOR_UPDATE: { Pair<Integer, Integer> pair = (Pair<Integer, Integer>) msg.obj; AsyncResult ar = (AsyncResult) msg.obj; if (ar.exception != null) { loge("EVENT_LINK_BANDWIDTH_ESTIMATOR_UPDATE e=" + ar.exception); } else { Pair<Integer, Integer> pair = (Pair<Integer, Integer>) ar.result; if (isBandwidthSourceKey( DctConstants.BANDWIDTH_SOURCE_BANDWIDTH_ESTIMATOR_KEY)) { updateLinkBandwidthsFromBandwidthEstimator(pair.first, pair.second); } } retVal = HANDLED; break; } Loading
src/java/com/android/internal/telephony/dataconnection/LinkBandwidthEstimator.java +110 −48 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ import android.os.Handler; import android.os.HandlerExecutor; import android.os.Message; import android.os.OutcomeReceiver; import android.os.Registrant; import android.os.RegistrantList; import android.preference.PreferenceManager; import android.telephony.AccessNetworkConstants; import android.telephony.CellIdentity; Loading @@ -53,7 +55,6 @@ import android.view.Display; import com.android.internal.annotations.VisibleForTesting; 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; Loading Loading @@ -86,6 +87,8 @@ public class LinkBandwidthEstimator extends Handler { static final int MSG_NR_FREQUENCY_CHANGED = 6; @VisibleForTesting static final int MSG_NR_STATE_CHANGED = 7; @VisibleForTesting static final int MSG_ACTIVE_PHONE_CHANGED = 8; // TODO: move the following parameters to xml file private static final int TRAFFIC_STATS_POLL_INTERVAL_MS = 1_000; Loading Loading @@ -138,6 +141,7 @@ public class LinkBandwidthEstimator extends Handler { "LTE:30000,15000", "NR_NSA:47000,18000", "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<>(); private static final String UNKNOWN_PLMN = ""; // To be used in the long term avg, each count needs to be above the following value public static final int BW_STATS_COUNT_THRESHOLD = 5; Loading @@ -146,6 +150,7 @@ public class LinkBandwidthEstimator extends Handler { public static final int LINK_RX = 1; public static final int NUM_LINK_DIRECTION = 2; // One common timestamp for all sim to avoid frequent modem polling private final Phone mPhone; private final TelephonyFacade mTelephonyFacade; private final TelephonyManager mTelephonyManager; Loading @@ -153,6 +158,7 @@ public class LinkBandwidthEstimator extends Handler { private final LocalLog mLocalLog = new LocalLog(512); private boolean mScreenOn = false; private boolean mIsOnDefaultRoute = false; private boolean mIsOnActiveData = false; private long mLastModemPollTimeMs; private boolean mLastTrafficValid = true; private long mLastMobileTxBytes; Loading @@ -166,19 +172,20 @@ public class LinkBandwidthEstimator extends Handler { private int mSignalLevel; private int mDataRat = TelephonyManager.NETWORK_TYPE_UNKNOWN; private int mTac; private String mPlmn = ""; private String mPlmn = UNKNOWN_PLMN; private NetworkCapabilities mNetworkCapabilities; private NetworkBandwidth mPlaceholderNetwork; private long mFilterUpdateTimeMs; private int mBandwidthUpdateSignalDbm = -1; private int mBandwidthUpdateSignalLevel = -1; private int mBandwidthUpdateDataRat = TelephonyManager.NETWORK_TYPE_UNKNOWN; private String mBandwidthUpdatePlmn = ""; private String mBandwidthUpdatePlmn = UNKNOWN_PLMN; private BandwidthState mTxState = new BandwidthState(LINK_TX); private BandwidthState mRxState = new BandwidthState(LINK_RX); private RegistrantList mBandwidthChangedRegistrants = new RegistrantList(); private static void initAvgBwPerRatTable() { for (String config : AVG_BW_PER_RAT) { int rxKbps = 14; Loading Loading @@ -256,9 +263,9 @@ public class LinkBandwidthEstimator extends Handler { mConnectivityManager.registerDefaultNetworkCallback(mDefaultNetworkCallback, this); mTelephonyManager.registerTelephonyCallback(new HandlerExecutor(this), mTelephonyCallback); mPlaceholderNetwork = new NetworkBandwidth(""); mPlaceholderNetwork = new NetworkBandwidth(UNKNOWN_PLMN); initAvgBwPerRatTable(); registerDataServiceState(); registerNrStateFrequencyChange(); } @Override Loading @@ -285,12 +292,35 @@ public class LinkBandwidthEstimator extends Handler { case MSG_NR_STATE_CHANGED: updateStaticBwValueResetFilter(); break; case MSG_ACTIVE_PHONE_CHANGED: handleActivePhoneChanged((int) msg.obj); break; default: Rlog.e(TAG, "invalid message " + msg.what); break; } } /** * Registers for bandwidth estimation change. The bandwidth will be returned * * {@link AsyncResult#result} as a {@link Pair} Object. * * The {@link AsyncResult} will be in the notification {@link Message#obj}. * @param h handler to notify * @param what what code of message when delivered * @param obj placed in Message.obj */ public void registerForBandwidthChanged(Handler h, int what, Object obj) { Registrant r = new Registrant(h, what, obj); mBandwidthChangedRegistrants.add(r); } /** * Unregisters for bandwidth estimation change. * @param h handler to notify */ public void unregisterForBandwidthChanged(Handler h) { mBandwidthChangedRegistrants.remove(h); } /** * @return True if one the device's screen (e.g. main screen, wifi display, HDMI display etc...) * is on. Loading Loading @@ -340,15 +370,26 @@ public class LinkBandwidthEstimator extends Handler { handleTrafficStatsPollConditionChanged(); } private void handleActivePhoneChanged(int activeDataSubId) { boolean isOnActiveData = activeDataSubId == mPhone.getSubId(); if (mIsOnActiveData == isOnActiveData) { return; } mIsOnActiveData = isOnActiveData; logd("mIsOnActiveData " + mIsOnActiveData + " activeDataSubId " + activeDataSubId); handleTrafficStatsPollConditionChanged(); } private void handleTrafficStatsPollConditionChanged() { removeMessages(MSG_TRAFFIC_STATS_POLL); if (mScreenOn && mIsOnDefaultRoute) { updateDataRatCellIdentity(); if (mScreenOn && mIsOnDefaultRoute && mIsOnActiveData) { updateDataRatCellIdentityBandwidth(); handleTrafficStatsPoll(); } } private void handleTrafficStatsPoll() { invalidateTxRxSamples(); long mobileTxBytes = mTelephonyFacade.getMobileTxBytes(); long mobileRxBytes = mTelephonyFacade.getMobileRxBytes(); long txBytesDelta = mobileTxBytes - mLastMobileTxBytes; Loading Loading @@ -396,7 +437,7 @@ public class LinkBandwidthEstimator extends Handler { .append(" txByteDeltaAcc ").append(mTxBytesDeltaAcc) .append(" rxByteDeltaAcc ").append(mRxBytesDeltaAcc) .append(" trigger modem activity request").toString()); updateDataRatCellIdentity(); updateDataRatCellIdentityBandwidth(); // Filter update will happen after the request makeRequestModemActivity(); return; Loading @@ -405,10 +446,12 @@ public class LinkBandwidthEstimator extends Handler { long timeSinceLastFilterUpdateMs = currTimeMs - mFilterUpdateTimeMs; // Update filter if (timeSinceLastFilterUpdateMs >= FILTER_UPDATE_MAX_INTERVAL_MS) { updateDataRatCellIdentity(); boolean updatedBandwidth = updateDataRatCellIdentityBandwidth(); if (!updatedBandwidth) { updateTxRxBandwidthFilterSendToDataConnection(); } } } private void makeRequestModemActivity() { mLastModemPollTimeMs = mTelephonyFacade.getElapsedSinceBootMillis(); Loading @@ -422,7 +465,6 @@ public class LinkBandwidthEstimator extends Handler { mLastModemActivityInfo = result; // Update for next poll resetByteDeltaAcc(); invalidateTxRxSamples(); } private void resetByteDeltaAcc() { Loading Loading @@ -495,11 +537,12 @@ public class LinkBandwidthEstimator extends Handler { mTxState.updateBandwidthFilter(); mRxState.updateBandwidthFilter(); if (mTxState.hasLargeBwChange() boolean isNetworkChanged = mTxState.hasLargeBwChange() || mRxState.hasLargeBwChange() || mBandwidthUpdateDataRat != mDataRat || mBandwidthUpdateSignalLevel != mSignalLevel || !mBandwidthUpdatePlmn.equals(mPlmn)) { || !mBandwidthUpdatePlmn.equals(mPlmn); if (isValidNetwork() && isNetworkChanged) { mTxState.mLastReportedBwKbps = mTxState.mAvgUsedKbps < 0 ? -1 : mTxState.mFilterKbps; mRxState.mLastReportedBwKbps = mRxState.mAvgUsedKbps < 0 ? -1 : mRxState.mFilterKbps; sendLinkBandwidthToDataConnection( Loading @@ -515,6 +558,10 @@ public class LinkBandwidthEstimator extends Handler { mRxState.calculateError(); } private boolean isValidNetwork() { return !mPlmn.equals(UNKNOWN_PLMN) && mDataRat != TelephonyManager.NETWORK_TYPE_UNKNOWN; } private class BandwidthState { private final int mLink; int mFilterKbps; Loading @@ -538,7 +585,11 @@ public class LinkBandwidthEstimator extends Handler { if (timeDeltaMs < TX_RX_TIME_MIN_MS) { return; } int linkBandwidthKbps = (int) (bytesDelta * 8 * 1000 / timeDeltaMs / 1024); long linkBandwidthLongKbps = bytesDelta * 8 / timeDeltaMs * 1000 / 1024; if (linkBandwidthLongKbps > Integer.MAX_VALUE || linkBandwidthLongKbps < 0) { return; } int linkBandwidthKbps = (int) linkBandwidthLongKbps; mBwSampleValid = true; mBwSampleKbps = linkBandwidthKbps; Loading Loading @@ -578,14 +629,20 @@ public class LinkBandwidthEstimator extends Handler { } if (filterInKbps == mFilterKbps) { logv(mLink + " skip filter because the same input / current = " + filterInKbps); return; } int alpha = timeDeltaSec > LARGE_TIME_DECAY_RATIO * timeConstantSec ? 0 : (int) (FILTER_SCALE * Math.exp(-1.0 * timeDeltaSec / timeConstantSec)); mFilterKbps = alpha == 0 ? filterInKbps : ((mFilterKbps * alpha + filterInKbps * FILTER_SCALE - filterInKbps * alpha) / FILTER_SCALE); if (alpha == 0) { mFilterKbps = filterInKbps; return; } long filterOutKbps = (long) mFilterKbps * alpha + filterInKbps * FILTER_SCALE - filterInKbps * alpha; filterOutKbps = filterOutKbps / FILTER_SCALE; mFilterKbps = (int) Math.min(filterOutKbps, Integer.MAX_VALUE); StringBuilder sb = new StringBuilder(); logv(sb.append(mLink) .append(" lastSampleWeight=").append(alpha) Loading Loading @@ -631,6 +688,7 @@ public class LinkBandwidthEstimator extends Handler { } private void resetBandwidthFilter() { mBwSampleValid = false; mFilterKbps = getAvgLinkBandwidthKbps(); } Loading Loading @@ -660,8 +718,9 @@ public class LinkBandwidthEstimator extends Handler { // Calculate a byte count threshold for the given avg BW and observation window size private int calculateByteCountThreshold(int avgBwKbps, int durationMs) { int avgBytes = avgBwKbps / 8 * durationMs; return avgBytes * LOW_BW_TO_AVG_BW_RATIO_NUM / LOW_BW_TO_AVG_BW_RATIO_DEN; long avgBytes = (long) avgBwKbps / 8 * durationMs; long result = avgBytes * LOW_BW_TO_AVG_BW_RATIO_NUM / LOW_BW_TO_AVG_BW_RATIO_DEN; return (int) Math.min(result, Integer.MAX_VALUE); } public boolean hasLargeBwChange() { Loading @@ -671,7 +730,8 @@ public class LinkBandwidthEstimator extends Handler { } public void calculateError() { if (!mBwSampleValid || getCurrentCount() <= BW_STATS_COUNT_THRESHOLD + 1) { if (!mBwSampleValid || getCurrentCount() <= BW_STATS_COUNT_THRESHOLD + 1 || mAvgUsedKbps <= 0) { return; } int bwEstExtErrPercent = calculateErrorPercent(mLastReportedBwKbps, mBwSampleKbps); Loading @@ -680,8 +740,7 @@ public class LinkBandwidthEstimator extends Handler { int coldStartErrPercent = calculateErrorPercent(mStaticBwKbps, mBwSampleKbps); TelephonyMetrics.getInstance().writeBandwidthStats(mLink, mDataRat, getNrMode(mDataRat), mSignalLevel, bwEstIntErrPercent, bwEstExtErrPercent, coldStartErrPercent, mAvgUsedKbps); mSignalLevel, bwEstExtErrPercent, coldStartErrPercent, mAvgUsedKbps); StringBuilder sb = new StringBuilder(); logd(sb.append(mLink) Loading @@ -698,9 +757,8 @@ public class LinkBandwidthEstimator extends Handler { } private int calculateErrorPercent(int inKbps, int bwSampleKbps) { int errorKbps = inKbps - bwSampleKbps; int errorPercent = bwSampleKbps > 0 ? (errorKbps * 100 / bwSampleKbps) : 0; return Math.max(-MAX_ERROR_PERCENT, Math.min(errorPercent, MAX_ERROR_PERCENT)); long errorPercent = 100L * (inKbps - bwSampleKbps) / bwSampleKbps; return (int) Math.max(-MAX_ERROR_PERCENT, Math.min(errorPercent, MAX_ERROR_PERCENT)); } } Loading @@ -718,22 +776,15 @@ public class LinkBandwidthEstimator extends Handler { // Reset BW filter to a long term avg value (PLMN/RAT/TAC dependent) or static BW value. // It should be called whenever PLMN/RAT or static BW value is changed; private void resetBandwidthFilter() { StringBuilder sb = new StringBuilder(); mTxState.resetBandwidthFilter(); mRxState.resetBandwidthFilter(); } private void sendLinkBandwidthToDataConnection(int linkBandwidthTxKps, int linkBandwidthRxKps) { DcTracker dt = mPhone.getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN); if (dt == null) { return; } DataConnection dc = dt.getDataConnectionByApnType(PhoneConstants.APN_TYPE_DEFAULT); if (dc == null) { return; } logv("send to DC tx " + linkBandwidthTxKps + " rx " + linkBandwidthRxKps); dc.updateLinkBandwidthEstimation(linkBandwidthTxKps, linkBandwidthRxKps); Pair<Integer, Integer> bandwidthInfo = new Pair<Integer, Integer>(linkBandwidthTxKps, linkBandwidthRxKps); mBandwidthChangedRegistrants.notifyRegistrants(new AsyncResult(null, bandwidthInfo, null)); } private void handleSignalStrengthChanged(SignalStrength signalStrength) { Loading @@ -741,17 +792,20 @@ public class LinkBandwidthEstimator extends Handler { return; } updateDataRatCellIdentity(); mSignalStrengthDbm = signalStrength.getDbm(); mSignalLevel = signalStrength.getLevel(); if (Math.abs(mBandwidthUpdateSignalDbm - mSignalStrengthDbm) > RSSI_DELTA_THRESHOLD_DB) { updateByteCountThr(); boolean updatedBandwidth = updateDataRatCellIdentityBandwidth(); if (updatedBandwidth) { return; } if (Math.abs(mBandwidthUpdateSignalDbm - mSignalStrengthDbm) > RSSI_DELTA_THRESHOLD_DB) { updateTxRxBandwidthFilterSendToDataConnection(); } } private void registerDataServiceState() { private void registerNrStateFrequencyChange() { mPhone.getServiceStateTracker().registerForNrStateChanged(this, MSG_NR_STATE_CHANGED, null); mPhone.getServiceStateTracker().registerForNrFrequencyChanged(this, Loading Loading @@ -843,18 +897,19 @@ public class LinkBandwidthEstimator extends Handler { NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); } private void updateDataRatCellIdentity() { private boolean updateDataRatCellIdentityBandwidth() { boolean updatedPlmn = false; CellIdentity cellIdentity = mPhone.getCurrentCellIdentity(); mTac = getTac(cellIdentity); String plmn; if (mPhone.getServiceState().getOperatorNumeric() != null) { plmn = mPhone.getServiceState().getOperatorNumeric(); } else { if (cellIdentity.getPlmn() != null) { plmn = cellIdentity.getPlmn(); } else { if (cellIdentity.getOperatorAlphaShort() != null) { plmn = cellIdentity.getOperatorAlphaShort().toString(); } else { plmn = ""; plmn = UNKNOWN_PLMN; } } if (mPlmn == null || !plmn.equals(mPlmn)) { Loading @@ -874,10 +929,12 @@ public class LinkBandwidthEstimator extends Handler { } } if (updatedPlmn || updatedRat) { boolean updatedPlmnOrRat = updatedPlmn || updatedRat; if (updatedPlmnOrRat) { resetBandwidthFilter(); updateTxRxBandwidthFilterSendToDataConnection(); } return updatedPlmnOrRat; } private int getTac(@NonNull CellIdentity cellIdentity) { Loading @@ -900,11 +957,16 @@ public class LinkBandwidthEstimator extends Handler { } private class TelephonyCallbackImpl extends TelephonyCallback implements TelephonyCallback.SignalStrengthsListener { TelephonyCallback.SignalStrengthsListener, TelephonyCallback.ActiveDataSubscriptionIdListener { @Override public void onSignalStrengthsChanged(SignalStrength signalStrength) { obtainMessage(MSG_SIGNAL_STRENGTH_CHANGED, signalStrength).sendToTarget(); } @Override public void onActiveDataSubscriptionIdChanged(int subId) { obtainMessage(MSG_ACTIVE_PHONE_CHANGED, subId).sendToTarget(); } } void logv(String msg) { Loading
src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java +12 −17 Original line number Diff line number Diff line Loading @@ -2934,12 +2934,10 @@ public class TelephonyMetrics { * Write bandwidth estimator stats */ public synchronized void writeBandwidthStats(int link, int rat, int nrMode, int signalLevel, int bwEstIntErrPercent, int bwEstExtErrPercent, int coldStartErrPercent, int avgUsedKbps) { int signalLevel, 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.mBwEstErrorAcc[signalLevel] += Math.abs(bwEstExtErrPercent); stats.mStaticBwErrorAcc[signalLevel] += Math.abs(coldStartErrPercent); stats.mAvgBwKbps[signalLevel] = avgUsedKbps; stats.mCount[signalLevel]++; } Loading Loading @@ -2976,9 +2974,8 @@ public class TelephonyMetrics { 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 long[] mBwEstErrorAcc = new long[NUM_SIGNAL_LEVEL]; final long[] mStaticBwErrorAcc = new long[NUM_SIGNAL_LEVEL]; final int[] mAvgBwKbps = new int[NUM_SIGNAL_LEVEL]; final int[] mCount = new int[NUM_SIGNAL_LEVEL]; Loading @@ -2993,9 +2990,8 @@ public class TelephonyMetrics { 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)) .append("\n BwEst Error\n").append(printAvgError(mBwEstErrorAcc, mCount)) .append("\n StaticBw Error\n").append(printAvgError(mStaticBwErrorAcc, mCount)) .toString(); } Loading @@ -3010,8 +3006,7 @@ public class TelephonyMetrics { 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; int avgStat = calculateAvgError(stats[k], count[k]); sb.append(" " + avgStat); } return sb.toString(); Loading Loading @@ -3039,15 +3034,15 @@ public class TelephonyMetrics { stats.signalLevel = level; stats.count = count; stats.avgBwKbps = mAvgBwKbps[level]; stats.staticBwNrmsePercent = calculateNrmse(mStaticBwNse[level], count); stats.bwEstNrmsePercent = calculateNrmse(mBwEstExtNse[level], count); stats.staticBwErrorPercent = calculateAvgError(mStaticBwErrorAcc[level], count); stats.bwEstErrorPercent = calculateAvgError(mBwEstErrorAcc[level], count); return stats; } return null; } private int calculateNrmse(long nse, int count) { return (count > 0 && nse >= 0) ? (int) Math.sqrt(nse / count) : 0; private int calculateAvgError(long errorAccPercent, int count) { return (count > 0) ? (int) (errorAccPercent / count) : 0; } } Loading
tests/telephonytests/src/com/android/internal/telephony/dataconnection/LinkBandwidthEstimatorTest.java +98 −23 File changed.Preview size limit exceeded, changes collapsed. Show changes