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.telephony.qns; 18 19 import static com.android.telephony.qns.DataConnectionStatusTracker.STATE_CONNECTED; 20 import static com.android.telephony.qns.DataConnectionStatusTracker.STATE_HANDOVER; 21 import static com.android.telephony.qns.QnsConstants.INVALID_ID; 22 23 import android.annotation.IntDef; 24 import android.net.NetworkCapabilities; 25 import android.os.Handler; 26 import android.os.Looper; 27 import android.os.Message; 28 import android.os.SystemClock; 29 import android.telephony.AccessNetworkConstants; 30 import android.telephony.Annotation; 31 import android.telephony.TelephonyManager; 32 import android.util.Log; 33 import android.util.Pair; 34 35 import com.android.internal.annotations.VisibleForTesting; 36 import com.android.telephony.qns.DataConnectionStatusTracker.DataConnectionChangedInfo; 37 38 import java.io.PrintWriter; 39 import java.util.ArrayList; 40 import java.util.HashMap; 41 import java.util.List; 42 import java.util.Map; 43 import java.util.concurrent.ConcurrentHashMap; 44 45 /** 46 * Prevents HO pingpong between Cellular and IWLAN. Provide Throttling for certain cause. Provide 47 * Handover not allowed policy. 48 */ 49 class RestrictManager { 50 private final String mLogTag; 51 private final boolean mDebugFlag = true; 52 static final int RESTRICT_TYPE_GUARDING = 1; 53 static final int RESTRICT_TYPE_THROTTLING = 2; 54 static final int RESTRICT_TYPE_HO_NOT_ALLOWED = 3; 55 static final int RESTRICT_TYPE_NON_PREFERRED_TRANSPORT = 4; 56 static final int RESTRICT_TYPE_RTP_LOW_QUALITY = 5; 57 static final int RESTRICT_TYPE_RESTRICT_IWLAN_IN_CALL = 6; 58 static final int RESTRICT_TYPE_RESTRICT_IWLAN_CS_CALL = 7; 59 static final int RESTRICT_TYPE_FALLBACK_TO_WWAN_IMS_REGI_FAIL = 8; 60 static final int RESTRICT_TYPE_FALLBACK_ON_DATA_CONNECTION_FAIL = 9; 61 static final int RESTRICT_TYPE_FALLBACK_TO_WWAN_RTT_BACKHAUL_FAIL = 10; 62 63 @IntDef( 64 value = { 65 RESTRICT_TYPE_GUARDING, 66 RESTRICT_TYPE_THROTTLING, 67 RESTRICT_TYPE_HO_NOT_ALLOWED, 68 RESTRICT_TYPE_NON_PREFERRED_TRANSPORT, 69 RESTRICT_TYPE_RTP_LOW_QUALITY, 70 RESTRICT_TYPE_RESTRICT_IWLAN_IN_CALL, 71 RESTRICT_TYPE_RESTRICT_IWLAN_CS_CALL, 72 RESTRICT_TYPE_FALLBACK_TO_WWAN_IMS_REGI_FAIL, 73 RESTRICT_TYPE_FALLBACK_ON_DATA_CONNECTION_FAIL, 74 RESTRICT_TYPE_FALLBACK_TO_WWAN_RTT_BACKHAUL_FAIL, 75 }) 76 @interface RestrictType {} 77 78 static final int RELEASE_EVENT_DISCONNECT = 1; 79 static final int RELEASE_EVENT_WIFI_AP_CHANGED = 2; 80 static final int RELEASE_EVENT_WFC_PREFER_MODE_CHANGED = 3; 81 static final int RELEASE_EVENT_CALL_END = 4; 82 static final int RELEASE_EVENT_IMS_NOT_SUPPORT_RAT = 5; 83 84 @IntDef( 85 value = { 86 RELEASE_EVENT_DISCONNECT, 87 RELEASE_EVENT_WIFI_AP_CHANGED, 88 RELEASE_EVENT_WFC_PREFER_MODE_CHANGED, 89 RELEASE_EVENT_CALL_END, 90 RELEASE_EVENT_IMS_NOT_SUPPORT_RAT, 91 }) 92 @interface ReleaseEvent {} 93 94 private static final int EVENT_DATA_CONNECTION_CHANGED = 3001; 95 private static final int EVENT_CALL_STATE_CHANGED = 3002; 96 private static final int EVENT_SRVCC_STATE_CHANGED = 3003; 97 private static final int EVENT_IMS_REGISTRATION_STATE_CHANGED = 3004; 98 private static final int EVENT_LOW_RTP_QUALITY_REPORTED = 3006; 99 private static final int EVENT_RELEASE_RESTRICTION = 3008; 100 protected static final int EVENT_INITIAL_DATA_CONNECTION_FAIL_RETRY_TIMER_EXPIRED = 3009; 101 private static final int EVENT_WIFI_RTT_BACKHAUL_CHECK_STATUS = 3010; 102 103 @VisibleForTesting static final int GUARDING_TIMER_HANDOVER_INIT = 30000; 104 105 static final HashMap<Integer, int[]> sReleaseEventMap = 106 new HashMap<Integer, int[]>() { 107 { 108 put( 109 RESTRICT_TYPE_GUARDING, 110 new int[] { 111 RELEASE_EVENT_DISCONNECT, RELEASE_EVENT_WFC_PREFER_MODE_CHANGED 112 }); 113 put( 114 RESTRICT_TYPE_RTP_LOW_QUALITY, 115 new int[] {RELEASE_EVENT_CALL_END, RELEASE_EVENT_WIFI_AP_CHANGED}); 116 put(RESTRICT_TYPE_RESTRICT_IWLAN_IN_CALL, new int[] {RELEASE_EVENT_CALL_END}); 117 put( 118 RESTRICT_TYPE_FALLBACK_TO_WWAN_IMS_REGI_FAIL, 119 new int[] { 120 RELEASE_EVENT_DISCONNECT, RELEASE_EVENT_IMS_NOT_SUPPORT_RAT 121 }); 122 put( 123 RESTRICT_TYPE_FALLBACK_ON_DATA_CONNECTION_FAIL, 124 new int[] { 125 RELEASE_EVENT_DISCONNECT, 126 RELEASE_EVENT_WIFI_AP_CHANGED, 127 RELEASE_EVENT_WFC_PREFER_MODE_CHANGED, 128 RELEASE_EVENT_IMS_NOT_SUPPORT_RAT 129 }); 130 put( 131 RESTRICT_TYPE_FALLBACK_TO_WWAN_RTT_BACKHAUL_FAIL, 132 new int[] { 133 RELEASE_EVENT_DISCONNECT, 134 RELEASE_EVENT_WIFI_AP_CHANGED, 135 RELEASE_EVENT_IMS_NOT_SUPPORT_RAT 136 }); 137 } 138 }; 139 private static final int[] ignorableRestrictionsOnSingleRat = 140 new int[] { 141 RESTRICT_TYPE_GUARDING, 142 RESTRICT_TYPE_RTP_LOW_QUALITY, 143 RESTRICT_TYPE_RESTRICT_IWLAN_IN_CALL, 144 RESTRICT_TYPE_FALLBACK_TO_WWAN_IMS_REGI_FAIL, 145 RESTRICT_TYPE_FALLBACK_ON_DATA_CONNECTION_FAIL, 146 RESTRICT_TYPE_FALLBACK_TO_WWAN_RTT_BACKHAUL_FAIL 147 }; 148 149 private QnsCarrierConfigManager mQnsCarrierConfigManager; 150 private QnsTelephonyListener mTelephonyListener; 151 private QnsEventDispatcher mQnsEventDispatcher; 152 @VisibleForTesting Handler mHandler; 153 154 @QnsConstants.CellularCoverage 155 int mCellularCoverage; // QnsConstants.COVERAGE_HOME or QnsConstants.COVERAGE_ROAM 156 157 int mCellularAccessNetwork; 158 159 @VisibleForTesting QnsRegistrant mRestrictInfoRegistrant; 160 private DataConnectionStatusTracker mDataConnectionStatusTracker; 161 private CellularNetworkStatusTracker mCellularNetworkStatusTracker; 162 private QnsCallStatusTracker mQnsCallStatusTracker; 163 private QnsCallStatusTracker.ActiveCallTracker mActiveCallTracker; 164 private QnsImsManager mQnsImsManager; 165 private QnsTimer mQnsTimer; 166 private WifiBackhaulMonitor mWifiBackhaulMonitor; 167 private QnsMetrics mQnsMetrics; 168 private int mNetCapability; 169 private int mSlotId; 170 private int mTransportType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID; 171 private int mLastEvaluatedTransportType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID; 172 private int mWfcPreference; 173 private int mWfcRoamingPreference; 174 private int mCounterForIwlanRestrictionInCall; 175 private int mRetryCounterOnDataConnectionFail; 176 private int mFallbackCounterOnDataConnectionFail; 177 private boolean mIsRttStatusCheckRegistered = false; 178 private int mLastDataConnectionTransportType; 179 private int mFallbackTimerId = -1; 180 private boolean mIsTimerRunningOnDataConnectionFail = false; 181 private Pair<Integer, Long> mDeferredThrottlingEvent = null; 182 183 /** IMS call type */ 184 @QnsConstants.QnsCallType private int mImsCallType; 185 /** Call state from TelephonyCallback.CallStateListener */ 186 @Annotation.CallState private int mCallState; 187 188 private Map<Integer, RestrictInfo> mRestrictInfos = new ConcurrentHashMap<>(); 189 private Map<Restriction, Integer> mRestrictionTimers = new ConcurrentHashMap<>(); 190 191 private class RestrictManagerHandler extends Handler { RestrictManagerHandler(Looper l)192 RestrictManagerHandler(Looper l) { 193 super(l); 194 } 195 196 @Override handleMessage(Message message)197 public void handleMessage(Message message) { 198 QnsAsyncResult ar; 199 int transportType; 200 Log.d(mLogTag, "handleMessage : " + message.what); 201 switch (message.what) { 202 case EVENT_DATA_CONNECTION_CHANGED: 203 ar = (QnsAsyncResult) message.obj; 204 onDataConnectionChanged((DataConnectionChangedInfo) ar.mResult); 205 break; 206 207 case EVENT_CALL_STATE_CHANGED: 208 ar = (QnsAsyncResult) message.obj; 209 int callState = (int) ar.mResult; 210 onCallStateChanged(callState, mTransportType, mCellularAccessNetwork); 211 break; 212 213 case EVENT_SRVCC_STATE_CHANGED: 214 ar = (QnsAsyncResult) message.obj; 215 int srvccState = (int) ar.mResult; 216 onSrvccStateChanged(srvccState); 217 break; 218 219 case EVENT_LOW_RTP_QUALITY_REPORTED: 220 ar = (QnsAsyncResult) message.obj; 221 int reason = (int) ar.mResult; 222 Log.d(mLogTag, "EVENT_LOW_RTP_QUALITY_REPORTED reason: " + reason); 223 onLowRtpQualityEvent(reason); 224 break; 225 226 case EVENT_IMS_REGISTRATION_STATE_CHANGED: 227 ar = (QnsAsyncResult) message.obj; 228 onImsRegistrationStateChanged((QnsImsManager.ImsRegistrationState) ar.mResult); 229 break; 230 231 case EVENT_RELEASE_RESTRICTION: 232 transportType = message.arg1; 233 Restriction restriction = (Restriction) message.obj; 234 Log.d( 235 mLogTag, 236 "EVENT_RELEASE_RESTRICTION : " 237 + QnsConstants.transportTypeToString(transportType) 238 + " " 239 + restrictTypeToString(restriction.mRestrictType)); 240 if (restriction 241 == mRestrictInfos 242 .get(transportType) 243 .getRestrictionMap() 244 .get(restriction.mRestrictType)) { 245 releaseRestriction(transportType, restriction.mRestrictType); 246 mQnsTimer.unregisterTimer(mRestrictionTimers 247 .getOrDefault(restriction, INVALID_ID)); 248 mRestrictionTimers.remove(restriction); 249 } 250 break; 251 252 case EVENT_INITIAL_DATA_CONNECTION_FAIL_RETRY_TIMER_EXPIRED: 253 Log.d( 254 mLogTag, 255 "Initial Data Connection fail timer expired" 256 + mIsTimerRunningOnDataConnectionFail); 257 258 mQnsTimer.unregisterTimer(mFallbackTimerId); 259 if (mIsTimerRunningOnDataConnectionFail) { 260 int currTransportType = message.arg1; 261 fallbackToOtherTransportOnDataConnectionFail(currTransportType); 262 } 263 break; 264 265 case EVENT_WIFI_RTT_BACKHAUL_CHECK_STATUS: 266 ar = (QnsAsyncResult) message.obj; 267 boolean rttCheckStatus = (boolean) ar.mResult; 268 if (!rttCheckStatus) { // rtt Backhaul check failed 269 Log.d(mLogTag, "Rtt check status received:Fail"); 270 onWlanRttFail(); 271 } 272 break; 273 274 case QnsEventDispatcher.QNS_EVENT_WFC_MODE_TO_WIFI_ONLY: 275 onWfcModeChanged(QnsConstants.WIFI_ONLY, QnsConstants.COVERAGE_HOME); 276 break; 277 case QnsEventDispatcher.QNS_EVENT_WFC_MODE_TO_CELLULAR_PREFERRED: 278 onWfcModeChanged(QnsConstants.CELL_PREF, QnsConstants.COVERAGE_HOME); 279 break; 280 281 case QnsEventDispatcher.QNS_EVENT_WFC_MODE_TO_WIFI_PREFERRED: 282 onWfcModeChanged(QnsConstants.WIFI_PREF, QnsConstants.COVERAGE_HOME); 283 break; 284 285 case QnsEventDispatcher.QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_ONLY: 286 onWfcModeChanged(QnsConstants.WIFI_ONLY, QnsConstants.COVERAGE_ROAM); 287 break; 288 289 case QnsEventDispatcher.QNS_EVENT_WFC_ROAMING_MODE_TO_CELLULAR_PREFERRED: 290 onWfcModeChanged(QnsConstants.CELL_PREF, QnsConstants.COVERAGE_ROAM); 291 break; 292 293 case QnsEventDispatcher.QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_PREFERRED: 294 onWfcModeChanged(QnsConstants.WIFI_PREF, QnsConstants.COVERAGE_ROAM); 295 break; 296 297 case QnsEventDispatcher.QNS_EVENT_APM_ENABLED: 298 case QnsEventDispatcher.QNS_EVENT_WFC_DISABLED: 299 case QnsEventDispatcher.QNS_EVENT_WIFI_DISABLING: 300 if (mFallbackCounterOnDataConnectionFail > 0) { 301 Log.d(mLogTag, "Reset Fallback Counter on APM On/WFC off/Wifi Off"); 302 mFallbackCounterOnDataConnectionFail = 0; 303 } 304 305 if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS 306 && hasRestrictionType( 307 AccessNetworkConstants.TRANSPORT_TYPE_WLAN, 308 RESTRICT_TYPE_FALLBACK_TO_WWAN_RTT_BACKHAUL_FAIL)) { 309 310 releaseRestriction( 311 AccessNetworkConstants.TRANSPORT_TYPE_WLAN, 312 RESTRICT_TYPE_FALLBACK_TO_WWAN_RTT_BACKHAUL_FAIL); 313 } 314 break; 315 default: 316 break; 317 } 318 } 319 } 320 321 class LowRtpQualityRestriction extends Restriction{ 322 private int mReason; LowRtpQualityRestriction(int type, int[] releaseEvents, int restrictTime, int reason)323 LowRtpQualityRestriction(int type, int[] releaseEvents, int restrictTime, int reason) { 324 super(type, releaseEvents, restrictTime); 325 mReason = reason; 326 } getReason()327 int getReason() { 328 return mReason; 329 } 330 } 331 332 class Restriction { 333 private final int mRestrictType; 334 final ArrayList<Integer> mReleaseEventList; 335 long mReleaseTime; 336 Restriction(int type, int[] releaseEvents, long restrictTime)337 Restriction(int type, int[] releaseEvents, long restrictTime) { 338 mRestrictType = type; 339 if (restrictTime == 0) { 340 mReleaseTime = 0; 341 } else { 342 mReleaseTime = restrictTime + SystemClock.elapsedRealtime(); 343 if (restrictTime > 0 && mReleaseTime < 0) { 344 mReleaseTime = Long.MAX_VALUE; 345 } 346 } 347 if (releaseEvents != null && releaseEvents.length > 0) { 348 mReleaseEventList = new ArrayList<>(); 349 for (int i : releaseEvents) { 350 mReleaseEventList.add(i); 351 } 352 } else { 353 mReleaseEventList = null; 354 } 355 } 356 needRelease(int event)357 boolean needRelease(int event) { 358 if (mReleaseEventList == null) { 359 return false; 360 } 361 for (Integer i : mReleaseEventList) { 362 if (event == i.intValue()) { 363 return true; 364 } 365 } 366 return false; 367 } 368 updateRestrictTime(long timeMillis)369 void updateRestrictTime(long timeMillis) { 370 mReleaseTime = SystemClock.elapsedRealtime() + timeMillis; 371 if (timeMillis > 0 && mReleaseTime < 0) { 372 mReleaseTime = Long.MAX_VALUE; 373 } 374 } 375 376 @Override toString()377 public String toString() { 378 StringBuilder builder = new StringBuilder(); 379 builder.append("[RESTRICTION type:").append(restrictTypeToString(mRestrictType)); 380 builder.append(" releaseEvents:( "); 381 if (mReleaseEventList != null) { 382 for (Integer i : mReleaseEventList) { 383 builder.append(i).append(" "); 384 } 385 } 386 builder.append(") remainedTimeMillis:"); 387 if (mReleaseTime == 0) { 388 builder.append("N/A"); 389 } else { 390 long remain = mReleaseTime - SystemClock.elapsedRealtime(); 391 builder.append(remain); 392 } 393 builder.append("]"); 394 return builder.toString(); 395 } 396 } 397 398 class RestrictInfo { 399 private int mTransportMode; // AccessNetworkConstants.TRANSPORT_TYPE_WWAN; 400 private HashMap<Integer, Restriction> mRestrictionMap = new HashMap<>(); 401 RestrictInfo(int transportMode)402 RestrictInfo(int transportMode) { 403 mTransportMode = transportMode; 404 } 405 getRestrictionMap()406 HashMap<Integer, Restriction> getRestrictionMap() { 407 return mRestrictionMap; 408 } 409 isRestricted()410 boolean isRestricted() { 411 return mRestrictionMap.size() != 0; 412 } 413 414 /** 415 * This method returns if the restriction info has given restriction type. 416 * 417 * @param restrictType integer value of restriction type. 418 * @return true if restrictinfo has the restriction; otherwise false. 419 */ hasRestrictionType(@estrictType int restrictType)420 boolean hasRestrictionType(@RestrictType int restrictType) { 421 return mRestrictionMap.get(restrictType) != null; 422 } 423 424 @Override toString()425 public String toString() { 426 StringBuilder builder = new StringBuilder(); 427 builder.append("RestrictInfo[") 428 .append(QnsConstants.transportTypeToString(mTransportMode)) 429 .append("] : "); 430 if (isRestricted()) { 431 for (Restriction restriction : mRestrictionMap.values()) { 432 builder.append(restriction.toString()).append(" "); 433 } 434 } else { 435 builder.append("No restriction"); 436 } 437 return builder.toString(); 438 } 439 } 440 RestrictManager( QnsComponents qnsComponents, Looper loop, int netCapability, DataConnectionStatusTracker dcst, int slotId)441 RestrictManager( 442 QnsComponents qnsComponents, 443 Looper loop, 444 int netCapability, 445 DataConnectionStatusTracker dcst, 446 int slotId) { 447 mRestrictInfos.put( 448 AccessNetworkConstants.TRANSPORT_TYPE_WWAN, 449 new RestrictInfo(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)); 450 mRestrictInfos.put( 451 AccessNetworkConstants.TRANSPORT_TYPE_WLAN, 452 new RestrictInfo(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)); 453 mSlotId = slotId; 454 mLogTag = 455 RestrictManager.class.getSimpleName() 456 + "_" 457 + mSlotId 458 + "_" 459 + QnsUtils.getNameOfNetCapability(netCapability); 460 mTelephonyListener = qnsComponents.getQnsTelephonyListener(mSlotId); 461 mQnsEventDispatcher = qnsComponents.getQnsEventDispatcher(mSlotId); 462 mQnsCarrierConfigManager = qnsComponents.getQnsCarrierConfigManager(mSlotId); 463 mQnsTimer = qnsComponents.getQnsTimer(); 464 mHandler = new RestrictManagerHandler(loop); 465 mNetCapability = netCapability; 466 mDataConnectionStatusTracker = dcst; 467 mQnsCallStatusTracker = qnsComponents.getQnsCallStatusTracker(mSlotId); 468 mActiveCallTracker = qnsComponents.getQnsCallStatusTracker(mSlotId).getActiveCallTracker(); 469 mQnsMetrics = qnsComponents.getQnsMetrics(); 470 mDataConnectionStatusTracker.registerDataConnectionStatusChanged( 471 mHandler, EVENT_DATA_CONNECTION_CHANGED); 472 if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS) { 473 mTelephonyListener.registerCallStateListener( 474 mHandler, EVENT_CALL_STATE_CHANGED, null, true); 475 mTelephonyListener.registerSrvccStateListener( 476 mHandler, EVENT_SRVCC_STATE_CHANGED, null); 477 } 478 if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS) { 479 mQnsImsManager = qnsComponents.getQnsImsManager(mSlotId); 480 mQnsImsManager.registerImsRegistrationStatusChanged( 481 mHandler, EVENT_IMS_REGISTRATION_STATE_CHANGED); 482 mWifiBackhaulMonitor = qnsComponents.getWifiBackhaulMonitor(mSlotId); 483 } 484 485 // check if we can pass "mQnsImsManager" 486 mWfcPreference = QnsUtils.getWfcMode(qnsComponents.getQnsImsManager(mSlotId), false); 487 mWfcRoamingPreference = QnsUtils.getWfcMode(qnsComponents.getQnsImsManager(mSlotId), true); 488 489 List<Integer> events = new ArrayList<>(); 490 events.add(QnsEventDispatcher.QNS_EVENT_WFC_MODE_TO_WIFI_ONLY); 491 events.add(QnsEventDispatcher.QNS_EVENT_WFC_MODE_TO_CELLULAR_PREFERRED); 492 events.add(QnsEventDispatcher.QNS_EVENT_WFC_MODE_TO_WIFI_PREFERRED); 493 events.add(QnsEventDispatcher.QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_ONLY); 494 events.add(QnsEventDispatcher.QNS_EVENT_WFC_ROAMING_MODE_TO_CELLULAR_PREFERRED); 495 events.add(QnsEventDispatcher.QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_PREFERRED); 496 events.add(QnsEventDispatcher.QNS_EVENT_APM_ENABLED); 497 events.add(QnsEventDispatcher.QNS_EVENT_WFC_DISABLED); 498 events.add(QnsEventDispatcher.QNS_EVENT_WIFI_DISABLING); 499 mQnsEventDispatcher.registerEvent(events, mHandler); 500 501 mCellularNetworkStatusTracker = qnsComponents.getCellularNetworkStatusTracker(mSlotId); 502 restrictNonPreferredTransport(); 503 } 504 clearRestrictions()505 void clearRestrictions() { 506 mRestrictInfos.get(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).getRestrictionMap().clear(); 507 mRestrictInfos.get(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).getRestrictionMap().clear(); 508 } 509 close()510 void close() { 511 mDataConnectionStatusTracker.unRegisterDataConnectionStatusChanged(mHandler); 512 if (mIsRttStatusCheckRegistered 513 && mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS) { 514 mIsRttStatusCheckRegistered = false; 515 mWifiBackhaulMonitor.unRegisterForRttStatusChange(mHandler); 516 } 517 518 if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS) { 519 mTelephonyListener.unregisterCallStateChanged(mHandler); 520 mTelephonyListener.unregisterSrvccStateChanged(mHandler); 521 } 522 mQnsEventDispatcher.unregisterEvent(mHandler); 523 if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS 524 || mNetCapability == NetworkCapabilities.NET_CAPABILITY_EIMS) { 525 if (mActiveCallTracker != null) { 526 mActiveCallTracker.unregisterLowMediaQualityListener(mHandler); 527 } 528 } 529 if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS) { 530 mQnsImsManager.unregisterImsRegistrationStatusChanged(mHandler); 531 } 532 mRestrictionTimers.clear(); 533 } 534 onWfcModeChanged(int prefMode, @QnsConstants.CellularCoverage int coverage)535 private void onWfcModeChanged(int prefMode, @QnsConstants.CellularCoverage int coverage) { 536 Log.d(mLogTag, "onWfcModeChanged prefMode :" + prefMode + " coverage:" + coverage); 537 if (coverage == QnsConstants.COVERAGE_HOME) { 538 mWfcPreference = prefMode; 539 } else if (coverage == QnsConstants.COVERAGE_ROAM) { 540 mWfcRoamingPreference = prefMode; 541 } 542 if (mCellularCoverage == coverage) { 543 if (prefMode == QnsConstants.CELL_PREF) { 544 processReleaseEvent( 545 AccessNetworkConstants.TRANSPORT_TYPE_WWAN, 546 RELEASE_EVENT_WFC_PREFER_MODE_CHANGED); 547 } 548 if (prefMode == QnsConstants.WIFI_PREF || prefMode == QnsConstants.WIFI_ONLY) { 549 processReleaseEvent( 550 AccessNetworkConstants.TRANSPORT_TYPE_WLAN, 551 RELEASE_EVENT_WFC_PREFER_MODE_CHANGED); 552 } 553 } 554 checkIfCancelNonPreferredRestriction(getPreferredTransportType()); 555 } 556 557 @VisibleForTesting restrictNonPreferredTransport()558 void restrictNonPreferredTransport() { 559 if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS 560 && !mCellularNetworkStatusTracker.isAirplaneModeEnabled()) { 561 Log.d(mLogTag, "Restrict non-preferred transport at power up"); 562 int transportType = getPreferredTransportType(); 563 int waitingTimer = 564 mQnsCarrierConfigManager.getWaitingTimerForPreferredTransportOnPowerOn( 565 transportType); 566 if (waitingTimer != QnsConstants.KEY_DEFAULT_VALUE) { 567 int preventTransportType = QnsUtils.getOtherTransportType(transportType); 568 Log.d( 569 mLogTag, 570 "prevent " 571 + QnsConstants.transportTypeToString(preventTransportType) 572 + " " 573 + waitingTimer 574 + " milli seconds"); 575 addRestriction( 576 preventTransportType, 577 RESTRICT_TYPE_NON_PREFERRED_TRANSPORT, 578 sReleaseEventMap.get(RESTRICT_TYPE_NON_PREFERRED_TRANSPORT), 579 waitingTimer); 580 } 581 } 582 } 583 checkIfCancelNonPreferredRestriction(int transportType)584 private void checkIfCancelNonPreferredRestriction(int transportType) { 585 if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS) { 586 releaseRestriction(transportType, RESTRICT_TYPE_NON_PREFERRED_TRANSPORT); 587 } 588 } 589 getPreferredTransportType()590 private int getPreferredTransportType() { 591 int transportType; 592 int preference = mWfcPreference; 593 if (mCellularCoverage == QnsConstants.COVERAGE_ROAM) { 594 preference = mWfcRoamingPreference; 595 } 596 if (preference == QnsConstants.WIFI_PREF || preference == QnsConstants.WIFI_ONLY) { 597 transportType = AccessNetworkConstants.TRANSPORT_TYPE_WLAN; 598 } else { 599 transportType = AccessNetworkConstants.TRANSPORT_TYPE_WWAN; 600 } 601 return transportType; 602 } 603 onCallStateChanged(int callState, int transportType, int cellularAn)604 private void onCallStateChanged(int callState, int transportType, int cellularAn) { 605 Log.d( 606 mLogTag, 607 "onCallStateChanged :" 608 + callState 609 + " transport:" 610 + transportType 611 + " cellularAN:" 612 + cellularAn); 613 mCallState = callState; 614 if (callState != TelephonyManager.CALL_STATE_IDLE) { 615 if (transportType != AccessNetworkConstants.TRANSPORT_TYPE_WLAN 616 && cellularAn != AccessNetworkConstants.AccessNetworkType.EUTRAN 617 && cellularAn != AccessNetworkConstants.AccessNetworkType.NGRAN) { 618 onCsCallStarted(); 619 } 620 } else { 621 releaseRestriction( 622 AccessNetworkConstants.TRANSPORT_TYPE_WLAN, 623 RESTRICT_TYPE_RESTRICT_IWLAN_CS_CALL); 624 } 625 } 626 onSrvccStateChanged(int srvccState)627 private void onSrvccStateChanged(int srvccState) { 628 Log.d(mLogTag, "onSrvccStateChanged :" + srvccState); 629 if (mImsCallType != QnsConstants.CALL_TYPE_IDLE 630 && srvccState == TelephonyManager.SRVCC_STATE_HANDOVER_STARTED) { 631 addRestriction( 632 AccessNetworkConstants.TRANSPORT_TYPE_WLAN, 633 RESTRICT_TYPE_RESTRICT_IWLAN_CS_CALL, 634 sReleaseEventMap.get(RESTRICT_TYPE_RESTRICT_IWLAN_CS_CALL), 635 0); 636 } else if (mCallState == TelephonyManager.CALL_STATE_IDLE 637 || srvccState == TelephonyManager.SRVCC_STATE_HANDOVER_CANCELED 638 || srvccState == TelephonyManager.SRVCC_STATE_HANDOVER_FAILED) { 639 releaseRestriction( 640 AccessNetworkConstants.TRANSPORT_TYPE_WLAN, 641 RESTRICT_TYPE_RESTRICT_IWLAN_CS_CALL); 642 } 643 } 644 onCsCallStarted()645 private void onCsCallStarted() { 646 if (!mQnsCarrierConfigManager.allowImsOverIwlanCellularLimitedCase()) { 647 addRestriction( 648 AccessNetworkConstants.TRANSPORT_TYPE_WLAN, 649 RESTRICT_TYPE_RESTRICT_IWLAN_CS_CALL, 650 sReleaseEventMap.get(RESTRICT_TYPE_RESTRICT_IWLAN_CS_CALL), 651 0); 652 } 653 } 654 655 @VisibleForTesting onLowRtpQualityEvent(@nsConstants.RtpLowQualityReason int reason)656 void onLowRtpQualityEvent(@QnsConstants.RtpLowQualityReason int reason) { 657 int lowRtpQualityRestrictTime = 658 mQnsCarrierConfigManager.getHoRestrictedTimeOnLowRTPQuality(mTransportType); 659 if ((mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN 660 || mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 661 && lowRtpQualityRestrictTime > 0 662 && (mImsCallType == QnsConstants.CALL_TYPE_VOICE 663 || mImsCallType == QnsConstants.CALL_TYPE_EMERGENCY)) { 664 if (reason > 0) { 665 Restriction restriction = 666 new LowRtpQualityRestriction(RESTRICT_TYPE_RTP_LOW_QUALITY, 667 sReleaseEventMap.get(RESTRICT_TYPE_RTP_LOW_QUALITY), 668 lowRtpQualityRestrictTime, 669 reason); 670 // If current report has 'no RTP reason' and previous report at previous 671 // transport type doesn't have 'no RTP reason', let's move back to previous 672 // transport type. 673 if ((reason & 1 << QnsConstants.RTP_LOW_QUALITY_REASON_NO_RTP) != 0) { 674 releaseRestriction(QnsUtils.getOtherTransportType(mTransportType), 675 RESTRICT_TYPE_GUARDING, true); 676 HashMap<Integer, Restriction> restrictionMap = mRestrictInfos 677 .get(QnsUtils.getOtherTransportType(mTransportType)) 678 .getRestrictionMap(); 679 Restriction restrictionOtherSide = restrictionMap.get( 680 RESTRICT_TYPE_RTP_LOW_QUALITY); 681 if (restrictionOtherSide != null 682 && restrictionOtherSide instanceof LowRtpQualityRestriction) { 683 int reasonOtherSide = 684 ((LowRtpQualityRestriction) restrictionOtherSide).getReason(); 685 if ((reasonOtherSide & 1 << QnsConstants.RTP_LOW_QUALITY_REASON_NO_RTP) 686 == 0) { 687 releaseRestriction(QnsUtils.getOtherTransportType(mTransportType), 688 RESTRICT_TYPE_RTP_LOW_QUALITY, true); 689 } 690 } 691 } 692 // If both transport have low RTP quality restriction, let ANE do final decision. 693 addRestriction(mTransportType, restriction, lowRtpQualityRestrictTime); 694 695 if (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) { 696 int fallbackReason = mQnsCarrierConfigManager.getQnsIwlanHoRestrictReason(); 697 if (fallbackReason == QnsConstants.FALLBACK_REASON_RTP_OR_WIFI 698 || fallbackReason == QnsConstants.FALLBACK_REASON_RTP_ONLY) { 699 increaseCounterToRestrictIwlanInCall(); 700 } 701 } 702 } else { 703 if (hasRestrictionType(mTransportType, RESTRICT_TYPE_RTP_LOW_QUALITY)) { 704 releaseRestriction(mTransportType, RESTRICT_TYPE_RTP_LOW_QUALITY); 705 } 706 } 707 } 708 } 709 710 @VisibleForTesting onDataConnectionChanged(DataConnectionChangedInfo status)711 void onDataConnectionChanged(DataConnectionChangedInfo status) { 712 int dataConnectionState = status.getState(); 713 if (dataConnectionState == STATE_CONNECTED || dataConnectionState == STATE_HANDOVER) { 714 mTransportType = status.getTransportType(); 715 } else { 716 mTransportType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID; 717 } 718 719 Log.d(mLogTag, "onDataConnectionChanged transportType:" + status); 720 switch (status.getEvent()) { 721 case DataConnectionStatusTracker.EVENT_DATA_CONNECTION_DISCONNECTED: 722 processDataConnectionDisconnected(); 723 break; 724 case DataConnectionStatusTracker.EVENT_DATA_CONNECTION_STARTED: 725 processDataConnectionStarted(status.getTransportType()); 726 break; 727 case DataConnectionStatusTracker.EVENT_DATA_CONNECTION_CONNECTED: 728 processDataConnectionConnected(mTransportType); 729 break; 730 case DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_STARTED: 731 processDataConnectionHandoverStarted(); 732 break; 733 case DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_SUCCESS: 734 processDataConnectionHandoverSuccess(); 735 break; 736 case DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_FAILED: 737 processDataConnectionHandoverFailed(mTransportType); 738 break; 739 case DataConnectionStatusTracker.EVENT_DATA_CONNECTION_FAILED: 740 processDataConnectionFailed(status.getTransportType()); 741 break; 742 default: 743 Log.d(mLogTag, "unknown DataConnectionChangedEvent:"); 744 break; 745 } 746 } 747 processDataConnectionConnected(int transportType)748 private void processDataConnectionConnected(int transportType) { 749 // Since HO hysterisis Guard timer is expected 750 checkToCancelInitialPdnConnectionFailFallback(); 751 clearInitialPdnConnectionFailFallbackRestriction(); 752 753 checkIfCancelNonPreferredRestriction(QnsUtils.getOtherTransportType(transportType)); 754 if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS) { 755 if (mLastEvaluatedTransportType == AccessNetworkConstants.TRANSPORT_TYPE_INVALID 756 || transportType == mLastEvaluatedTransportType) { 757 processHandoverGuardingOperation(transportType); 758 } else { 759 Log.d( 760 mLogTag, 761 "DataConnectionConnected, but transport type is different," 762 + " Handover init may follow"); 763 } 764 } 765 } 766 clearInitialPdnConnectionFailFallbackRestriction()767 private void clearInitialPdnConnectionFailFallbackRestriction() { 768 mFallbackCounterOnDataConnectionFail = 0; 769 if (hasRestrictionType( 770 AccessNetworkConstants.TRANSPORT_TYPE_WWAN, 771 RESTRICT_TYPE_FALLBACK_ON_DATA_CONNECTION_FAIL)) { 772 releaseRestriction( 773 AccessNetworkConstants.TRANSPORT_TYPE_WWAN, 774 RESTRICT_TYPE_FALLBACK_ON_DATA_CONNECTION_FAIL); 775 } 776 if (hasRestrictionType( 777 AccessNetworkConstants.TRANSPORT_TYPE_WLAN, 778 RESTRICT_TYPE_FALLBACK_ON_DATA_CONNECTION_FAIL)) { 779 releaseRestriction( 780 AccessNetworkConstants.TRANSPORT_TYPE_WLAN, 781 RESTRICT_TYPE_FALLBACK_ON_DATA_CONNECTION_FAIL); 782 } 783 } 784 checkToCancelInitialPdnConnectionFailFallback()785 private void checkToCancelInitialPdnConnectionFailFallback() { 786 Log.d(mLogTag, "clear Initial PDN Connection fail Timer checks"); 787 788 mIsTimerRunningOnDataConnectionFail = false; 789 mRetryCounterOnDataConnectionFail = 0; 790 791 mQnsTimer.unregisterTimer(mFallbackTimerId); 792 } 793 processDataConnectionDisconnected()794 private void processDataConnectionDisconnected() { 795 processReleaseEvent(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, RELEASE_EVENT_DISCONNECT); 796 processReleaseEvent(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, RELEASE_EVENT_DISCONNECT); 797 mCounterForIwlanRestrictionInCall = 0; 798 if (mDeferredThrottlingEvent != null) { 799 long delayMillis = 800 mDeferredThrottlingEvent.second - QnsUtils.getSystemElapsedRealTime(); 801 if (delayMillis > 0) { 802 if (mDebugFlag) Log.d(mLogTag, "onDisconnected, process deferred Throttling event"); 803 addRestriction( 804 mDeferredThrottlingEvent.first, 805 RESTRICT_TYPE_THROTTLING, 806 sReleaseEventMap.get(RESTRICT_TYPE_THROTTLING), 807 delayMillis); 808 } 809 mDeferredThrottlingEvent = null; 810 } 811 } 812 processDataConnectionStarted(int currTransportType)813 private void processDataConnectionStarted(int currTransportType) { 814 if (mLastDataConnectionTransportType != currTransportType) { 815 Log.d( 816 mLogTag, 817 "clear Initial PDN Connection fallback checks for last transport type:" 818 + mLastDataConnectionTransportType); 819 checkToCancelInitialPdnConnectionFailFallback(); 820 821 if (hasRestrictionType( 822 mLastDataConnectionTransportType, 823 RESTRICT_TYPE_FALLBACK_ON_DATA_CONNECTION_FAIL)) { 824 Log.d( 825 mLogTag, 826 "PreIncrement_Fallback Counter : " + mFallbackCounterOnDataConnectionFail); 827 mFallbackCounterOnDataConnectionFail += 1; 828 } 829 mLastDataConnectionTransportType = currTransportType; 830 } 831 } 832 processDataConnectionHandoverStarted()833 private void processDataConnectionHandoverStarted() { 834 if ((mTransportType != AccessNetworkConstants.TRANSPORT_TYPE_INVALID) 835 && !hasRestrictionType(mTransportType, RestrictManager.RESTRICT_TYPE_GUARDING)) { 836 startGuarding(GUARDING_TIMER_HANDOVER_INIT, mTransportType); 837 } 838 } 839 processDataConnectionHandoverSuccess()840 private void processDataConnectionHandoverSuccess() { 841 // Handover Guarding Timer operation 842 processHandoverGuardingOperation(mTransportType); 843 844 // update LowRtpQualityListener 845 if (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN 846 || mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) { 847 // Return to the transport type restricted by low RTP. It may be singleRAT case, release 848 // the restriction. 849 releaseRestriction(mTransportType, RESTRICT_TYPE_RTP_LOW_QUALITY); 850 } 851 } 852 processDataConnectionHandoverFailed(int transportType)853 private void processDataConnectionHandoverFailed(int transportType) { 854 cancelGuarding(transportType); 855 } 856 processHandoverGuardingOperation(int transportType)857 private void processHandoverGuardingOperation(int transportType) { 858 int guardingTransport = QnsUtils.getOtherTransportType(transportType); 859 int delayMillis = getGuardingTimeMillis(guardingTransport, mImsCallType); 860 int minimumGuardingTimer = mQnsCarrierConfigManager.getMinimumHandoverGuardingTimer(); 861 if (delayMillis == 0 && minimumGuardingTimer > 0) { 862 delayMillis = minimumGuardingTimer; 863 } 864 865 if (delayMillis > 0) { 866 startGuarding(delayMillis, guardingTransport); 867 } else { 868 cancelGuarding(guardingTransport); 869 } 870 } 871 processDataConnectionFailed(int dataConnectionTransportType)872 private void processDataConnectionFailed(int dataConnectionTransportType) { 873 if (mCellularNetworkStatusTracker != null 874 && !mCellularNetworkStatusTracker.isAirplaneModeEnabled()) { 875 Log.d(mLogTag, "Initiate data connection fail Fallback support check"); 876 checkFallbackOnDataConnectionFail(dataConnectionTransportType); 877 } else { 878 checkToCancelInitialPdnConnectionFailFallback(); 879 } 880 } 881 checkFallbackOnDataConnectionFail(int transportType)882 private void checkFallbackOnDataConnectionFail(int transportType) { 883 int[] fallbackConfigOnInitDataFail = 884 mQnsCarrierConfigManager.getInitialDataConnectionFallbackConfig(mNetCapability); 885 886 Log.d( 887 mLogTag, 888 "FallbackConfig set is :" 889 + fallbackConfigOnInitDataFail[0] 890 + ":" 891 + fallbackConfigOnInitDataFail[1] 892 + ":" 893 + fallbackConfigOnInitDataFail[2]); 894 895 if ((fallbackConfigOnInitDataFail != null && fallbackConfigOnInitDataFail[0] == 1) 896 && !hasRestrictionType( 897 transportType, RESTRICT_TYPE_FALLBACK_ON_DATA_CONNECTION_FAIL) 898 && (fallbackConfigOnInitDataFail[3] == 0 899 || mFallbackCounterOnDataConnectionFail 900 < fallbackConfigOnInitDataFail[3])) { 901 Log.d( 902 mLogTag, 903 "FallbackCount: " 904 + fallbackConfigOnInitDataFail[3] 905 + "_" 906 + mFallbackCounterOnDataConnectionFail); 907 enableFallbackRetryCountCheckOnInitialPdnFail( 908 transportType, fallbackConfigOnInitDataFail[1]); 909 enableFallbackRetryTimerCheckOnInitialPdnFail( 910 transportType, fallbackConfigOnInitDataFail[2]); 911 } 912 } 913 enableFallbackRetryTimerCheckOnInitialPdnFail( int transportType, int fallbackRetryTimer)914 private void enableFallbackRetryTimerCheckOnInitialPdnFail( 915 int transportType, int fallbackRetryTimer) { 916 Log.d( 917 mLogTag, 918 "Start Initial Data Connection fail retry_timer On TransportType" 919 + fallbackRetryTimer 920 + "_" 921 + QnsConstants.transportTypeToString(transportType)); 922 if (fallbackRetryTimer > 0 && !mIsTimerRunningOnDataConnectionFail) { 923 Message msg = 924 mHandler.obtainMessage( 925 EVENT_INITIAL_DATA_CONNECTION_FAIL_RETRY_TIMER_EXPIRED, 926 transportType, 927 0, 928 null); 929 mFallbackTimerId = mQnsTimer.registerTimer(msg, fallbackRetryTimer); 930 mIsTimerRunningOnDataConnectionFail = true; 931 } 932 } 933 enableFallbackRetryCountCheckOnInitialPdnFail( int transportType, int fallbackRetryCount)934 private void enableFallbackRetryCountCheckOnInitialPdnFail( 935 int transportType, int fallbackRetryCount) { 936 Log.d( 937 mLogTag, 938 "Start Initial Data Connection fail retry_count On TransportType" 939 + fallbackRetryCount 940 + "_" 941 + mRetryCounterOnDataConnectionFail 942 + "_" 943 + QnsConstants.transportTypeToString(transportType)); 944 if (fallbackRetryCount > 0) { 945 if (mRetryCounterOnDataConnectionFail == fallbackRetryCount) { 946 fallbackToOtherTransportOnDataConnectionFail(transportType); 947 } else { 948 mRetryCounterOnDataConnectionFail += 1; 949 } 950 } 951 } 952 fallbackToOtherTransportOnDataConnectionFail(int currTransportType)953 private void fallbackToOtherTransportOnDataConnectionFail(int currTransportType) { 954 955 checkToCancelInitialPdnConnectionFailFallback(); 956 957 addRestriction( 958 currTransportType, 959 RESTRICT_TYPE_FALLBACK_ON_DATA_CONNECTION_FAIL, 960 sReleaseEventMap.get(RESTRICT_TYPE_FALLBACK_ON_DATA_CONNECTION_FAIL), 961 mQnsCarrierConfigManager.getFallbackGuardTimerOnInitialConnectionFail( 962 mNetCapability)); 963 } 964 965 @VisibleForTesting onImsRegistrationStateChanged(QnsImsManager.ImsRegistrationState event)966 void onImsRegistrationStateChanged(QnsImsManager.ImsRegistrationState event) { 967 Log.d( 968 mLogTag, 969 "onImsRegistrationStateChanged[" 970 + QnsConstants.transportTypeToString(mTransportType) 971 + "] transportType[" 972 + QnsConstants.transportTypeToString(event.getTransportType()) 973 + "] RegistrationState[" 974 + QnsConstants.imsRegistrationEventToString(event.getEvent()) 975 + "]"); 976 int prefMode = 977 mCellularCoverage == QnsConstants.COVERAGE_HOME 978 ? mWfcPreference 979 : mWfcRoamingPreference; 980 981 registerRttStatusCheckEvent(); 982 983 switch (event.getEvent()) { 984 case QnsConstants.IMS_REGISTRATION_CHANGED_UNREGISTERED: 985 onImsUnregistered(event, mTransportType, prefMode); 986 break; 987 case QnsConstants.IMS_REGISTRATION_CHANGED_ACCESS_NETWORK_CHANGE_FAILED: 988 onImsHoRegisterFailed(event, mTransportType, prefMode); 989 break; 990 case QnsConstants.IMS_REGISTRATION_CHANGED_REGISTERED: 991 Log.d( 992 mLogTag, 993 "On Ims Registered: " 994 + QnsConstants.transportTypeToString(event.getTransportType())); 995 if (event.getTransportType() == AccessNetworkConstants.TRANSPORT_TYPE_WLAN 996 && hasRestrictionType( 997 AccessNetworkConstants.TRANSPORT_TYPE_WLAN, 998 RESTRICT_TYPE_FALLBACK_TO_WWAN_IMS_REGI_FAIL)) { 999 releaseRestriction( 1000 AccessNetworkConstants.TRANSPORT_TYPE_WLAN, 1001 RESTRICT_TYPE_FALLBACK_TO_WWAN_IMS_REGI_FAIL); 1002 } 1003 break; 1004 default: 1005 break; 1006 } 1007 } 1008 registerRttStatusCheckEvent()1009 private void registerRttStatusCheckEvent() { 1010 if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS) { 1011 1012 if (mWifiBackhaulMonitor.isRttCheckEnabled()) { 1013 if (!mIsRttStatusCheckRegistered) { 1014 mIsRttStatusCheckRegistered = true; 1015 mWifiBackhaulMonitor.registerForRttStatusChange( 1016 mHandler, EVENT_WIFI_RTT_BACKHAUL_CHECK_STATUS); 1017 } 1018 } else { 1019 if (mIsRttStatusCheckRegistered) { 1020 mIsRttStatusCheckRegistered = false; 1021 mWifiBackhaulMonitor.unRegisterForRttStatusChange(mHandler); 1022 } 1023 } 1024 } 1025 } 1026 onImsUnregistered( QnsImsManager.ImsRegistrationState event, int transportType, int prefMode)1027 private void onImsUnregistered( 1028 QnsImsManager.ImsRegistrationState event, int transportType, int prefMode) { 1029 if (transportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) { 1030 int fallbackTimeMillis = 1031 mQnsCarrierConfigManager.getFallbackTimeImsUnregistered( 1032 event.getReasonInfo().getCode(), prefMode); 1033 if (fallbackTimeMillis > 0 1034 && mQnsCarrierConfigManager.isAccessNetworkAllowed( 1035 mCellularAccessNetwork, NetworkCapabilities.NET_CAPABILITY_IMS)) { 1036 fallbackToWwanForImsRegistration(fallbackTimeMillis); 1037 } 1038 } 1039 } 1040 onImsHoRegisterFailed( QnsImsManager.ImsRegistrationState event, int transportType, int prefMode)1041 private void onImsHoRegisterFailed( 1042 QnsImsManager.ImsRegistrationState event, int transportType, int prefMode) { 1043 if (transportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN 1044 && transportType == event.getTransportType()) { 1045 int fallbackTimeMillis = 1046 mQnsCarrierConfigManager.getFallbackTimeImsHoRegisterFailed( 1047 event.getReasonInfo().getCode(), prefMode); 1048 if (fallbackTimeMillis > 0 1049 && mQnsCarrierConfigManager.isAccessNetworkAllowed( 1050 mCellularAccessNetwork, NetworkCapabilities.NET_CAPABILITY_IMS)) { 1051 fallbackToWwanForImsRegistration(fallbackTimeMillis); 1052 } 1053 } 1054 } 1055 onWlanRttFail()1056 protected void onWlanRttFail() { 1057 Log.d(mLogTag, "start RTT Fallback:"); 1058 int fallbackTimeMillis = mQnsCarrierConfigManager.getWlanRttFallbackHystTimer(); 1059 if (fallbackTimeMillis > 0 1060 && mQnsCarrierConfigManager.isAccessNetworkAllowed( 1061 mCellularAccessNetwork, NetworkCapabilities.NET_CAPABILITY_IMS)) { 1062 1063 fallbackToWwanForImsRegistration( 1064 AccessNetworkConstants.TRANSPORT_TYPE_WLAN, 1065 RESTRICT_TYPE_FALLBACK_TO_WWAN_RTT_BACKHAUL_FAIL, 1066 fallbackTimeMillis); 1067 } 1068 } 1069 fallbackToWwanForImsRegistration(int fallbackTimeMillis)1070 private void fallbackToWwanForImsRegistration(int fallbackTimeMillis) { 1071 fallbackToWwanForImsRegistration( 1072 AccessNetworkConstants.TRANSPORT_TYPE_WLAN, 1073 RESTRICT_TYPE_FALLBACK_TO_WWAN_IMS_REGI_FAIL, 1074 fallbackTimeMillis); 1075 } 1076 fallbackToWwanForImsRegistration( int transportType, int restrictType, int fallbackTimeMillis)1077 private void fallbackToWwanForImsRegistration( 1078 int transportType, int restrictType, int fallbackTimeMillis) { 1079 Log.d(mLogTag, "release ignorable restrictions on WWAN to fallback."); 1080 for (int restriction : ignorableRestrictionsOnSingleRat) { 1081 releaseRestriction(QnsUtils.getOtherTransportType(transportType), restriction, false); 1082 } 1083 addRestriction( 1084 transportType, 1085 restrictType, 1086 sReleaseEventMap.get(restrictType), 1087 fallbackTimeMillis); 1088 } 1089 1090 /** Update Last notified transport type from ANE which owns this RestrictManager */ updateLastNotifiedTransportType(@ccessNetworkConstants.TransportType int transportType)1091 void updateLastNotifiedTransportType(@AccessNetworkConstants.TransportType int transportType) { 1092 if (mDebugFlag) { 1093 Log.d( 1094 mLogTag, 1095 "updateLastEvaluatedTransportType: " 1096 + QnsConstants.transportTypeToString(transportType)); 1097 } 1098 mLastEvaluatedTransportType = transportType; 1099 if (mDataConnectionStatusTracker.isActiveState() && mTransportType != transportType) { 1100 startGuarding(GUARDING_TIMER_HANDOVER_INIT, 1101 QnsUtils.getOtherTransportType(transportType)); 1102 } 1103 } 1104 1105 @VisibleForTesting setCellularCoverage(@nsConstants.CellularCoverage int coverage)1106 void setCellularCoverage(@QnsConstants.CellularCoverage int coverage) { 1107 Log.d(mLogTag, "setCellularCoverage:" + QnsConstants.coverageToString(coverage)); 1108 mCellularCoverage = coverage; 1109 checkIfCancelNonPreferredRestriction(getPreferredTransportType()); 1110 } 1111 setQnsCallType(@nsConstants.QnsCallType int callType)1112 protected void setQnsCallType(@QnsConstants.QnsCallType int callType) { 1113 if (callType != mImsCallType) { 1114 updateGuardingTimerConditionOnCallState(mImsCallType, callType); 1115 } 1116 1117 mImsCallType = callType; 1118 1119 Log.d(mLogTag, "setQnsCallType: " + QnsConstants.callTypeToString(callType)); 1120 if (callType == QnsConstants.CALL_TYPE_IDLE) { 1121 Log.d(mLogTag, "Call end. init mCounterForIwlanRestrictionInCall"); 1122 mCounterForIwlanRestrictionInCall = 0; 1123 1124 processReleaseEvent(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, RELEASE_EVENT_CALL_END); 1125 processReleaseEvent(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, RELEASE_EVENT_CALL_END); 1126 unregisterLowRtpQualityEvent(); 1127 } else { 1128 registerLowRtpQualityEvent(); 1129 } 1130 } 1131 updateGuardingTimerConditionOnCallState(int prevCallType, int newCallType)1132 private void updateGuardingTimerConditionOnCallState(int prevCallType, int newCallType) { 1133 int currGuardingTransport = QnsUtils.getOtherTransportType(mTransportType); 1134 if (mRestrictInfos.get(currGuardingTransport) == null) return; 1135 1136 HashMap<Integer, Restriction> restrictionMap = 1137 mRestrictInfos.get(currGuardingTransport).getRestrictionMap(); 1138 Restriction restriction = restrictionMap.get(RESTRICT_TYPE_GUARDING); 1139 1140 if (restriction != null) { 1141 int prevCallTypeMillis = getGuardingTimeMillis(currGuardingTransport, prevCallType); 1142 if (prevCallTypeMillis == 0) { 1143 return; // We don't need to update minimum guarding timer. 1144 } 1145 int newCallTypeMillis = 1146 getGuardingTimeMillis( 1147 currGuardingTransport, newCallType); // new Call type timer 1148 if (newCallTypeMillis == prevCallTypeMillis) return; 1149 1150 if (newCallTypeMillis != 0) { 1151 // remaining time on current call type 1152 long prevCallTypeRemainingMillis = 1153 restriction.mReleaseTime - SystemClock.elapsedRealtime(); 1154 int guardTimerElapsed = prevCallTypeMillis - (int) prevCallTypeRemainingMillis; 1155 int newGuardTimer = newCallTypeMillis - guardTimerElapsed; 1156 1157 if (mDebugFlag) { 1158 Log.d( 1159 mLogTag, 1160 "Prev Call Type Guarding millis:" 1161 + prevCallTypeMillis 1162 + "Prev Call type remaining millis:" 1163 + prevCallTypeRemainingMillis 1164 + "New Call type Guarding millis:" 1165 + newCallTypeMillis 1166 + "Guard timer Elapsed:" 1167 + guardTimerElapsed 1168 + "New Guard timer to set:" 1169 + newGuardTimer); 1170 } 1171 if (newGuardTimer > 0) { 1172 startGuarding(newGuardTimer, currGuardingTransport); 1173 return; 1174 } 1175 } 1176 cancelGuarding(currGuardingTransport); 1177 } 1178 } 1179 1180 @VisibleForTesting setCellularAccessNetwork(int accessNetwork)1181 void setCellularAccessNetwork(int accessNetwork) { 1182 mCellularAccessNetwork = accessNetwork; 1183 Log.d(mLogTag, "Current Cellular Network:" + mCellularAccessNetwork); 1184 if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS 1185 && !mQnsCarrierConfigManager.isAccessNetworkAllowed( 1186 accessNetwork, mNetCapability)) { 1187 processReleaseEvent( 1188 AccessNetworkConstants.TRANSPORT_TYPE_WLAN, RELEASE_EVENT_IMS_NOT_SUPPORT_RAT); 1189 } 1190 } 1191 addRestriction(int transport, Restriction restrictObj, long timeMillis)1192 void addRestriction(int transport, Restriction restrictObj, long timeMillis) { 1193 boolean needNotify = false; 1194 HashMap<Integer, Restriction> restrictionMap = 1195 mRestrictInfos.get(transport).getRestrictionMap(); 1196 Restriction restriction = restrictionMap.get(restrictObj.mRestrictType); 1197 Log.d( 1198 mLogTag, 1199 "addRestriction[" 1200 + QnsConstants.transportTypeToString(transport) 1201 + "] " 1202 + restrictTypeToString(restrictObj.mRestrictType) 1203 + " was restrict:" 1204 + (restriction != null) 1205 + " timeMillis:" + timeMillis); 1206 if (restriction == null) { 1207 restriction = restrictObj; 1208 restrictionMap.put(restrictObj.mRestrictType, restriction); 1209 Log.d( 1210 mLogTag, 1211 "addRestriction[" 1212 + QnsConstants.transportTypeToString(transport) 1213 + "] " 1214 + restriction); 1215 needNotify = true; 1216 } else { 1217 if (timeMillis > 0) { 1218 restriction.updateRestrictTime(timeMillis); 1219 removeReleaseRestrictionMessage(restriction); 1220 } 1221 Log.d( 1222 mLogTag, 1223 "updateRestriction[" 1224 + QnsConstants.transportTypeToString(transport) 1225 + "] " 1226 + restriction); 1227 } 1228 if (timeMillis > 0) { 1229 sendReleaseRestrictionMessage(transport, restriction); 1230 } 1231 if (needNotify) { 1232 notifyRestrictInfoChanged(); 1233 } 1234 } 1235 addRestriction(int transport, int type, int[] releaseEvents, long timeMillis)1236 void addRestriction(int transport, int type, int[] releaseEvents, long timeMillis) { 1237 boolean needNotify = false; 1238 HashMap<Integer, Restriction> restrictionMap = 1239 mRestrictInfos.get(transport).getRestrictionMap(); 1240 Restriction restriction = restrictionMap.get(type); 1241 Log.d( 1242 mLogTag, 1243 "addRestriction[" 1244 + QnsConstants.transportTypeToString(transport) 1245 + "] " 1246 + restrictTypeToString(type) 1247 + " was restrict:" 1248 + (restriction != null) 1249 + " timeMillis:" + timeMillis); 1250 if (restriction == null) { 1251 restriction = new Restriction(type, releaseEvents, timeMillis); 1252 restrictionMap.put(type, restriction); 1253 Log.d( 1254 mLogTag, 1255 "addRestriction[" 1256 + QnsConstants.transportTypeToString(transport) 1257 + "] " 1258 + restriction); 1259 needNotify = true; 1260 } else { 1261 if (timeMillis > 0) { 1262 restriction.updateRestrictTime(timeMillis); 1263 removeReleaseRestrictionMessage(restriction); 1264 } 1265 Log.d( 1266 mLogTag, 1267 "updateRestriction[" 1268 + QnsConstants.transportTypeToString(transport) 1269 + "] " 1270 + restriction); 1271 } 1272 if (timeMillis > 0) { 1273 sendReleaseRestrictionMessage(transport, restriction); 1274 } 1275 if (needNotify) { 1276 notifyRestrictInfoChanged(); 1277 } 1278 } 1279 releaseRestriction(int transport, int type)1280 void releaseRestriction(int transport, int type) { 1281 releaseRestriction(transport, type, false); 1282 } 1283 releaseRestriction(int transport, int type, boolean skipNotify)1284 void releaseRestriction(int transport, int type, boolean skipNotify) { 1285 boolean needNotify = false; 1286 HashMap<Integer, Restriction> restrictionMap = 1287 mRestrictInfos.get(transport).getRestrictionMap(); 1288 Restriction restriction = restrictionMap.get(type); 1289 Log.d( 1290 mLogTag, 1291 "releaseRestriction[" 1292 + QnsConstants.transportTypeToString(transport) 1293 + "] " 1294 + restrictTypeToString(type) 1295 + " was restrict:" 1296 + (restriction != null)); 1297 if (restriction == null) { 1298 Log.d(mLogTag, "no restriction to release " + restrictTypeToString(type) + " " + type); 1299 } else { 1300 if (restriction.mReleaseTime > 0) { 1301 removeReleaseRestrictionMessage(restriction); 1302 } 1303 restrictionMap.remove(restriction.mRestrictType); 1304 mRestrictionTimers.remove(restriction); 1305 needNotify = true; 1306 } 1307 if (needNotify && !skipNotify) { 1308 notifyRestrictInfoChanged(); 1309 } 1310 } 1311 processReleaseEvent(int transportType, int event)1312 void processReleaseEvent(int transportType, int event) { 1313 ArrayList<Integer> releaseList = new ArrayList<>(); 1314 HashMap<Integer, Restriction> restrictMap = 1315 mRestrictInfos.get(transportType).getRestrictionMap(); 1316 Log.d( 1317 mLogTag, 1318 "processReleaseEvent[" 1319 + QnsConstants.transportTypeToString(transportType) 1320 + "] " 1321 + event); 1322 1323 for (Integer restrictType : restrictMap.keySet()) { 1324 if (restrictMap.get(restrictType).needRelease(event)) { 1325 releaseList.add(restrictType); 1326 } 1327 } 1328 for (Integer restrictType : releaseList) { 1329 releaseRestriction(transportType, restrictType); 1330 } 1331 } 1332 sendReleaseRestrictionMessage(int transportType, Restriction restriction)1333 private void sendReleaseRestrictionMessage(int transportType, Restriction restriction) { 1334 if (restriction == null) { 1335 Log.e(mLogTag, "sendReleaseRestrictionMessage restriction is null"); 1336 return; 1337 } 1338 Message msg = 1339 mHandler.obtainMessage(EVENT_RELEASE_RESTRICTION, transportType, 0, restriction); 1340 long delayInMillis = restriction.mReleaseTime - SystemClock.elapsedRealtime(); 1341 int timerId = mQnsTimer.registerTimer(msg, delayInMillis); 1342 mRestrictionTimers.put(restriction, timerId); 1343 Log.d( 1344 mLogTag, 1345 restrictTypeToString(restriction.mRestrictType) 1346 + " will be released after " 1347 + delayInMillis 1348 + " millisecs"); 1349 } 1350 removeReleaseRestrictionMessage(Restriction restriction)1351 private void removeReleaseRestrictionMessage(Restriction restriction) { 1352 if (restriction == null) { 1353 Log.e(mLogTag, "removeReleaseRestrictionMessage restriction is null"); 1354 return; 1355 } 1356 mQnsTimer.unregisterTimer(mRestrictionTimers.getOrDefault(restriction, INVALID_ID)); 1357 mRestrictionTimers.remove(restriction); 1358 } 1359 registerRestrictInfoChanged(Handler h, int what)1360 void registerRestrictInfoChanged(Handler h, int what) { 1361 mRestrictInfoRegistrant = new QnsRegistrant(h, what, null); 1362 } 1363 unRegisterRestrictInfoChanged(Handler h)1364 void unRegisterRestrictInfoChanged(Handler h) { 1365 mRestrictInfoRegistrant = null; 1366 } 1367 1368 @VisibleForTesting isRestricted(int transportType)1369 boolean isRestricted(int transportType) { 1370 if (mRestrictInfos.isEmpty()) return false; 1371 1372 if (mRestrictInfos.get(transportType) != null) { 1373 return mRestrictInfos.get(transportType).isRestricted(); 1374 } 1375 1376 return false; 1377 } 1378 isRestrictedExceptGuarding(int transportType)1379 boolean isRestrictedExceptGuarding(int transportType) { 1380 try { 1381 RestrictInfo info = mRestrictInfos.get(transportType); 1382 int size = info.getRestrictionMap().size(); 1383 if (info.hasRestrictionType(RESTRICT_TYPE_GUARDING)) { 1384 size--; 1385 } 1386 return size > 0; 1387 } catch (Exception e) { 1388 } 1389 return false; 1390 } 1391 1392 @VisibleForTesting hasRestrictionType(int transportType, int restrictType)1393 boolean hasRestrictionType(int transportType, int restrictType) { 1394 try { 1395 if (mRestrictInfos != null) { 1396 return mRestrictInfos.get(transportType).hasRestrictionType(restrictType); 1397 } 1398 } catch (Exception e) { 1399 1400 } 1401 return false; 1402 } 1403 1404 /** This method is only for Testing */ 1405 @VisibleForTesting getRemainingGuardTimer(int transportType)1406 protected long getRemainingGuardTimer(int transportType) { 1407 return mRestrictInfos 1408 .get(transportType) 1409 .getRestrictionMap() 1410 .get(RESTRICT_TYPE_GUARDING) 1411 .mReleaseTime 1412 - SystemClock.elapsedRealtime(); 1413 } 1414 1415 @VisibleForTesting isAllowedOnSingleTransport(int transportType)1416 boolean isAllowedOnSingleTransport(int transportType) { 1417 if (mRestrictInfos.isEmpty()) return false; 1418 Log.d( 1419 mLogTag, 1420 "isAllowedOnSingleTransport (" 1421 + QnsConstants.transportTypeToString(transportType) 1422 + ") restriction :" 1423 + mRestrictInfos.get(transportType).toString()); 1424 int countIgnorableRestriction = 0; 1425 for (int restrictType : ignorableRestrictionsOnSingleRat) { 1426 if (mRestrictInfos.get(transportType).hasRestrictionType(restrictType)) { 1427 countIgnorableRestriction++; 1428 } 1429 } 1430 if (mRestrictInfos.get(transportType).getRestrictionMap().size() 1431 == countIgnorableRestriction) { 1432 return true; 1433 } 1434 return false; 1435 } 1436 increaseCounterToRestrictIwlanInCall()1437 void increaseCounterToRestrictIwlanInCall() { 1438 mCounterForIwlanRestrictionInCall += 1; 1439 int maxAllowedRoveOutByLowRtpQuality = 1440 mQnsCarrierConfigManager.getQnsMaxIwlanHoCountDuringCall(); 1441 if (maxAllowedRoveOutByLowRtpQuality > 0 1442 && mCounterForIwlanRestrictionInCall == maxAllowedRoveOutByLowRtpQuality) { 1443 Log.d(mLogTag, "reached maxAllowedRoveOutByLowRtpQuality"); 1444 addRestriction( 1445 AccessNetworkConstants.TRANSPORT_TYPE_WLAN, 1446 RESTRICT_TYPE_RESTRICT_IWLAN_IN_CALL, 1447 sReleaseEventMap.get(RESTRICT_TYPE_RESTRICT_IWLAN_IN_CALL), 1448 0); 1449 } 1450 } 1451 notifyRestrictInfoChanged()1452 private void notifyRestrictInfoChanged() { 1453 Log.d(mLogTag, "notifyRestrictInfoChanged"); 1454 if (mRestrictInfoRegistrant != null) { 1455 mRestrictInfoRegistrant.notifyResult(mRestrictInfos); 1456 1457 // metrics 1458 sendRestrictionsForMetrics(); 1459 } else { 1460 Log.d(mLogTag, "notifyRestrictInfoChanged. no Registrant."); 1461 } 1462 } 1463 registerLowRtpQualityEvent()1464 private void registerLowRtpQualityEvent() { 1465 if ((mImsCallType == QnsConstants.CALL_TYPE_VOICE 1466 || mImsCallType == QnsConstants.CALL_TYPE_EMERGENCY) 1467 && (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN 1468 || mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 1469 && mActiveCallTracker != null) { 1470 int hoRestrictTimeOnLowRtpQuality = 1471 mQnsCarrierConfigManager.getHoRestrictedTimeOnLowRTPQuality(mTransportType); 1472 if (hoRestrictTimeOnLowRtpQuality > 0) { 1473 Log.d(mLogTag, "registerLowRtpQualityEvent"); 1474 mActiveCallTracker.registerLowMediaQualityListener( 1475 mHandler, EVENT_LOW_RTP_QUALITY_REPORTED, null); 1476 } 1477 } 1478 } 1479 unregisterLowRtpQualityEvent()1480 private void unregisterLowRtpQualityEvent() { 1481 if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS 1482 || mNetCapability == NetworkCapabilities.NET_CAPABILITY_EIMS) { 1483 if (mActiveCallTracker != null) { 1484 mActiveCallTracker.unregisterLowMediaQualityListener(mHandler); 1485 } 1486 } 1487 } 1488 getGuardingTimeMillis(int transportType, int callType)1489 private int getGuardingTimeMillis(int transportType, int callType) { 1490 int delayMillis; 1491 switch (mNetCapability) { 1492 case NetworkCapabilities.NET_CAPABILITY_IMS: 1493 case NetworkCapabilities.NET_CAPABILITY_EIMS: 1494 if (!mQnsCarrierConfigManager.isHysteresisTimerEnabled(mCellularCoverage)) { 1495 Log.d( 1496 mLogTag, 1497 "getGuardingTimeMillis: handover guarding timer is not enabled at " 1498 + QnsConstants.coverageToString(mCellularCoverage)); 1499 return 0; 1500 } 1501 if (transportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) { 1502 delayMillis = 1503 mQnsCarrierConfigManager.getWwanHysteresisTimer( 1504 mNetCapability, callType); 1505 } else { 1506 delayMillis = 1507 mQnsCarrierConfigManager.getWlanHysteresisTimer( 1508 mNetCapability, callType); 1509 } 1510 if (delayMillis > 0 1511 && mQnsCarrierConfigManager.isGuardTimerHysteresisOnPrefSupported()) { 1512 int preference = mWfcPreference; 1513 if (mCellularCoverage == QnsConstants.COVERAGE_ROAM) { 1514 preference = mWfcRoamingPreference; 1515 } 1516 if (preference == QnsConstants.CELL_PREF 1517 && transportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) { 1518 Log.d( 1519 mLogTag, 1520 "getGuardingTimeMillis: cellular preferred case, don't guard" 1521 + " handover to WLAN"); 1522 delayMillis = 0; 1523 } else if (preference == QnsConstants.WIFI_PREF 1524 && transportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) { 1525 Log.d( 1526 mLogTag, 1527 "getGuardingTimeMillis: wifi preferred case, don't guard handover" 1528 + " to WWAN"); 1529 delayMillis = 0; 1530 } 1531 } 1532 break; 1533 case NetworkCapabilities.NET_CAPABILITY_MMS: 1534 case NetworkCapabilities.NET_CAPABILITY_XCAP: 1535 case NetworkCapabilities.NET_CAPABILITY_CBS: 1536 callType = mQnsCallStatusTracker.isCallIdle() ? QnsConstants.CALL_TYPE_IDLE 1537 : QnsConstants.CALL_TYPE_VOICE; 1538 if (transportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) { 1539 delayMillis = 1540 mQnsCarrierConfigManager.getWwanHysteresisTimer( 1541 mNetCapability, callType); 1542 } else if (transportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) { 1543 delayMillis = 1544 mQnsCarrierConfigManager.getWlanHysteresisTimer( 1545 mNetCapability, callType); 1546 } else { 1547 delayMillis = 0; 1548 } 1549 break; 1550 default: 1551 delayMillis = 0; 1552 break; 1553 } 1554 Log.d( 1555 mLogTag, 1556 "getGuardingTimeMillis: timer = " 1557 + delayMillis 1558 + " for transport type = " 1559 + QnsConstants.transportTypeToString(transportType) 1560 + " in " 1561 + QnsConstants.callTypeToString(callType) 1562 + " state."); 1563 1564 return delayMillis; 1565 } 1566 1567 @VisibleForTesting startGuarding(int delay, int transportType)1568 void startGuarding(int delay, int transportType) { 1569 // It is invalid to run to RESTRICT_TYPE_GUARDING for both Transport at same time 1570 // Make sure to release source TransportType Guarding before starting guarding for New 1571 // Transport 1572 // Type 1573 if (transportType != AccessNetworkConstants.TRANSPORT_TYPE_INVALID 1574 && hasRestrictionType(QnsUtils.getOtherTransportType(transportType), 1575 RestrictManager.RESTRICT_TYPE_GUARDING)) { 1576 Log.d( 1577 mLogTag, 1578 "RESTRICT_TYPE_GUARDING cleared from Guarding for:" 1579 + QnsConstants.transportTypeToString(mTransportType)); 1580 // addRestriction() will take care to notify the ANE of Restrict Info status 1581 releaseRestriction( 1582 QnsUtils.getOtherTransportType(transportType), RESTRICT_TYPE_GUARDING, true); 1583 } 1584 1585 addRestriction( 1586 transportType, 1587 RESTRICT_TYPE_GUARDING, 1588 sReleaseEventMap.get(RESTRICT_TYPE_GUARDING), 1589 delay); 1590 } 1591 cancelGuarding(int transportType)1592 private void cancelGuarding(int transportType) { 1593 releaseRestriction(transportType, RESTRICT_TYPE_GUARDING); 1594 } 1595 notifyThrottling(boolean throttle, long throttleTime, int transportType)1596 protected void notifyThrottling(boolean throttle, long throttleTime, int transportType) { 1597 Log.d( 1598 mLogTag, 1599 "notifyThrottling throttle:" 1600 + throttle 1601 + " throttleTime:" 1602 + throttleTime 1603 + " transportType:" 1604 + QnsConstants.transportTypeToString(transportType)); 1605 if (throttle) { 1606 if (throttleTime < 0) { 1607 //FWK send minus value of throttle expiration time, consider anomaly report at here. 1608 return; 1609 } 1610 long delayMillis = throttleTime - SystemClock.elapsedRealtime(); 1611 if (delayMillis > 0) { 1612 if (mDataConnectionStatusTracker.isActiveState()) { 1613 Log.d( 1614 mLogTag, 1615 "Defer Throttling event during active state transportType:" 1616 + transportType 1617 + " ThrottleTime:" 1618 + throttleTime); 1619 mDeferredThrottlingEvent = new Pair<>(transportType, throttleTime); 1620 } else { 1621 if (throttleTime == Long.MAX_VALUE || throttleTime == Integer.MAX_VALUE) { 1622 //Keep throttle status until receiving un-throttle event. 1623 delayMillis = 0; 1624 } 1625 addRestriction( 1626 transportType, 1627 RESTRICT_TYPE_THROTTLING, 1628 sReleaseEventMap.get(RESTRICT_TYPE_THROTTLING), 1629 delayMillis); 1630 } 1631 } 1632 } else { 1633 releaseRestriction(transportType, RESTRICT_TYPE_THROTTLING); 1634 if (mDeferredThrottlingEvent != null) mDeferredThrottlingEvent = null; 1635 } 1636 } 1637 restrictTypeToString(int restrictType)1638 static String restrictTypeToString(int restrictType) { 1639 switch (restrictType) { 1640 case RESTRICT_TYPE_GUARDING: 1641 return "RESTRICT_TYPE_GUARDING"; 1642 case RESTRICT_TYPE_THROTTLING: 1643 return "RESTRICT_TYPE_THROTTLING"; 1644 case RESTRICT_TYPE_HO_NOT_ALLOWED: 1645 return "RESTRICT_TYPE_HO_NOT_ALLOWED"; 1646 case RESTRICT_TYPE_NON_PREFERRED_TRANSPORT: 1647 return "RESTRICT_TYPE_NON_PREFERRED_TRANSPORT"; 1648 case RESTRICT_TYPE_RTP_LOW_QUALITY: 1649 return "RESTRICT_TYPE_RTP_LOW_QUALITY"; 1650 case RESTRICT_TYPE_RESTRICT_IWLAN_IN_CALL: 1651 return "RESTRICT_TYPE_RESTRICT_IWLAN_IN_CALL"; 1652 case RESTRICT_TYPE_RESTRICT_IWLAN_CS_CALL: 1653 return "RESTRICT_TYPE_RESTRICT_IWLAN_CS_CALL"; 1654 case RESTRICT_TYPE_FALLBACK_TO_WWAN_IMS_REGI_FAIL: 1655 return "RESTRICT_TYPE_FALLBACK_TO_WWAN_IMS_REGI_FAIL"; 1656 case RESTRICT_TYPE_FALLBACK_ON_DATA_CONNECTION_FAIL: 1657 return "RESTRICT_TYPE_FALLBACK_ON_DATA_CONNECTION_FAIL"; 1658 case RESTRICT_TYPE_FALLBACK_TO_WWAN_RTT_BACKHAUL_FAIL: 1659 return "RESTRICT_TYPE_FALLBACK_TO_WWAN_RTT_BACKHAUL_FAIL"; 1660 } 1661 return ""; 1662 } 1663 1664 /** 1665 * Dumps the state of {@link QualityMonitor} 1666 * 1667 * @param pw {@link PrintWriter} to write the state of the object. 1668 * @param prefix String to append at start of dumped log. 1669 */ dump(PrintWriter pw, String prefix)1670 void dump(PrintWriter pw, String prefix) { 1671 pw.println(prefix + "------------------------------"); 1672 pw.println( 1673 prefix 1674 + "RestrictManager[" 1675 + QnsUtils.getNameOfNetCapability(mNetCapability) 1676 + "_" 1677 + mSlotId 1678 + "]:"); 1679 pw.println( 1680 prefix 1681 + "mTransportType=" 1682 + QnsConstants.transportTypeToString(mTransportType) 1683 + ", mLastEvaluatedTransportType=" 1684 + QnsConstants.transportTypeToString(mLastEvaluatedTransportType) 1685 + ", mLastDataConnectionTransportType=" 1686 + QnsConstants.transportTypeToString(mLastDataConnectionTransportType)); 1687 pw.println( 1688 prefix 1689 + "mCounterForIwlanRestrictionInCall=" 1690 + mCounterForIwlanRestrictionInCall 1691 + ", mRetryCounterOnDataConnectionFail=" 1692 + mRetryCounterOnDataConnectionFail 1693 + ", mFallbackCounterOnDataConnectionFail=" 1694 + mFallbackCounterOnDataConnectionFail); 1695 pw.println( 1696 prefix 1697 + "mImsCallType=" 1698 + QnsConstants.callTypeToString(mImsCallType) 1699 + ", mCallState=" 1700 + QnsConstants.callStateToString(mCallState)); 1701 pw.println(prefix + "mRestrictInfos=" + mRestrictInfos); 1702 } 1703 sendRestrictionsForMetrics()1704 private void sendRestrictionsForMetrics() { 1705 if (mNetCapability != NetworkCapabilities.NET_CAPABILITY_IMS) { 1706 return; 1707 } 1708 ArrayList<Integer> wlanRestrictions = 1709 new ArrayList<>( 1710 mRestrictInfos 1711 .get(AccessNetworkConstants.TRANSPORT_TYPE_WLAN) 1712 .getRestrictionMap() 1713 .keySet()); 1714 ArrayList<Integer> wwanRestrictions = 1715 new ArrayList<>( 1716 mRestrictInfos 1717 .get(AccessNetworkConstants.TRANSPORT_TYPE_WLAN) 1718 .getRestrictionMap() 1719 .keySet()); 1720 mQnsMetrics.reportAtomForRestrictions(mNetCapability, mSlotId, 1721 wlanRestrictions, wwanRestrictions, mQnsCarrierConfigManager.getCarrierId()); 1722 } 1723 } 1724