1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony.data; 18 19 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; 20 21 import android.annotation.CallbackExecutor; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.content.Context; 25 import android.content.SharedPreferences; 26 import android.hardware.display.DisplayManager; 27 import android.net.ConnectivityManager; 28 import android.net.Network; 29 import android.net.NetworkCapabilities; 30 import android.os.AsyncResult; 31 import android.os.Handler; 32 import android.os.HandlerExecutor; 33 import android.os.Message; 34 import android.os.OutcomeReceiver; 35 import android.os.Registrant; 36 import android.os.RegistrantList; 37 import android.preference.PreferenceManager; 38 import android.telephony.AccessNetworkConstants; 39 import android.telephony.Annotation.DataActivityType; 40 import android.telephony.CellIdentity; 41 import android.telephony.CellIdentityGsm; 42 import android.telephony.CellIdentityLte; 43 import android.telephony.CellIdentityNr; 44 import android.telephony.CellIdentityTdscdma; 45 import android.telephony.CellIdentityWcdma; 46 import android.telephony.ModemActivityInfo; 47 import android.telephony.NetworkRegistrationInfo; 48 import android.telephony.ServiceState; 49 import android.telephony.SignalStrength; 50 import android.telephony.TelephonyCallback; 51 import android.telephony.TelephonyManager; 52 import android.util.ArrayMap; 53 import android.util.ArraySet; 54 import android.util.LocalLog; 55 import android.util.Pair; 56 import android.view.Display; 57 58 import com.android.internal.annotations.VisibleForTesting; 59 import com.android.internal.telephony.DctConstants; 60 import com.android.internal.telephony.Phone; 61 import com.android.internal.telephony.TelephonyFacade; 62 import com.android.internal.telephony.metrics.TelephonyMetrics; 63 import com.android.internal.telephony.nano.TelephonyProto.NrMode; 64 import com.android.internal.util.IndentingPrintWriter; 65 import com.android.telephony.Rlog; 66 67 import java.io.FileDescriptor; 68 import java.io.PrintWriter; 69 import java.util.Map; 70 import java.util.Objects; 71 import java.util.Set; 72 import java.util.concurrent.Executor; 73 74 /** 75 * Link Bandwidth Estimator based on the byte counts in TrafficStats and the time reported in modem 76 * activity. 77 */ 78 public class LinkBandwidthEstimator extends Handler { 79 private static final String TAG = LinkBandwidthEstimator.class.getSimpleName(); 80 private static final boolean DBG = false; 81 @VisibleForTesting 82 static final int MSG_SCREEN_STATE_CHANGED = 1; 83 @VisibleForTesting 84 static final int MSG_TRAFFIC_STATS_POLL = 2; 85 @VisibleForTesting 86 static final int MSG_MODEM_ACTIVITY_RETURNED = 3; 87 @VisibleForTesting 88 static final int MSG_DEFAULT_NETWORK_CHANGED = 4; 89 @VisibleForTesting 90 static final int MSG_SIGNAL_STRENGTH_CHANGED = 5; 91 @VisibleForTesting 92 static final int MSG_NR_FREQUENCY_CHANGED = 6; 93 @VisibleForTesting 94 static final int MSG_NR_STATE_CHANGED = 7; 95 @VisibleForTesting 96 static final int MSG_ACTIVE_PHONE_CHANGED = 8; 97 @VisibleForTesting 98 static final int MSG_DATA_REG_STATE_OR_RAT_CHANGED = 9; 99 100 // TODO: move the following parameters to xml file 101 private static final int TRAFFIC_STATS_POLL_INTERVAL_MS = 1_000; 102 private static final int MODEM_POLL_MIN_INTERVAL_MS = 5_000; 103 private static final int TRAFFIC_MODEM_POLL_BYTE_RATIO = 8; 104 private static final int TRAFFIC_POLL_BYTE_THRESHOLD_MAX = 20_000; 105 private static final int BYTE_DELTA_ACC_THRESHOLD_MAX_KB = 8_000; 106 private static final int MODEM_POLL_TIME_DELTA_MAX_MS = 10_000; 107 private static final int FILTER_UPDATE_MAX_INTERVAL_MS = 5_100; 108 // BW samples with Tx or Rx time below the following value is ignored. 109 private static final int TX_RX_TIME_MIN_MS = 200; 110 // The large time constant used in BW filter 111 private static final int TIME_CONSTANT_LARGE_SEC = 6; 112 // The small time constant used in BW filter 113 private static final int TIME_CONSTANT_SMALL_SEC = 6; 114 // If RSSI changes by more than the below value, update BW filter with small time constant 115 private static final int RSSI_DELTA_THRESHOLD_DB = 6; 116 // The up-scaling factor of filter coefficient. 117 private static final int FILTER_SCALE = 128; 118 // Force weight to 0 if the elapsed time is above LARGE_TIME_DECAY_RATIO * time constant 119 private static final int LARGE_TIME_DECAY_RATIO = 4; 120 // Modem Tx time may contain Rx time as defined in HAL. To work around the issue, if Tx time 121 // over Rx time ratio is above the following value, use Tx time + Rx time as Rx time. 122 private static final int TX_OVER_RX_TIME_RATIO_THRESHOLD_NUM = 3; 123 private static final int TX_OVER_RX_TIME_RATIO_THRESHOLD_DEN = 2; 124 // Default Link bandwidth value if the RAT entry is not found in static BW table. 125 private static final int DEFAULT_LINK_BAND_WIDTH_KBPS = 14; 126 // If Tx or Rx link bandwidth change is above the following value, send the BW update 127 private static final int BW_UPDATE_THRESHOLD_PERCENT = 15; 128 129 // To be used in link bandwidth estimation, each TrafficStats poll sample needs to be above 130 // a predefine threshold. 131 // For RAT with static BW above HIGH_BANDWIDTH_THRESHOLD_KBPS, it uses the following table. 132 // For others RATs, the thresholds are derived from the static BW values. 133 // The following table is defined per signal level, int [NUM_SIGNAL_LEVEL]. 134 private static final int HIGH_BANDWIDTH_THRESHOLD_KBPS = 5000; 135 //Array dimension : int [NUM_LINK_DIRECTION][NUM_SIGNAL_LEVEL] 136 private static final int[][] BYTE_DELTA_THRESHOLD_KB = 137 {{200, 300, 400, 600, 1000}, {400, 600, 800, 1000, 1000}}; 138 // Used to derive byte count threshold from avg BW 139 private static final int LOW_BW_TO_AVG_BW_RATIO_NUM = 3; 140 private static final int LOW_BW_TO_AVG_BW_RATIO_DEN = 8; 141 private static final int MAX_BW_TO_STATIC_BW_RATIO = 15; 142 private static final int BYTE_DELTA_THRESHOLD_MIN_KB = 10; 143 private static final int MAX_ERROR_PERCENT = 100 * 100; 144 private static final String[] AVG_BW_PER_RAT = { 145 "GPRS:24,24", "EDGE:70,18", "UMTS:115,115", "CDMA:14,14", 146 "CDMA - 1xRTT:30,30", "CDMA - EvDo rev. 0:750,48", "CDMA - EvDo rev. A:950,550", 147 "HSDPA:4300,620", "HSUPA:4300,1800", "HSPA:4300,1800", "CDMA - EvDo rev. B:1500,550", 148 "CDMA - eHRPD:750,48", "HSPA+:13000,3400", "TD_SCDMA:115,115", 149 "LTE:30000,15000", "NR_NSA:47000,18000", 150 "NR_NSA_MMWAVE:145000,60000", "NR:145000,60000", "NR_MMWAVE:145000,60000"}; 151 private static final Map<String, Pair<Integer, Integer>> AVG_BW_PER_RAT_MAP = new ArrayMap<>(); 152 private static final String UNKNOWN_PLMN = ""; 153 154 // To be used in the long term avg, each count needs to be above the following value 155 public static final int BW_STATS_COUNT_THRESHOLD = 5; 156 public static final int NUM_SIGNAL_LEVEL = 5; 157 public static final int LINK_TX = 0; 158 public static final int LINK_RX = 1; 159 public static final int NUM_LINK_DIRECTION = 2; 160 161 // One common timestamp for all sim to avoid frequent modem polling 162 private final Phone mPhone; 163 private final TelephonyFacade mTelephonyFacade; 164 private final TelephonyManager mTelephonyManager; 165 private final ConnectivityManager mConnectivityManager; 166 private final LocalLog mLocalLog = new LocalLog(512); 167 private boolean mScreenOn = false; 168 private boolean mIsOnDefaultRoute = false; 169 private boolean mIsOnActiveData = false; 170 private long mLastModemPollTimeMs; 171 private boolean mLastTrafficValid = true; 172 private long mLastMobileTxBytes; 173 private long mLastMobileRxBytes; 174 private long mTxBytesDeltaAcc; 175 private long mRxBytesDeltaAcc; 176 177 private ModemActivityInfo mLastModemActivityInfo = null; 178 private final TelephonyCallback mTelephonyCallback = new TelephonyCallbackImpl(); 179 private int mSignalStrengthDbm; 180 private int mSignalLevel; 181 private int mDataRat = TelephonyManager.NETWORK_TYPE_UNKNOWN; 182 private int mTac; 183 private String mPlmn = UNKNOWN_PLMN; 184 private NetworkCapabilities mNetworkCapabilities; 185 private NetworkBandwidth mPlaceholderNetwork; 186 private long mFilterUpdateTimeMs; 187 188 private int mBandwidthUpdateSignalDbm = -1; 189 private int mBandwidthUpdateSignalLevel = -1; 190 private int mBandwidthUpdateDataRat = TelephonyManager.NETWORK_TYPE_UNKNOWN; 191 private String mBandwidthUpdatePlmn = UNKNOWN_PLMN; 192 private BandwidthState mTxState = new BandwidthState(LINK_TX); 193 private BandwidthState mRxState = new BandwidthState(LINK_RX); 194 private RegistrantList mBandwidthChangedRegistrants = new RegistrantList(); 195 private long mLastPlmnOrRatChangeTimeMs; 196 private long mLastDrsOrRatChangeTimeMs; 197 198 private int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE; 199 200 /** Link bandwidth estimator callbacks. */ 201 private final @NonNull Set<LinkBandwidthEstimatorCallback> mLinkBandwidthEstimatorCallbacks = 202 new ArraySet<>(); 203 204 /** 205 * The link bandwidth estimator callback. Note this is only used for passing information 206 * internally in the data stack, should not be used externally. 207 */ 208 public static class LinkBandwidthEstimatorCallback extends DataCallback { 209 /** 210 * Constructor 211 * 212 * @param executor The executor of the callback. 213 */ LinkBandwidthEstimatorCallback(@onNull @allbackExecutor Executor executor)214 public LinkBandwidthEstimatorCallback(@NonNull @CallbackExecutor Executor executor) { 215 super(executor); 216 } 217 218 /** 219 * Called when data activity changed. 220 * 221 * @param dataActivity The data activity. 222 */ onDataActivityChanged(@ataActivityType int dataActivity)223 public void onDataActivityChanged(@DataActivityType int dataActivity) {} 224 225 /** 226 * Called when bandwidth changed. 227 * 228 * @param uplinkBandwidthKbps Uplink bandwidth estimate in Kbps. 229 * @param downlinkBandwidthKbps Downlink bandwidth estimate in Kbps. 230 */ onBandwidthChanged(int uplinkBandwidthKbps, int downlinkBandwidthKbps)231 public void onBandwidthChanged(int uplinkBandwidthKbps, int downlinkBandwidthKbps) {} 232 } 233 initAvgBwPerRatTable()234 private static void initAvgBwPerRatTable() { 235 for (String config : AVG_BW_PER_RAT) { 236 int rxKbps = 14; 237 int txKbps = 14; 238 String[] kv = config.split(":"); 239 if (kv.length == 2) { 240 String[] split = kv[1].split(","); 241 if (split.length == 2) { 242 try { 243 rxKbps = Integer.parseInt(split[0]); 244 txKbps = Integer.parseInt(split[1]); 245 } catch (NumberFormatException ignored) { 246 } 247 } 248 AVG_BW_PER_RAT_MAP.put(kv[0], new Pair<>(rxKbps, txKbps)); 249 } 250 } 251 } 252 253 private final DisplayManager.DisplayListener mDisplayListener = 254 new DisplayManager.DisplayListener() { 255 @Override 256 public void onDisplayAdded(int displayId) { 257 } 258 259 @Override 260 public void onDisplayRemoved(int displayId) { 261 } 262 263 @Override 264 public void onDisplayChanged(int displayId) { 265 obtainMessage(MSG_SCREEN_STATE_CHANGED, isScreenOn()).sendToTarget(); 266 } 267 }; 268 269 private final OutcomeReceiver<ModemActivityInfo, TelephonyManager.ModemActivityInfoException> 270 mOutcomeReceiver = 271 new OutcomeReceiver<ModemActivityInfo, TelephonyManager.ModemActivityInfoException>() { 272 @Override 273 public void onResult(ModemActivityInfo result) { 274 obtainMessage(MSG_MODEM_ACTIVITY_RETURNED, result).sendToTarget(); 275 } 276 277 @Override 278 public void onError(TelephonyManager.ModemActivityInfoException e) { 279 Rlog.e(TAG, "error reading modem stats:" + e); 280 obtainMessage(MSG_MODEM_ACTIVITY_RETURNED, null).sendToTarget(); 281 } 282 }; 283 284 private final ConnectivityManager.NetworkCallback mDefaultNetworkCallback = 285 new ConnectivityManager.NetworkCallback() { 286 @Override 287 public void onCapabilitiesChanged(@NonNull Network network, 288 @NonNull NetworkCapabilities networkCapabilities) { 289 obtainMessage(MSG_DEFAULT_NETWORK_CHANGED, networkCapabilities).sendToTarget(); 290 } 291 292 public void onLost(@NonNull Network network) { 293 obtainMessage(MSG_DEFAULT_NETWORK_CHANGED, null).sendToTarget(); 294 } 295 }; 296 LinkBandwidthEstimator(Phone phone, TelephonyFacade telephonyFacade)297 public LinkBandwidthEstimator(Phone phone, TelephonyFacade telephonyFacade) { 298 mPhone = phone; 299 mTelephonyFacade = telephonyFacade; 300 mTelephonyManager = phone.getContext() 301 .getSystemService(TelephonyManager.class) 302 .createForSubscriptionId(phone.getSubId()); 303 mConnectivityManager = phone.getContext().getSystemService(ConnectivityManager.class); 304 DisplayManager dm = (DisplayManager) phone.getContext().getSystemService( 305 Context.DISPLAY_SERVICE); 306 dm.registerDisplayListener(mDisplayListener, null); 307 handleScreenStateChanged(isScreenOn()); 308 mConnectivityManager.registerDefaultNetworkCallback(mDefaultNetworkCallback, this); 309 mTelephonyManager.registerTelephonyCallback(new HandlerExecutor(this), 310 mTelephonyCallback); 311 mPlaceholderNetwork = new NetworkBandwidth(UNKNOWN_PLMN); 312 initAvgBwPerRatTable(); 313 registerNrStateFrequencyChange(); 314 mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(AccessNetworkConstants 315 .TRANSPORT_TYPE_WWAN, this, MSG_DATA_REG_STATE_OR_RAT_CHANGED, null); 316 } 317 318 @Override handleMessage(Message msg)319 public void handleMessage(Message msg) { 320 switch (msg.what) { 321 case MSG_SCREEN_STATE_CHANGED: 322 handleScreenStateChanged((boolean) msg.obj); 323 break; 324 case MSG_TRAFFIC_STATS_POLL: 325 handleTrafficStatsPoll(); 326 break; 327 case MSG_MODEM_ACTIVITY_RETURNED: 328 handleModemActivityReturned((ModemActivityInfo) msg.obj); 329 break; 330 case MSG_DEFAULT_NETWORK_CHANGED: 331 handleDefaultNetworkChanged((NetworkCapabilities) msg.obj); 332 break; 333 case MSG_SIGNAL_STRENGTH_CHANGED: 334 handleSignalStrengthChanged((SignalStrength) msg.obj); 335 break; 336 case MSG_NR_FREQUENCY_CHANGED: 337 // fall through 338 case MSG_NR_STATE_CHANGED: 339 updateStaticBwValueResetFilter(); 340 break; 341 case MSG_ACTIVE_PHONE_CHANGED: 342 handleActivePhoneChanged((int) msg.obj); 343 break; 344 case MSG_DATA_REG_STATE_OR_RAT_CHANGED: 345 handleDrsOrRatChanged((AsyncResult) msg.obj); 346 break; 347 default: 348 Rlog.e(TAG, "invalid message " + msg.what); 349 break; 350 } 351 } 352 353 /** 354 * Registers for bandwidth estimation change. The bandwidth will be returned 355 * * {@link AsyncResult#result} as a {@link Pair} Object. 356 * * The {@link AsyncResult} will be in the notification {@link Message#obj}. 357 * @param h handler to notify 358 * @param what what code of message when delivered 359 * @param obj placed in Message.obj 360 * 361 * @deprecated Use {@link #registerCallback(LinkBandwidthEstimatorCallback)}. 362 */ 363 @Deprecated //TODO: Remove once old data stack is removed. registerForBandwidthChanged(Handler h, int what, Object obj)364 public void registerForBandwidthChanged(Handler h, int what, Object obj) { 365 Registrant r = new Registrant(h, what, obj); 366 mBandwidthChangedRegistrants.add(r); 367 } 368 369 /** 370 * Unregisters for bandwidth estimation change. 371 * @param h handler to notify 372 * 373 * @deprecated Use {@link #unregisterCallback(LinkBandwidthEstimatorCallback)}. 374 */ 375 @Deprecated //TODO: Remove once old data stack is removed. unregisterForBandwidthChanged(Handler h)376 public void unregisterForBandwidthChanged(Handler h) { 377 mBandwidthChangedRegistrants.remove(h); 378 } 379 380 /** 381 * Register the callback for receiving information from {@link LinkBandwidthEstimator}. 382 * 383 * @param callback The callback. 384 */ registerCallback(@onNull LinkBandwidthEstimatorCallback callback)385 public void registerCallback(@NonNull LinkBandwidthEstimatorCallback callback) { 386 mLinkBandwidthEstimatorCallbacks.add(callback); 387 } 388 389 /** 390 * Unregister the callback. 391 * 392 * @param callback The previously registered callback. 393 */ unregisterCallback(@onNull LinkBandwidthEstimatorCallback callback)394 public void unregisterCallback(@NonNull LinkBandwidthEstimatorCallback callback) { 395 mLinkBandwidthEstimatorCallbacks.remove(callback); 396 } 397 398 /** 399 * @return True if one the device's screen (e.g. main screen, wifi display, HDMI display etc...) 400 * is on. 401 */ isScreenOn()402 private boolean isScreenOn() { 403 // Note that we don't listen to Intent.SCREEN_ON and Intent.SCREEN_OFF because they are no 404 // longer adequate for monitoring the screen state since they are not sent in cases where 405 // the screen is turned off transiently such as due to the proximity sensor. 406 final DisplayManager dm = (DisplayManager) mPhone.getContext().getSystemService( 407 Context.DISPLAY_SERVICE); 408 Display[] displays = dm.getDisplays(); 409 410 if (displays != null) { 411 for (Display display : displays) { 412 // Anything other than STATE_ON is treated as screen off, such as STATE_DOZE, 413 // STATE_DOZE_SUSPEND, etc... 414 if (display.getState() == Display.STATE_ON) { 415 return true; 416 } 417 } 418 return false; 419 } 420 421 return false; 422 } 423 handleScreenStateChanged(boolean screenOn)424 private void handleScreenStateChanged(boolean screenOn) { 425 if (mScreenOn == screenOn) { 426 return; 427 } 428 mScreenOn = screenOn; 429 handleTrafficStatsPollConditionChanged(); 430 } 431 handleDefaultNetworkChanged(NetworkCapabilities networkCapabilities)432 private void handleDefaultNetworkChanged(NetworkCapabilities networkCapabilities) { 433 mNetworkCapabilities = networkCapabilities; 434 boolean isOnDefaultRoute; 435 if (networkCapabilities == null) { 436 isOnDefaultRoute = false; 437 } else { 438 isOnDefaultRoute = networkCapabilities.hasTransport(TRANSPORT_CELLULAR); 439 } 440 if (mIsOnDefaultRoute == isOnDefaultRoute) { 441 return; 442 } 443 mIsOnDefaultRoute = isOnDefaultRoute; 444 handleTrafficStatsPollConditionChanged(); 445 } 446 handleActivePhoneChanged(int activeDataSubId)447 private void handleActivePhoneChanged(int activeDataSubId) { 448 boolean isOnActiveData = activeDataSubId == mPhone.getSubId(); 449 if (mIsOnActiveData == isOnActiveData) { 450 return; 451 } 452 mIsOnActiveData = isOnActiveData; 453 logd("mIsOnActiveData " + mIsOnActiveData + " activeDataSubId " + activeDataSubId); 454 handleTrafficStatsPollConditionChanged(); 455 } 456 handleDrsOrRatChanged(AsyncResult ar)457 private void handleDrsOrRatChanged(AsyncResult ar) { 458 Pair<Integer, Integer> drsRatPair = (Pair<Integer, Integer>) ar.result; 459 logd("DrsOrRatChanged dataRegState " + drsRatPair.first + " rilRat " + drsRatPair.second); 460 mLastDrsOrRatChangeTimeMs = mTelephonyFacade.getElapsedSinceBootMillis(); 461 } 462 handleTrafficStatsPollConditionChanged()463 private void handleTrafficStatsPollConditionChanged() { 464 removeMessages(MSG_TRAFFIC_STATS_POLL); 465 if (mScreenOn && mIsOnDefaultRoute && mIsOnActiveData) { 466 updateDataRatCellIdentityBandwidth(); 467 handleTrafficStatsPoll(); 468 } 469 } 470 handleTrafficStatsPoll()471 private void handleTrafficStatsPoll() { 472 invalidateTxRxSamples(); 473 long mobileTxBytes = mTelephonyFacade.getMobileTxBytes(); 474 long mobileRxBytes = mTelephonyFacade.getMobileRxBytes(); 475 long txBytesDelta = mobileTxBytes - mLastMobileTxBytes; 476 long rxBytesDelta = mobileRxBytes - mLastMobileRxBytes; 477 478 // Schedule the next traffic stats poll 479 sendEmptyMessageDelayed(MSG_TRAFFIC_STATS_POLL, TRAFFIC_STATS_POLL_INTERVAL_MS); 480 481 mLastMobileTxBytes = mobileTxBytes; 482 mLastMobileRxBytes = mobileRxBytes; 483 // Sometimes TrafficStats byte counts return invalid values 484 // Ignore two polls if it happens 485 boolean trafficValid = txBytesDelta >= 0 && rxBytesDelta >= 0; 486 if (!mLastTrafficValid || !trafficValid) { 487 mLastTrafficValid = trafficValid; 488 Rlog.e(TAG, " run into invalid traffic count"); 489 return; 490 } 491 492 mTxBytesDeltaAcc += txBytesDelta; 493 mRxBytesDeltaAcc += rxBytesDelta; 494 495 boolean doModemPoll = true; 496 // Check if it meets the requirement to request modem activity 497 long txByteDeltaThr = Math.min(mTxState.mByteDeltaAccThr / TRAFFIC_MODEM_POLL_BYTE_RATIO, 498 TRAFFIC_POLL_BYTE_THRESHOLD_MAX); 499 long rxByteDeltaThr = Math.min(mRxState.mByteDeltaAccThr / TRAFFIC_MODEM_POLL_BYTE_RATIO, 500 TRAFFIC_POLL_BYTE_THRESHOLD_MAX); 501 if (txBytesDelta < txByteDeltaThr && rxBytesDelta < rxByteDeltaThr 502 && mTxBytesDeltaAcc < mTxState.mByteDeltaAccThr 503 && mRxBytesDeltaAcc < mRxState.mByteDeltaAccThr) { 504 doModemPoll = false; 505 } 506 507 long currTimeMs = mTelephonyFacade.getElapsedSinceBootMillis(); 508 long timeSinceLastModemPollMs = currTimeMs - mLastModemPollTimeMs; 509 if (timeSinceLastModemPollMs < MODEM_POLL_MIN_INTERVAL_MS) { 510 doModemPoll = false; 511 } 512 513 if (doModemPoll) { 514 StringBuilder sb = new StringBuilder(); 515 logd(sb.append("txByteDelta ").append(txBytesDelta) 516 .append(" rxByteDelta ").append(rxBytesDelta) 517 .append(" txByteDeltaAcc ").append(mTxBytesDeltaAcc) 518 .append(" rxByteDeltaAcc ").append(mRxBytesDeltaAcc) 519 .append(" trigger modem activity request").toString()); 520 updateDataRatCellIdentityBandwidth(); 521 // Filter update will happen after the request 522 makeRequestModemActivity(); 523 return; 524 } 525 526 int dataActivity; 527 if (txBytesDelta > 0 && rxBytesDelta > 0) { 528 dataActivity = TelephonyManager.DATA_ACTIVITY_INOUT; 529 } else if (rxBytesDelta > 0) { 530 dataActivity = TelephonyManager.DATA_ACTIVITY_IN; 531 } else if (txBytesDelta > 0) { 532 dataActivity = TelephonyManager.DATA_ACTIVITY_OUT; 533 } else { 534 dataActivity = TelephonyManager.DATA_ACTIVITY_NONE; 535 } 536 537 if (mDataActivity != dataActivity) { 538 mDataActivity = dataActivity; 539 mLinkBandwidthEstimatorCallbacks.forEach(callback -> callback.invokeFromExecutor( 540 () -> callback.onDataActivityChanged(dataActivity))); 541 } 542 543 long timeSinceLastFilterUpdateMs = currTimeMs - mFilterUpdateTimeMs; 544 // Update filter 545 if (timeSinceLastFilterUpdateMs >= FILTER_UPDATE_MAX_INTERVAL_MS) { 546 if (!updateDataRatCellIdentityBandwidth()) { 547 updateTxRxBandwidthFilterSendToDataConnection(); 548 } 549 } 550 } 551 makeRequestModemActivity()552 private void makeRequestModemActivity() { 553 mLastModemPollTimeMs = mTelephonyFacade.getElapsedSinceBootMillis(); 554 // TODO: add CountDown in case that onResult/OnError() never happen 555 mTelephonyManager.requestModemActivityInfo(Runnable::run, mOutcomeReceiver); 556 } 557 handleModemActivityReturned(ModemActivityInfo result)558 private void handleModemActivityReturned(ModemActivityInfo result) { 559 updateBandwidthTxRxSamples(result); 560 updateTxRxBandwidthFilterSendToDataConnection(); 561 mLastModemActivityInfo = result; 562 // Update for next poll 563 resetByteDeltaAcc(); 564 } 565 resetByteDeltaAcc()566 private void resetByteDeltaAcc() { 567 mTxBytesDeltaAcc = 0; 568 mRxBytesDeltaAcc = 0; 569 } 570 invalidateTxRxSamples()571 private void invalidateTxRxSamples() { 572 mTxState.mBwSampleValid = false; 573 mRxState.mBwSampleValid = false; 574 } 575 updateBandwidthTxRxSamples(ModemActivityInfo modemActivityInfo)576 private void updateBandwidthTxRxSamples(ModemActivityInfo modemActivityInfo) { 577 if (mLastModemActivityInfo == null || modemActivityInfo == null 578 || mNetworkCapabilities == null || hasRecentDataRegStatePlmnOrRatChange()) { 579 return; 580 } 581 582 long lastTimeMs = mLastModemActivityInfo.getTimestampMillis(); 583 long currTimeMs = modemActivityInfo.getTimestampMillis(); 584 long timeDeltaMs = currTimeMs - lastTimeMs; 585 586 if (timeDeltaMs > MODEM_POLL_TIME_DELTA_MAX_MS || timeDeltaMs <= 0) { 587 return; 588 } 589 ModemActivityInfo deltaInfo = mLastModemActivityInfo.getDelta(modemActivityInfo); 590 long txTimeDeltaMs = getModemTxTimeMs(deltaInfo); 591 long rxTimeDeltaMs = deltaInfo.getReceiveTimeMillis(); 592 593 // Check if txTimeDeltaMs / rxTimeDeltaMs > TX_OVER_RX_TIME_RATIO_THRESHOLD 594 boolean isTxTimeOverRxTimeRatioLarge = (txTimeDeltaMs * TX_OVER_RX_TIME_RATIO_THRESHOLD_DEN 595 > rxTimeDeltaMs * TX_OVER_RX_TIME_RATIO_THRESHOLD_NUM); 596 long rxTimeBwEstMs = isTxTimeOverRxTimeRatioLarge 597 ? (txTimeDeltaMs + rxTimeDeltaMs) : rxTimeDeltaMs; 598 599 mTxState.updateBandwidthSample(mTxBytesDeltaAcc, txTimeDeltaMs); 600 mRxState.updateBandwidthSample(mRxBytesDeltaAcc, rxTimeBwEstMs); 601 602 int reportedTxTputKbps = mNetworkCapabilities.getLinkUpstreamBandwidthKbps(); 603 int reportedRxTputKbps = mNetworkCapabilities.getLinkDownstreamBandwidthKbps(); 604 605 StringBuilder sb = new StringBuilder(); 606 logd(sb.append("UpdateBwSample") 607 .append(" dBm ").append(mSignalStrengthDbm) 608 .append(" level ").append(mSignalLevel) 609 .append(" rat ").append(getDataRatName(mDataRat)) 610 .append(" plmn ").append(mPlmn) 611 .append(" tac ").append(mTac) 612 .append(" reportedTxKbps ").append(reportedTxTputKbps) 613 .append(" reportedRxKbps ").append(reportedRxTputKbps) 614 .append(" txMs ").append(txTimeDeltaMs) 615 .append(" rxMs ").append(rxTimeDeltaMs) 616 .append(" txKB ").append(mTxBytesDeltaAcc / 1024) 617 .append(" rxKB ").append(mRxBytesDeltaAcc / 1024) 618 .append(" txKBThr ").append(mTxState.mByteDeltaAccThr / 1024) 619 .append(" rxKBThr ").append(mRxState.mByteDeltaAccThr / 1024) 620 .toString()); 621 } 622 hasRecentDataRegStatePlmnOrRatChange()623 private boolean hasRecentDataRegStatePlmnOrRatChange() { 624 if (mLastModemActivityInfo == null) { 625 return false; 626 } 627 return (mLastDrsOrRatChangeTimeMs > mLastModemActivityInfo.getTimestampMillis() 628 || mLastPlmnOrRatChangeTimeMs > mLastModemActivityInfo.getTimestampMillis()); 629 } 630 getModemTxTimeMs(ModemActivityInfo modemActivity)631 private long getModemTxTimeMs(ModemActivityInfo modemActivity) { 632 long txTimeMs = 0; 633 for (int lvl = 0; lvl < ModemActivityInfo.getNumTxPowerLevels(); lvl++) { 634 txTimeMs += modemActivity.getTransmitDurationMillisAtPowerLevel(lvl); 635 } 636 return txTimeMs; 637 } 638 updateTxRxBandwidthFilterSendToDataConnection()639 private void updateTxRxBandwidthFilterSendToDataConnection() { 640 mFilterUpdateTimeMs = mTelephonyFacade.getElapsedSinceBootMillis(); 641 mTxState.updateBandwidthFilter(); 642 mRxState.updateBandwidthFilter(); 643 644 boolean isNetworkChanged = mTxState.hasLargeBwChange() 645 || mRxState.hasLargeBwChange() 646 || mBandwidthUpdateDataRat != mDataRat 647 || mBandwidthUpdateSignalLevel != mSignalLevel 648 || !mBandwidthUpdatePlmn.equals(mPlmn); 649 if (isValidNetwork() && isNetworkChanged) { 650 mTxState.mLastReportedBwKbps = mTxState.mAvgUsedKbps < 0 ? -1 : mTxState.mFilterKbps; 651 mRxState.mLastReportedBwKbps = mRxState.mAvgUsedKbps < 0 ? -1 : mRxState.mFilterKbps; 652 sendLinkBandwidthToDataConnection( 653 mTxState.mLastReportedBwKbps, 654 mRxState.mLastReportedBwKbps); 655 } 656 mBandwidthUpdateSignalDbm = mSignalStrengthDbm; 657 mBandwidthUpdateSignalLevel = mSignalLevel; 658 mBandwidthUpdateDataRat = mDataRat; 659 mBandwidthUpdatePlmn = mPlmn; 660 661 mTxState.calculateError(); 662 mRxState.calculateError(); 663 } 664 665 private boolean isValidNetwork() { 666 return !mPlmn.equals(UNKNOWN_PLMN) && mDataRat != TelephonyManager.NETWORK_TYPE_UNKNOWN; 667 } 668 669 private class BandwidthState { 670 private final int mLink; 671 int mFilterKbps; 672 int mByteDeltaAccThr = BYTE_DELTA_THRESHOLD_KB[0][0]; 673 int mAvgUsedKbps; 674 int mBwSampleKbps; 675 boolean mBwSampleValid; 676 long mBwSampleValidTimeMs; 677 int mStaticBwKbps; 678 int mLastReportedBwKbps; 679 680 BandwidthState(int link) { 681 mLink = link; 682 } 683 684 private void updateBandwidthSample(long bytesDelta, long timeDeltaMs) { 685 updateByteCountThr(); 686 if (bytesDelta < mByteDeltaAccThr) { 687 return; 688 } 689 if (timeDeltaMs < TX_RX_TIME_MIN_MS) { 690 return; 691 } 692 long linkBandwidthLongKbps = bytesDelta * 8 / timeDeltaMs * 1000 / 1024; 693 if (linkBandwidthLongKbps > (long) mStaticBwKbps * MAX_BW_TO_STATIC_BW_RATIO 694 || linkBandwidthLongKbps < 0) { 695 return; 696 } 697 int linkBandwidthKbps = (int) linkBandwidthLongKbps; 698 mBwSampleValid = true; 699 mBwSampleKbps = linkBandwidthKbps; 700 701 String dataRatName = getDataRatName(mDataRat); 702 NetworkBandwidth network = lookupNetwork(mPlmn, dataRatName); 703 // Update per RAT stats of all TAC 704 network.update(linkBandwidthKbps, mLink, mSignalLevel); 705 706 // Update per TAC stats 707 network = lookupNetwork(mPlmn, mTac, dataRatName); 708 network.update(linkBandwidthKbps, mLink, mSignalLevel); 709 } 710 711 private void updateBandwidthFilter() { 712 int avgKbps = getAvgLinkBandwidthKbps(); 713 // Feed the filter with the long term avg if there is no valid BW sample so that filter 714 // will gradually converge the long term avg. 715 int filterInKbps = mBwSampleValid ? mBwSampleKbps : avgKbps; 716 717 long currTimeMs = mTelephonyFacade.getElapsedSinceBootMillis(); 718 int timeDeltaSec = (int) ((currTimeMs - mBwSampleValidTimeMs) / 1000); 719 720 // If the operation condition changes significantly since the last update 721 // or the sample has higher BW, use a faster filter. Otherwise, use a slow filter 722 int timeConstantSec; 723 if (Math.abs(mBandwidthUpdateSignalDbm - mSignalStrengthDbm) > RSSI_DELTA_THRESHOLD_DB 724 || !mBandwidthUpdatePlmn.equals(mPlmn) 725 || mBandwidthUpdateDataRat != mDataRat 726 || (mBwSampleValid && mBwSampleKbps > avgKbps)) { 727 timeConstantSec = TIME_CONSTANT_SMALL_SEC; 728 } else { 729 timeConstantSec = TIME_CONSTANT_LARGE_SEC; 730 } 731 // Update timestamp for next iteration 732 if (mBwSampleValid) { 733 mBwSampleValidTimeMs = currTimeMs; 734 } 735 736 if (filterInKbps == mFilterKbps) { 737 return; 738 } 739 740 int alpha = timeDeltaSec > LARGE_TIME_DECAY_RATIO * timeConstantSec ? 0 741 : (int) (FILTER_SCALE * Math.exp(-1.0 * timeDeltaSec / timeConstantSec)); 742 if (alpha == 0) { 743 mFilterKbps = filterInKbps; 744 return; 745 } 746 long filterOutKbps = (long) mFilterKbps * alpha 747 + filterInKbps * FILTER_SCALE - filterInKbps * alpha; 748 filterOutKbps = filterOutKbps / FILTER_SCALE; 749 mFilterKbps = (int) Math.min(filterOutKbps, Integer.MAX_VALUE); 750 751 StringBuilder sb = new StringBuilder(); 752 logv(sb.append(mLink) 753 .append(" lastSampleWeight=").append(alpha) 754 .append("/").append(FILTER_SCALE) 755 .append(" filterInKbps=").append(filterInKbps) 756 .append(" avgKbps=").append(avgKbps) 757 .append(" filterOutKbps=").append(mFilterKbps) 758 .toString()); 759 } 760 761 private int getAvgUsedLinkBandwidthKbps() { 762 // Check if current TAC/RAT/level has enough stats 763 String dataRatName = getDataRatName(mDataRat); 764 NetworkBandwidth network = lookupNetwork(mPlmn, mTac, dataRatName); 765 int count = network.getCount(mLink, mSignalLevel); 766 if (count >= BW_STATS_COUNT_THRESHOLD) { 767 return (int) (network.getValue(mLink, mSignalLevel) / count); 768 } 769 770 // Check if current RAT/level has enough stats 771 network = lookupNetwork(mPlmn, dataRatName); 772 count = network.getCount(mLink, mSignalLevel); 773 if (count >= BW_STATS_COUNT_THRESHOLD) { 774 return (int) (network.getValue(mLink, mSignalLevel) / count); 775 } 776 return -1; 777 } 778 getAvgUsedBandwidthAdjacentThreeLevelKbps()779 private int getAvgUsedBandwidthAdjacentThreeLevelKbps() { 780 String dataRatName = getDataRatName(mDataRat); 781 NetworkBandwidth network = lookupNetwork(mPlmn, dataRatName); 782 783 int bandwidthAtLow = getAvgUsedBandwidthAtLevel(network, mSignalLevel - 1); 784 int bandwidthAtHigh = getAvgUsedBandwidthAtLevel(network, mSignalLevel + 1); 785 if (bandwidthAtLow > 0 && bandwidthAtHigh > 0) { 786 return (bandwidthAtLow + bandwidthAtHigh) / 2; 787 } 788 789 int count = 0; 790 long value = 0; 791 for (int i = -1; i <= 1; i++) { 792 int currLevel = mSignalLevel + i; 793 if (currLevel < 0 || currLevel >= NUM_SIGNAL_LEVEL) { 794 continue; 795 } 796 count += network.getCount(mLink, currLevel); 797 value += network.getValue(mLink, currLevel); 798 } 799 800 if (count >= BW_STATS_COUNT_THRESHOLD) { 801 return (int) (value / count); 802 } 803 return -1; 804 } 805 getAvgUsedBandwidthAtLevel(NetworkBandwidth network, int signalLevel)806 private int getAvgUsedBandwidthAtLevel(NetworkBandwidth network, 807 int signalLevel) { 808 if (signalLevel < 0 || signalLevel >= NUM_SIGNAL_LEVEL) { 809 return -1; 810 } 811 int count = network.getCount(mLink, signalLevel); 812 if (count >= BW_STATS_COUNT_THRESHOLD) { 813 return (int) (network.getValue(mLink, signalLevel) / count); 814 } 815 return -1; 816 } 817 getCurrentCount()818 private int getCurrentCount() { 819 String dataRatName = getDataRatName(mDataRat); 820 NetworkBandwidth network = lookupNetwork(mPlmn, dataRatName); 821 return network.getCount(mLink, mSignalLevel); 822 } 823 824 /** get a long term avg value (PLMN/RAT/TAC/level dependent) or static value */ getAvgLinkBandwidthKbps()825 private int getAvgLinkBandwidthKbps() { 826 mAvgUsedKbps = getAvgUsedLinkBandwidthKbps(); 827 if (mAvgUsedKbps > 0) { 828 return mAvgUsedKbps; 829 } 830 mAvgUsedKbps = getAvgUsedBandwidthAdjacentThreeLevelKbps(); 831 if (mAvgUsedKbps > 0) { 832 return mAvgUsedKbps; 833 } 834 // Fall back to static value 835 return mStaticBwKbps; 836 } 837 resetBandwidthFilter()838 private void resetBandwidthFilter() { 839 mBwSampleValid = false; 840 mFilterKbps = getAvgLinkBandwidthKbps(); 841 } 842 updateByteCountThr()843 private void updateByteCountThr() { 844 // For high BW RAT cases, use predefined value + threshold derived from avg usage BW 845 if (mStaticBwKbps > HIGH_BANDWIDTH_THRESHOLD_KBPS) { 846 int lowBytes = calculateByteCountThreshold(getAvgUsedLinkBandwidthKbps(), 847 MODEM_POLL_MIN_INTERVAL_MS); 848 // Start with a predefined value 849 mByteDeltaAccThr = BYTE_DELTA_THRESHOLD_KB[mLink][mSignalLevel] * 1024; 850 if (lowBytes > 0) { 851 // Raise the threshold if the avg usage BW is high 852 mByteDeltaAccThr = Math.max(lowBytes, mByteDeltaAccThr); 853 mByteDeltaAccThr = Math.min(mByteDeltaAccThr, 854 BYTE_DELTA_ACC_THRESHOLD_MAX_KB * 1024); 855 } 856 return; 857 } 858 // For low BW RAT cases, derive the threshold from avg BW values 859 mByteDeltaAccThr = calculateByteCountThreshold(mStaticBwKbps, 860 MODEM_POLL_MIN_INTERVAL_MS); 861 862 mByteDeltaAccThr = Math.max(mByteDeltaAccThr, BYTE_DELTA_THRESHOLD_MIN_KB * 1024); 863 // Low BW RAT threshold value should be no more than high BW one. 864 mByteDeltaAccThr = Math.min(mByteDeltaAccThr, BYTE_DELTA_THRESHOLD_KB[mLink][0] * 1024); 865 } 866 867 // Calculate a byte count threshold for the given avg BW and observation window size calculateByteCountThreshold(int avgBwKbps, int durationMs)868 private int calculateByteCountThreshold(int avgBwKbps, int durationMs) { 869 long avgBytes = (long) avgBwKbps / 8 * durationMs; 870 long result = avgBytes * LOW_BW_TO_AVG_BW_RATIO_NUM / LOW_BW_TO_AVG_BW_RATIO_DEN; 871 return (int) Math.min(result, Integer.MAX_VALUE); 872 } 873 hasLargeBwChange()874 public boolean hasLargeBwChange() { 875 int deltaKbps = Math.abs(mLastReportedBwKbps - mFilterKbps); 876 return mAvgUsedKbps > 0 877 && deltaKbps * 100 > BW_UPDATE_THRESHOLD_PERCENT * mLastReportedBwKbps; 878 } 879 calculateError()880 public void calculateError() { 881 if (!mBwSampleValid || getCurrentCount() <= BW_STATS_COUNT_THRESHOLD + 1 882 || mAvgUsedKbps <= 0) { 883 return; 884 } 885 int bwEstExtErrPercent = calculateErrorPercent(mLastReportedBwKbps, mBwSampleKbps); 886 int bwEstAvgErrPercent = calculateErrorPercent(mAvgUsedKbps, mBwSampleKbps); 887 int bwEstIntErrPercent = calculateErrorPercent(mFilterKbps, mBwSampleKbps); 888 int coldStartErrPercent = calculateErrorPercent(mStaticBwKbps, mBwSampleKbps); 889 890 TelephonyMetrics.getInstance().writeBandwidthStats(mLink, mDataRat, getNrMode(mDataRat), 891 mSignalLevel, bwEstExtErrPercent, coldStartErrPercent, mBwSampleKbps); 892 893 StringBuilder sb = new StringBuilder(); 894 logd(sb.append(mLink) 895 .append(" sampKbps ").append(mBwSampleKbps) 896 .append(" filtKbps ").append(mFilterKbps) 897 .append(" reportKbps ").append(mLastReportedBwKbps) 898 .append(" avgUsedKbps ").append(mAvgUsedKbps) 899 .append(" csKbps ").append(mStaticBwKbps) 900 .append(" intErrPercent ").append(bwEstIntErrPercent) 901 .append(" avgErrPercent ").append(bwEstAvgErrPercent) 902 .append(" extErrPercent ").append(bwEstExtErrPercent) 903 .append(" csErrPercent ").append(coldStartErrPercent) 904 .toString()); 905 } 906 calculateErrorPercent(int inKbps, int bwSampleKbps)907 private int calculateErrorPercent(int inKbps, int bwSampleKbps) { 908 long errorPercent = 100L * (inKbps - bwSampleKbps) / bwSampleKbps; 909 return (int) Math.max(-MAX_ERROR_PERCENT, Math.min(errorPercent, MAX_ERROR_PERCENT)); 910 } 911 } 912 913 /** 914 * Update the byte count threshold. 915 * It should be called whenever the RAT or signal level is changed. 916 * For the RAT with high BW (4G and beyond), use BYTE_DELTA_THRESHOLD_KB table. 917 * For other RATs, derive the threshold based on the static BW values. 918 */ updateByteCountThr()919 private void updateByteCountThr() { 920 mTxState.updateByteCountThr(); 921 mRxState.updateByteCountThr(); 922 } 923 924 // Reset BW filter to a long term avg value (PLMN/RAT/TAC dependent) or static BW value. 925 // It should be called whenever PLMN/RAT or static BW value is changed; resetBandwidthFilter()926 private void resetBandwidthFilter() { 927 mTxState.resetBandwidthFilter(); 928 mRxState.resetBandwidthFilter(); 929 } 930 sendLinkBandwidthToDataConnection(int linkBandwidthTxKps, int linkBandwidthRxKps)931 private void sendLinkBandwidthToDataConnection(int linkBandwidthTxKps, int linkBandwidthRxKps) { 932 logv("send to DC tx " + linkBandwidthTxKps + " rx " + linkBandwidthRxKps); 933 Pair<Integer, Integer> bandwidthInfo = 934 new Pair<Integer, Integer>(linkBandwidthTxKps, linkBandwidthRxKps); 935 mBandwidthChangedRegistrants.notifyRegistrants(new AsyncResult(null, bandwidthInfo, null)); 936 mLinkBandwidthEstimatorCallbacks.forEach(callback -> callback.invokeFromExecutor( 937 () -> callback.onBandwidthChanged(linkBandwidthTxKps, linkBandwidthRxKps))); 938 } 939 handleSignalStrengthChanged(SignalStrength signalStrength)940 private void handleSignalStrengthChanged(SignalStrength signalStrength) { 941 if (signalStrength == null) { 942 return; 943 } 944 945 mSignalStrengthDbm = signalStrength.getDbm(); 946 mSignalLevel = signalStrength.getLevel(); 947 updateByteCountThr(); 948 if (updateDataRatCellIdentityBandwidth()) { 949 return; 950 } 951 952 if (Math.abs(mBandwidthUpdateSignalDbm - mSignalStrengthDbm) > RSSI_DELTA_THRESHOLD_DB) { 953 updateTxRxBandwidthFilterSendToDataConnection(); 954 } 955 } 956 registerNrStateFrequencyChange()957 private void registerNrStateFrequencyChange() { 958 mPhone.getServiceStateTracker().registerForNrStateChanged(this, 959 MSG_NR_STATE_CHANGED, null); 960 mPhone.getServiceStateTracker().registerForNrFrequencyChanged(this, 961 MSG_NR_FREQUENCY_CHANGED, null); 962 } 963 964 /** 965 * @return The data activity. 966 */ getDataActivity()967 public @DataActivityType int getDataActivity() { 968 return mDataActivity; 969 } 970 971 /** 972 * Get a string based on current RAT 973 */ getDataRatName(int rat)974 public String getDataRatName(int rat) { 975 return getDataRatName(rat, getNrMode(rat)); 976 } 977 getNrMode(int rat)978 private int getNrMode(int rat) { 979 if (rat == TelephonyManager.NETWORK_TYPE_LTE && isNrNsaConnected()) { 980 return mPhone.getServiceState().getNrFrequencyRange() 981 == ServiceState.FREQUENCY_RANGE_MMWAVE 982 ? NrMode.NR_NSA_MMWAVE : NrMode.NR_NSA; 983 } else if (rat == TelephonyManager.NETWORK_TYPE_NR) { 984 return mPhone.getServiceState().getNrFrequencyRange() 985 == ServiceState.FREQUENCY_RANGE_MMWAVE 986 ? NrMode.NR_SA_MMWAVE : NrMode.NR_SA; 987 } 988 return NrMode.NR_NONE; 989 } 990 991 /** 992 * Get a string based on current RAT and NR operation mode. 993 */ getDataRatName(int rat, int nrMode)994 public static String getDataRatName(int rat, int nrMode) { 995 if (rat == TelephonyManager.NETWORK_TYPE_LTE 996 && (nrMode == NrMode.NR_NSA || nrMode == NrMode.NR_NSA_MMWAVE)) { 997 return nrMode == NrMode.NR_NSA 998 ? DctConstants.RAT_NAME_NR_NSA : DctConstants.RAT_NAME_NR_NSA_MMWAVE; 999 } else if (rat == TelephonyManager.NETWORK_TYPE_NR) { 1000 return nrMode == NrMode.NR_SA 1001 ? TelephonyManager.getNetworkTypeName(rat) : DctConstants.RAT_NAME_NR_SA_MMWAVE; 1002 } 1003 return TelephonyManager.getNetworkTypeName(rat); 1004 } 1005 1006 /** 1007 * Check if the device is connected to NR 5G Non-Standalone network 1008 */ isNrNsaConnected()1009 private boolean isNrNsaConnected() { 1010 return mPhone.getServiceState().getNrState() 1011 == NetworkRegistrationInfo.NR_STATE_CONNECTED; 1012 } 1013 1014 // Update avg BW values. 1015 // It should be called whenever the RAT could be changed. 1016 // return true if avg value is changed; updateStaticBwValue(int dataRat)1017 private boolean updateStaticBwValue(int dataRat) { 1018 Pair<Integer, Integer> values = getStaticAvgBw(dataRat); 1019 if (values == null) { 1020 mTxState.mStaticBwKbps = DEFAULT_LINK_BAND_WIDTH_KBPS; 1021 mRxState.mStaticBwKbps = DEFAULT_LINK_BAND_WIDTH_KBPS; 1022 return true; 1023 } 1024 if (mTxState.mStaticBwKbps != values.second 1025 || mRxState.mStaticBwKbps != values.first) { 1026 mTxState.mStaticBwKbps = values.second; 1027 mRxState.mStaticBwKbps = values.first; 1028 return true; 1029 } 1030 return false; 1031 } 1032 1033 /** get per-RAT static bandwidth value */ getStaticAvgBw(int dataRat)1034 public Pair<Integer, Integer> getStaticAvgBw(int dataRat) { 1035 String dataRatName = getDataRatName(dataRat); 1036 Pair<Integer, Integer> values = AVG_BW_PER_RAT_MAP.get(dataRatName); 1037 if (values == null) { 1038 Rlog.e(TAG, dataRatName + " is not found in Avg BW table"); 1039 } 1040 return values; 1041 } 1042 updateStaticBwValueResetFilter()1043 private void updateStaticBwValueResetFilter() { 1044 if (updateStaticBwValue(mDataRat)) { 1045 updateByteCountThr(); 1046 resetBandwidthFilter(); 1047 updateTxRxBandwidthFilterSendToDataConnection(); 1048 } 1049 } 1050 getDataNri()1051 private NetworkRegistrationInfo getDataNri() { 1052 return mPhone.getServiceState().getNetworkRegistrationInfo( 1053 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 1054 } 1055 updateDataRatCellIdentityBandwidth()1056 private boolean updateDataRatCellIdentityBandwidth() { 1057 boolean updatedPlmn = false; 1058 CellIdentity cellIdentity = mPhone.getCurrentCellIdentity(); 1059 mTac = getTac(cellIdentity); 1060 String plmn; 1061 1062 if (mPhone.getServiceState().getOperatorNumeric() != null) { 1063 plmn = mPhone.getServiceState().getOperatorNumeric(); 1064 } else { 1065 if (cellIdentity.getPlmn() != null) { 1066 plmn = cellIdentity.getPlmn(); 1067 } else { 1068 plmn = UNKNOWN_PLMN; 1069 } 1070 } 1071 if (mPlmn == null || !plmn.equals(mPlmn)) { 1072 updatedPlmn = true; 1073 mPlmn = plmn; 1074 } 1075 1076 boolean updatedRat = false; 1077 NetworkRegistrationInfo nri = getDataNri(); 1078 if (nri != null) { 1079 int dataRat = nri.getAccessNetworkTechnology(); 1080 if (dataRat != mDataRat) { 1081 updatedRat = true; 1082 mDataRat = dataRat; 1083 updateStaticBwValue(mDataRat); 1084 updateByteCountThr(); 1085 } 1086 } 1087 1088 boolean updatedPlmnOrRat = updatedPlmn || updatedRat; 1089 if (updatedPlmnOrRat) { 1090 resetBandwidthFilter(); 1091 updateTxRxBandwidthFilterSendToDataConnection(); 1092 mLastPlmnOrRatChangeTimeMs = mTelephonyFacade.getElapsedSinceBootMillis(); 1093 } 1094 return updatedPlmnOrRat; 1095 } 1096 getTac(@onNull CellIdentity cellIdentity)1097 private int getTac(@NonNull CellIdentity cellIdentity) { 1098 if (cellIdentity instanceof CellIdentityLte) { 1099 return ((CellIdentityLte) cellIdentity).getTac(); 1100 } 1101 if (cellIdentity instanceof CellIdentityNr) { 1102 return ((CellIdentityNr) cellIdentity).getTac(); 1103 } 1104 if (cellIdentity instanceof CellIdentityWcdma) { 1105 return ((CellIdentityWcdma) cellIdentity).getLac(); 1106 } 1107 if (cellIdentity instanceof CellIdentityTdscdma) { 1108 return ((CellIdentityTdscdma) cellIdentity).getLac(); 1109 } 1110 if (cellIdentity instanceof CellIdentityGsm) { 1111 return ((CellIdentityGsm) cellIdentity).getLac(); 1112 } 1113 return 0; 1114 } 1115 1116 private class TelephonyCallbackImpl extends TelephonyCallback implements 1117 TelephonyCallback.SignalStrengthsListener, 1118 TelephonyCallback.ActiveDataSubscriptionIdListener { 1119 @Override onSignalStrengthsChanged(SignalStrength signalStrength)1120 public void onSignalStrengthsChanged(SignalStrength signalStrength) { 1121 obtainMessage(MSG_SIGNAL_STRENGTH_CHANGED, signalStrength).sendToTarget(); 1122 } 1123 @Override onActiveDataSubscriptionIdChanged(int subId)1124 public void onActiveDataSubscriptionIdChanged(int subId) { 1125 obtainMessage(MSG_ACTIVE_PHONE_CHANGED, subId).sendToTarget(); 1126 } 1127 } 1128 logv(String msg)1129 void logv(String msg) { 1130 if (DBG) Rlog.v(TAG, msg); 1131 } 1132 logd(String msg)1133 void logd(String msg) { 1134 if (DBG) Rlog.d(TAG, msg); 1135 mLocalLog.log(msg); 1136 } 1137 1138 @VisibleForTesting 1139 static final int UNKNOWN_TAC = -1; 1140 // Map with NetworkKey as the key and NetworkBandwidth as the value. 1141 // NetworkKey is specified by the PLMN, data RAT and TAC of network. 1142 // NetworkBandwidth represents the bandwidth related stats of each network. 1143 private final Map<NetworkKey, NetworkBandwidth> mNetworkMap = new ArrayMap<>(); 1144 private static class NetworkKey { 1145 private final String mPlmn; 1146 private final String mDataRat; 1147 private final int mTac; NetworkKey(String plmn, int tac, String dataRat)1148 NetworkKey(String plmn, int tac, String dataRat) { 1149 mPlmn = plmn; 1150 mTac = tac; 1151 mDataRat = dataRat; 1152 } 1153 @Override equals(@ullable Object o)1154 public boolean equals(@Nullable Object o) { 1155 if (o == null || !(o instanceof NetworkKey) || hashCode() != o.hashCode()) { 1156 return false; 1157 } 1158 1159 if (this == o) { 1160 return true; 1161 } 1162 1163 NetworkKey that = (NetworkKey) o; 1164 return mPlmn.equals(that.mPlmn) 1165 && mTac == that.mTac 1166 && mDataRat.equals(that.mDataRat); 1167 } 1168 1169 @Override hashCode()1170 public int hashCode() { 1171 return Objects.hash(mPlmn, mDataRat, mTac); 1172 } 1173 @Override toString()1174 public String toString() { 1175 StringBuilder sb = new StringBuilder(); 1176 sb.append("Plmn").append(mPlmn) 1177 .append("Rat").append(mDataRat) 1178 .append("Tac").append(mTac) 1179 .toString(); 1180 return sb.toString(); 1181 } 1182 } 1183 1184 @NonNull lookupNetwork(String plmn, String dataRat)1185 private NetworkBandwidth lookupNetwork(String plmn, String dataRat) { 1186 return lookupNetwork(plmn, UNKNOWN_TAC, dataRat); 1187 } 1188 1189 /** Look up NetworkBandwidth and create a new one if it doesn't exist */ 1190 @VisibleForTesting 1191 @NonNull lookupNetwork(String plmn, int tac, String dataRat)1192 public NetworkBandwidth lookupNetwork(String plmn, int tac, String dataRat) { 1193 if (plmn == null || dataRat.equals( 1194 TelephonyManager.getNetworkTypeName(TelephonyManager.NETWORK_TYPE_UNKNOWN))) { 1195 return mPlaceholderNetwork; 1196 } 1197 NetworkKey key = new NetworkKey(plmn, tac, dataRat); 1198 NetworkBandwidth ans = mNetworkMap.get(key); 1199 if (ans == null) { 1200 ans = new NetworkBandwidth(key.toString()); 1201 mNetworkMap.put(key, ans); 1202 } 1203 return ans; 1204 } 1205 1206 /** A class holding link bandwidth related stats */ 1207 @VisibleForTesting 1208 public class NetworkBandwidth { 1209 private final String mKey; NetworkBandwidth(String key)1210 NetworkBandwidth(String key) { 1211 mKey = key; 1212 } 1213 1214 /** Update link bandwidth stats */ update(long value, int link, int level)1215 public void update(long value, int link, int level) { 1216 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences( 1217 mPhone.getContext()); 1218 String valueKey = getValueKey(link, level); 1219 String countKey = getCountKey(link, level); 1220 SharedPreferences.Editor editor = sp.edit(); 1221 long currValue = sp.getLong(valueKey, 0); 1222 int currCount = sp.getInt(countKey, 0); 1223 editor.putLong(valueKey, currValue + value); 1224 editor.putInt(countKey, currCount + 1); 1225 editor.apply(); 1226 } 1227 getValueKey(int link, int level)1228 private String getValueKey(int link, int level) { 1229 return getDataKey(link, level) + "Data"; 1230 } 1231 getCountKey(int link, int level)1232 private String getCountKey(int link, int level) { 1233 return getDataKey(link, level) + "Count"; 1234 } 1235 getDataKey(int link, int level)1236 private String getDataKey(int link, int level) { 1237 StringBuilder sb = new StringBuilder(); 1238 return sb.append(mKey) 1239 .append("Link").append(link) 1240 .append("Level").append(level) 1241 .toString(); 1242 } 1243 1244 /** Get the accumulated bandwidth value */ getValue(int link, int level)1245 public long getValue(int link, int level) { 1246 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences( 1247 mPhone.getContext()); 1248 String valueKey = getValueKey(link, level); 1249 return sp.getLong(valueKey, 0); 1250 } 1251 1252 /** Get the accumulated bandwidth count */ getCount(int link, int level)1253 public int getCount(int link, int level) { 1254 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences( 1255 mPhone.getContext()); 1256 String countKey = getCountKey(link, level); 1257 return sp.getInt(countKey, 0); 1258 } 1259 1260 @Override toString()1261 public String toString() { 1262 StringBuilder sb = new StringBuilder(); 1263 sb.append(mKey); 1264 sb.append("\n"); 1265 for (int link = 0; link < NUM_LINK_DIRECTION; link++) { 1266 sb.append((link == 0 ? "tx" : "rx")); 1267 sb.append("\n avgKbps"); 1268 for (int level = 0; level < NUM_SIGNAL_LEVEL; level++) { 1269 int count = getCount(link, level); 1270 int avgKbps = count == 0 ? 0 : (int) (getValue(link, level) / count); 1271 sb.append(" ").append(avgKbps); 1272 } 1273 sb.append("\n count"); 1274 for (int level = 0; level < NUM_SIGNAL_LEVEL; level++) { 1275 int count = getCount(link, level); 1276 sb.append(" ").append(count); 1277 } 1278 sb.append("\n"); 1279 } 1280 return sb.toString(); 1281 } 1282 } 1283 1284 /** 1285 * Dump the internal state and local logs 1286 */ dump(FileDescriptor fd, PrintWriter printWriter, String[] args)1287 public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) { 1288 IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " "); 1289 pw.increaseIndent(); 1290 pw.println("current PLMN " + mPlmn + " TAC " + mTac + " RAT " + getDataRatName(mDataRat)); 1291 pw.println("all networks visited since device boot"); 1292 for (NetworkBandwidth network : mNetworkMap.values()) { 1293 pw.println(network.toString()); 1294 } 1295 1296 try { 1297 mLocalLog.dump(fd, pw, args); 1298 } catch (Exception e) { 1299 e.printStackTrace(); 1300 } 1301 pw.decreaseIndent(); 1302 pw.println(); 1303 pw.flush(); 1304 } 1305 1306 } 1307