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