1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.content.BroadcastReceiver; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IntentFilter; 25 import android.os.AsyncResult; 26 import android.os.Message; 27 import android.os.PersistableBundle; 28 import android.os.PowerManager; 29 import android.telephony.AccessNetworkConstants; 30 import android.telephony.Annotation; 31 import android.telephony.CarrierConfigManager; 32 import android.telephony.CellInfo; 33 import android.telephony.NetworkRegistrationInfo; 34 import android.telephony.PhysicalChannelConfig; 35 import android.telephony.ServiceState; 36 import android.telephony.TelephonyDisplayInfo; 37 import android.telephony.TelephonyManager; 38 import android.telephony.data.DataCallResponse; 39 import android.telephony.data.DataCallResponse.LinkStatus; 40 import android.text.TextUtils; 41 42 import com.android.internal.telephony.data.DataNetworkController.DataNetworkControllerCallback; 43 import com.android.internal.telephony.data.DataUtils; 44 import com.android.internal.util.IState; 45 import com.android.internal.util.IndentingPrintWriter; 46 import com.android.internal.util.State; 47 import com.android.internal.util.StateMachine; 48 import com.android.telephony.Rlog; 49 50 import java.io.FileDescriptor; 51 import java.io.PrintWriter; 52 import java.util.ArrayList; 53 import java.util.Arrays; 54 import java.util.HashMap; 55 import java.util.HashSet; 56 import java.util.List; 57 import java.util.Locale; 58 import java.util.Map; 59 import java.util.Set; 60 import java.util.regex.Matcher; 61 import java.util.regex.Pattern; 62 import java.util.stream.IntStream; 63 64 /** 65 * The NetworkTypeController evaluates the override network type of {@link TelephonyDisplayInfo} 66 * and sends it to {@link DisplayInfoController}. The override network type can replace the signal 67 * icon displayed on the status bar. It is affected by changes in data RAT, NR state, NR frequency, 68 * data activity, physical channel config, and carrier configurations. Based on carrier configs, 69 * NetworkTypeController also allows timers between various 5G states to prevent flickering. 70 */ 71 public class NetworkTypeController extends StateMachine { 72 private static final boolean DBG = true; 73 private static final String TAG = "NetworkTypeController"; 74 private static final String ICON_5G = "5g"; 75 private static final String ICON_5G_PLUS = "5g_plus"; 76 private static final String STATE_CONNECTED_NR_ADVANCED = "connected_mmwave"; 77 private static final String STATE_CONNECTED = "connected"; 78 private static final String STATE_NOT_RESTRICTED_RRC_IDLE = "not_restricted_rrc_idle"; 79 private static final String STATE_NOT_RESTRICTED_RRC_CON = "not_restricted_rrc_con"; 80 private static final String STATE_RESTRICTED = "restricted"; 81 private static final String STATE_ANY = "any"; 82 private static final String STATE_LEGACY = "legacy"; 83 private static final String[] ALL_STATES = {STATE_CONNECTED_NR_ADVANCED, STATE_CONNECTED, 84 STATE_NOT_RESTRICTED_RRC_IDLE, STATE_NOT_RESTRICTED_RRC_CON, STATE_RESTRICTED, 85 STATE_LEGACY }; 86 87 /** Stop all timers and go to current state. */ 88 public static final int EVENT_UPDATE = 0; 89 /** Quit after processing all existing messages. */ 90 private static final int EVENT_QUIT = 1; 91 /** Initialize all events. */ 92 private static final int EVENT_INITIALIZE = 2; 93 /** Event for service state changed (data rat, bandwidth, NR state, NR frequency, etc). */ 94 private static final int EVENT_SERVICE_STATE_CHANGED = 3; 95 /** Event for physical link status changed. */ 96 private static final int EVENT_PHYSICAL_LINK_STATUS_CHANGED = 4; 97 /** Event for physical channel config indications turned on/off. */ 98 private static final int EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED = 5; 99 /** Event for carrier configs changed. */ 100 private static final int EVENT_CARRIER_CONFIG_CHANGED = 6; 101 /** Event for primary timer expired. If a secondary timer exists, it will begin afterwards. */ 102 private static final int EVENT_PRIMARY_TIMER_EXPIRED = 7; 103 /** Event for secondary timer expired. */ 104 private static final int EVENT_SECONDARY_TIMER_EXPIRED = 8; 105 /** Event for radio off or unavailable. */ 106 private static final int EVENT_RADIO_OFF_OR_UNAVAILABLE = 9; 107 /** Event for preferred network mode changed. */ 108 private static final int EVENT_PREFERRED_NETWORK_MODE_CHANGED = 10; 109 /** Event for physical channel configs changed. */ 110 private static final int EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED = 11; 111 /** Event for device idle mode changed, when device goes to deep sleep and pauses all timers. */ 112 private static final int EVENT_DEVICE_IDLE_MODE_CHANGED = 12; 113 114 private static final String[] sEvents = new String[EVENT_DEVICE_IDLE_MODE_CHANGED + 1]; 115 static { 116 sEvents[EVENT_UPDATE] = "EVENT_UPDATE"; 117 sEvents[EVENT_QUIT] = "EVENT_QUIT"; 118 sEvents[EVENT_SERVICE_STATE_CHANGED] = "EVENT_SERVICE_STATE_CHANGED"; 119 sEvents[EVENT_PHYSICAL_LINK_STATUS_CHANGED] = "EVENT_PHYSICAL_LINK_STATUS_CHANGED"; 120 sEvents[EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED] = 121 "EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED"; 122 sEvents[EVENT_CARRIER_CONFIG_CHANGED] = "EVENT_CARRIER_CONFIG_CHANGED"; 123 sEvents[EVENT_PRIMARY_TIMER_EXPIRED] = "EVENT_PRIMARY_TIMER_EXPIRED"; 124 sEvents[EVENT_SECONDARY_TIMER_EXPIRED] = "EVENT_SECONDARY_TIMER_EXPIRED"; 125 sEvents[EVENT_RADIO_OFF_OR_UNAVAILABLE] = "EVENT_RADIO_OFF_OR_UNAVAILABLE"; 126 sEvents[EVENT_PREFERRED_NETWORK_MODE_CHANGED] = "EVENT_PREFERRED_NETWORK_MODE_CHANGED"; 127 sEvents[EVENT_INITIALIZE] = "EVENT_INITIALIZE"; 128 sEvents[EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED] = "EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED"; 129 sEvents[EVENT_DEVICE_IDLE_MODE_CHANGED] = "EVENT_DEVICE_IDLE_MODE_CHANGED"; 130 } 131 132 @NonNull private final Phone mPhone; 133 @NonNull private final DisplayInfoController mDisplayInfoController; 134 @NonNull private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 135 @Override 136 public void onReceive(Context context, Intent intent) { 137 switch (intent.getAction()) { 138 case PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED: 139 sendMessage(EVENT_DEVICE_IDLE_MODE_CHANGED); 140 break; 141 } 142 } 143 }; 144 145 @NonNull private final CarrierConfigManager.CarrierConfigChangeListener 146 mCarrierConfigChangeListener = 147 new CarrierConfigManager.CarrierConfigChangeListener() { 148 @Override 149 public void onCarrierConfigChanged(int slotIndex, int subId, int carrierId, 150 int specificCarrierId) { 151 // CarrierConfigChangeListener wouldn't send notification on device unlock 152 if (slotIndex == mPhone.getPhoneId()) { 153 sendMessage(EVENT_CARRIER_CONFIG_CHANGED); 154 } 155 } 156 }; 157 158 @NonNull private Map<String, OverrideTimerRule> mOverrideTimerRules = new HashMap<>(); 159 @NonNull private String mLteEnhancedPattern = ""; 160 @Annotation.OverrideNetworkType private int mOverrideNetworkType; 161 private boolean mIsPhysicalChannelConfigOn; 162 private boolean mIsPrimaryTimerActive; 163 private boolean mIsSecondaryTimerActive; 164 private boolean mIsTimerResetEnabledForLegacyStateRrcIdle; 165 private int mLtePlusThresholdBandwidth; 166 private int mNrAdvancedThresholdBandwidth; 167 private boolean mIncludeLteForNrAdvancedThresholdBandwidth; 168 private boolean mRatchetPccFieldsForSameAnchorNrCell; 169 @NonNull private final Set<Integer> mAdditionalNrAdvancedBands = new HashSet<>(); 170 @NonNull private String mPrimaryTimerState; 171 @NonNull private String mSecondaryTimerState; 172 @NonNull private String mPreviousState; 173 @LinkStatus private int mPhysicalLinkStatus; 174 private boolean mIsPhysicalChannelConfig16Supported; 175 private boolean mIsNrAdvancedAllowedByPco = false; 176 private int mNrAdvancedCapablePcoId = 0; 177 private boolean mIsUsingUserDataForRrcDetection = false; 178 private boolean mEnableNrAdvancedWhileRoaming = true; 179 private boolean mIsDeviceIdleMode = false; 180 181 @Nullable private DataNetworkControllerCallback mNrAdvancedCapableByPcoChangedCallback = null; 182 @Nullable private DataNetworkControllerCallback mNrPhysicalLinkStatusChangedCallback = null; 183 184 // Cached copies below to prevent race conditions 185 @NonNull private ServiceState mServiceState; 186 @Nullable private List<PhysicalChannelConfig> mPhysicalChannelConfigs; 187 188 // Ratchet physical channel config fields to prevent 5G/5G+ flickering 189 @NonNull private Set<Integer> mRatchetedNrBands = new HashSet<>(); 190 private int mRatchetedNrBandwidths = 0; 191 private int mLastAnchorNrCellId = PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN; 192 193 /** 194 * NetworkTypeController constructor. 195 * 196 * @param phone Phone object. 197 * @param displayInfoController DisplayInfoController to send override network types to. 198 */ NetworkTypeController(Phone phone, DisplayInfoController displayInfoController)199 public NetworkTypeController(Phone phone, DisplayInfoController displayInfoController) { 200 super(TAG, displayInfoController); 201 mPhone = phone; 202 mDisplayInfoController = displayInfoController; 203 mOverrideNetworkType = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE; 204 mIsPhysicalChannelConfigOn = true; 205 mPrimaryTimerState = ""; 206 mSecondaryTimerState = ""; 207 mPreviousState = ""; 208 DefaultState defaultState = new DefaultState(); 209 addState(defaultState); 210 addState(mLegacyState, defaultState); 211 addState(mIdleState, defaultState); 212 addState(mLteConnectedState, defaultState); 213 addState(mNrConnectedState, defaultState); 214 addState(mNrConnectedAdvancedState, defaultState); 215 setInitialState(defaultState); 216 start(); 217 218 mServiceState = mPhone.getServiceStateTracker().getServiceState(); 219 mPhysicalChannelConfigs = mPhone.getServiceStateTracker().getPhysicalChannelConfigList(); 220 221 sendMessage(EVENT_INITIALIZE); 222 } 223 224 /** 225 * @return The current override network type, used to create TelephonyDisplayInfo in 226 * DisplayInfoController. 227 */ getOverrideNetworkType()228 public @Annotation.OverrideNetworkType int getOverrideNetworkType() { 229 return mOverrideNetworkType; 230 } 231 232 /** 233 * @return The current data network type, used to create TelephonyDisplayInfo in 234 * DisplayInfoController. 235 */ getDataNetworkType()236 public @Annotation.NetworkType int getDataNetworkType() { 237 NetworkRegistrationInfo nri = mServiceState.getNetworkRegistrationInfo( 238 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 239 return nri == null ? TelephonyManager.NETWORK_TYPE_UNKNOWN 240 : nri.getAccessNetworkTechnology(); 241 } 242 243 /** 244 * @return {@code true} if either the primary or secondary 5G icon timers are active, 245 * and {@code false} if neither are. 246 */ areAnyTimersActive()247 public boolean areAnyTimersActive() { 248 return mIsPrimaryTimerActive || mIsSecondaryTimerActive; 249 } 250 registerForAllEvents()251 private void registerForAllEvents() { 252 mPhone.registerForRadioOffOrNotAvailable(getHandler(), 253 EVENT_RADIO_OFF_OR_UNAVAILABLE, null); 254 mPhone.registerForPreferredNetworkTypeChanged(getHandler(), 255 EVENT_PREFERRED_NETWORK_MODE_CHANGED, null); 256 mPhone.registerForPhysicalChannelConfig(getHandler(), 257 EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED, null); 258 mPhone.getServiceStateTracker().registerForServiceStateChanged(getHandler(), 259 EVENT_SERVICE_STATE_CHANGED, null); 260 mIsPhysicalChannelConfig16Supported = mPhone.getContext().getSystemService( 261 TelephonyManager.class).isRadioInterfaceCapabilitySupported( 262 TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED); 263 mPhone.getDeviceStateMonitor().registerForPhysicalChannelConfigNotifChanged(getHandler(), 264 EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED, null); 265 IntentFilter filter = new IntentFilter(); 266 filter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); 267 mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone); 268 CarrierConfigManager ccm = mPhone.getContext().getSystemService(CarrierConfigManager.class); 269 ccm.registerCarrierConfigChangeListener(Runnable::run, mCarrierConfigChangeListener); 270 } 271 unRegisterForAllEvents()272 private void unRegisterForAllEvents() { 273 mPhone.unregisterForRadioOffOrNotAvailable(getHandler()); 274 mPhone.unregisterForPreferredNetworkTypeChanged(getHandler()); 275 mPhone.getServiceStateTracker().unregisterForServiceStateChanged(getHandler()); 276 mPhone.getDeviceStateMonitor().unregisterForPhysicalChannelConfigNotifChanged(getHandler()); 277 mPhone.getContext().unregisterReceiver(mIntentReceiver); 278 CarrierConfigManager ccm = mPhone.getContext().getSystemService(CarrierConfigManager.class); 279 if (mCarrierConfigChangeListener != null) { 280 ccm.unregisterCarrierConfigChangeListener(mCarrierConfigChangeListener); 281 } 282 } 283 parseCarrierConfigs()284 private void parseCarrierConfigs() { 285 PersistableBundle config = CarrierConfigManager.getDefaultConfig(); 286 CarrierConfigManager configManager = 287 mPhone.getContext().getSystemService(CarrierConfigManager.class); 288 if (configManager != null) { 289 PersistableBundle b = configManager.getConfigForSubId(mPhone.getSubId()); 290 if (b != null) { 291 config = b; 292 } 293 } 294 mLteEnhancedPattern = config.getString( 295 CarrierConfigManager.KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING); 296 mIsTimerResetEnabledForLegacyStateRrcIdle = config.getBoolean( 297 CarrierConfigManager.KEY_NR_TIMERS_RESET_IF_NON_ENDC_AND_RRC_IDLE_BOOL); 298 mLtePlusThresholdBandwidth = config.getInt( 299 CarrierConfigManager.KEY_LTE_PLUS_THRESHOLD_BANDWIDTH_KHZ_INT); 300 mNrAdvancedThresholdBandwidth = config.getInt( 301 CarrierConfigManager.KEY_NR_ADVANCED_THRESHOLD_BANDWIDTH_KHZ_INT); 302 mIncludeLteForNrAdvancedThresholdBandwidth = config.getBoolean( 303 CarrierConfigManager.KEY_INCLUDE_LTE_FOR_NR_ADVANCED_THRESHOLD_BANDWIDTH_BOOL); 304 mRatchetPccFieldsForSameAnchorNrCell = config.getBoolean( 305 CarrierConfigManager.KEY_RATCHET_NR_ADVANCED_BANDWIDTH_IF_RRC_IDLE_BOOL); 306 mEnableNrAdvancedWhileRoaming = config.getBoolean( 307 CarrierConfigManager.KEY_ENABLE_NR_ADVANCED_WHILE_ROAMING_BOOL); 308 mAdditionalNrAdvancedBands.clear(); 309 int[] additionalNrAdvancedBands = config.getIntArray( 310 CarrierConfigManager.KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY); 311 if (additionalNrAdvancedBands != null) { 312 Arrays.stream(additionalNrAdvancedBands).forEach(mAdditionalNrAdvancedBands::add); 313 } 314 mNrAdvancedCapablePcoId = config.getInt( 315 CarrierConfigManager.KEY_NR_ADVANCED_CAPABLE_PCO_ID_INT); 316 if (mNrAdvancedCapablePcoId > 0 && mNrAdvancedCapableByPcoChangedCallback == null) { 317 mNrAdvancedCapableByPcoChangedCallback = 318 new DataNetworkControllerCallback(getHandler()::post) { 319 @Override 320 public void onNrAdvancedCapableByPcoChanged(boolean nrAdvancedCapable) { 321 log("mIsNrAdvancedAllowedByPco=" + nrAdvancedCapable); 322 mIsNrAdvancedAllowedByPco = nrAdvancedCapable; 323 sendMessage(EVENT_UPDATE); 324 } 325 }; 326 mPhone.getDataNetworkController().registerDataNetworkControllerCallback( 327 mNrAdvancedCapableByPcoChangedCallback); 328 } else if (mNrAdvancedCapablePcoId == 0 && mNrAdvancedCapableByPcoChangedCallback != null) { 329 mPhone.getDataNetworkController().unregisterDataNetworkControllerCallback( 330 mNrAdvancedCapableByPcoChangedCallback); 331 mNrAdvancedCapableByPcoChangedCallback = null; 332 } 333 mIsUsingUserDataForRrcDetection = config.getBoolean( 334 CarrierConfigManager.KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL); 335 if (!isUsingPhysicalChannelConfigForRrcDetection()) { 336 if (mNrPhysicalLinkStatusChangedCallback == null) { 337 mNrPhysicalLinkStatusChangedCallback = 338 new DataNetworkControllerCallback(getHandler()::post) { 339 @Override 340 public void onPhysicalLinkStatusChanged(@LinkStatus int status) { 341 sendMessage(obtainMessage(EVENT_PHYSICAL_LINK_STATUS_CHANGED, 342 new AsyncResult(null, status, null))); 343 } 344 }; 345 mPhone.getDataNetworkController().registerDataNetworkControllerCallback( 346 mNrPhysicalLinkStatusChangedCallback); 347 } 348 } else if (mNrPhysicalLinkStatusChangedCallback != null) { 349 mPhone.getDataNetworkController().unregisterDataNetworkControllerCallback( 350 mNrPhysicalLinkStatusChangedCallback); 351 mNrPhysicalLinkStatusChangedCallback = null; 352 } 353 String nrIconConfiguration = config.getString( 354 CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING); 355 String overrideTimerRule = config.getString( 356 CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING); 357 String overrideSecondaryTimerRule = config.getString( 358 CarrierConfigManager.KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING); 359 createTimerRules(nrIconConfiguration, overrideTimerRule, overrideSecondaryTimerRule); 360 updatePhysicalChannelConfigs(); 361 } 362 createTimerRules(String icons, String timers, String secondaryTimers)363 private void createTimerRules(String icons, String timers, String secondaryTimers) { 364 Map<String, OverrideTimerRule> tempRules = new HashMap<>(); 365 if (!TextUtils.isEmpty(icons)) { 366 // Format: "STATE:ICON,STATE2:ICON2" 367 for (String pair : icons.trim().split(",")) { 368 String[] kv = (pair.trim().toLowerCase(Locale.ROOT)).split(":"); 369 if (kv.length != 2) { 370 if (DBG) loge("Invalid 5G icon configuration, config = " + pair); 371 continue; 372 } 373 int icon = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE; 374 if (kv[1].equals(ICON_5G)) { 375 icon = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA; 376 } else if (kv[1].equals(ICON_5G_PLUS)) { 377 icon = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED; 378 } else { 379 if (DBG) loge("Invalid 5G icon = " + kv[1]); 380 } 381 tempRules.put(kv[0], new OverrideTimerRule(kv[0], icon)); 382 } 383 } 384 // Ensure all states have an associated OverrideTimerRule and icon 385 for (String state : ALL_STATES) { 386 if (!tempRules.containsKey(state)) { 387 tempRules.put(state, new OverrideTimerRule( 388 state, TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE)); 389 } 390 } 391 392 if (!TextUtils.isEmpty(timers)) { 393 // Format: "FROM_STATE,TO_STATE,DURATION;FROM_STATE_2,TO_STATE_2,DURATION_2" 394 for (String triple : timers.trim().split(";")) { 395 String[] kv = (triple.trim().toLowerCase(Locale.ROOT)).split(","); 396 if (kv.length != 3) { 397 if (DBG) loge("Invalid 5G icon timer configuration, config = " + triple); 398 continue; 399 } 400 int duration; 401 try { 402 duration = Integer.parseInt(kv[2]); 403 } catch (NumberFormatException e) { 404 continue; 405 } 406 if (kv[0].equals(STATE_ANY)) { 407 for (String state : ALL_STATES) { 408 OverrideTimerRule node = tempRules.get(state); 409 node.addTimer(kv[1], duration); 410 } 411 } else { 412 OverrideTimerRule node = tempRules.get(kv[0]); 413 node.addTimer(kv[1], duration); 414 } 415 } 416 } 417 418 if (!TextUtils.isEmpty(secondaryTimers)) { 419 // Format: "PRIMARY_STATE,TO_STATE,DURATION;PRIMARY_STATE_2,TO_STATE_2,DURATION_2" 420 for (String triple : secondaryTimers.trim().split(";")) { 421 String[] kv = (triple.trim().toLowerCase(Locale.ROOT)).split(","); 422 if (kv.length != 3) { 423 if (DBG) { 424 loge("Invalid 5G icon secondary timer configuration, config = " + triple); 425 } 426 continue; 427 } 428 int duration; 429 try { 430 duration = Integer.parseInt(kv[2]); 431 } catch (NumberFormatException e) { 432 continue; 433 } 434 if (kv[0].equals(STATE_ANY)) { 435 for (String state : ALL_STATES) { 436 OverrideTimerRule node = tempRules.get(state); 437 node.addSecondaryTimer(kv[1], duration); 438 } 439 } else { 440 OverrideTimerRule node = tempRules.get(kv[0]); 441 node.addSecondaryTimer(kv[1], duration); 442 } 443 } 444 } 445 446 mOverrideTimerRules = tempRules; 447 if (DBG) log("mOverrideTimerRules: " + mOverrideTimerRules); 448 } 449 updateOverrideNetworkType()450 private void updateOverrideNetworkType() { 451 if (mIsPrimaryTimerActive || mIsSecondaryTimerActive) { 452 if (DBG) log("Skip updating override network type since timer is active."); 453 return; 454 } 455 mOverrideNetworkType = getCurrentOverrideNetworkType(); 456 mDisplayInfoController.updateTelephonyDisplayInfo(); 457 } 458 getCurrentOverrideNetworkType()459 private @Annotation.OverrideNetworkType int getCurrentOverrideNetworkType() { 460 int displayNetworkType = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE; 461 int dataNetworkType = getDataNetworkType(); 462 boolean nrNsa = isLte(dataNetworkType) 463 && mServiceState.getNrState() != NetworkRegistrationInfo.NR_STATE_NONE; 464 boolean nrSa = dataNetworkType == TelephonyManager.NETWORK_TYPE_NR; 465 466 // NR display is not accurate when physical channel config notifications are off 467 if (mIsPhysicalChannelConfigOn && (nrNsa || nrSa)) { 468 // Process NR display network type 469 displayNetworkType = getNrDisplayType(nrSa); 470 if (displayNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE && !nrSa) { 471 // Use LTE values if 5G values aren't defined 472 displayNetworkType = getLteDisplayType(); 473 } 474 } else if (isLte(dataNetworkType)) { 475 // Process LTE display network type 476 displayNetworkType = getLteDisplayType(); 477 } 478 return displayNetworkType; 479 } 480 getNrDisplayType(boolean isNrSa)481 private @Annotation.OverrideNetworkType int getNrDisplayType(boolean isNrSa) { 482 // Don't show 5G icon if preferred network type does not include 5G 483 if ((mPhone.getCachedAllowedNetworkTypesBitmask() 484 & TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) { 485 return TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE; 486 } 487 // Icon display keys in order of priority 488 List<String> keys = new ArrayList<>(); 489 if (isNrSa) { 490 if (isNrAdvanced()) { 491 keys.add(STATE_CONNECTED_NR_ADVANCED); 492 } 493 } else { 494 switch (mServiceState.getNrState()) { 495 case NetworkRegistrationInfo.NR_STATE_CONNECTED: 496 if (isNrAdvanced()) { 497 keys.add(STATE_CONNECTED_NR_ADVANCED); 498 } 499 keys.add(STATE_CONNECTED); 500 break; 501 case NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED: 502 keys.add(isPhysicalLinkActive() ? STATE_NOT_RESTRICTED_RRC_CON 503 : STATE_NOT_RESTRICTED_RRC_IDLE); 504 break; 505 case NetworkRegistrationInfo.NR_STATE_RESTRICTED: 506 keys.add(STATE_RESTRICTED); 507 break; 508 } 509 } 510 511 for (String key : keys) { 512 OverrideTimerRule rule = mOverrideTimerRules.get(key); 513 if (rule != null && rule.mOverrideType 514 != TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) { 515 return rule.mOverrideType; 516 } 517 } 518 return TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE; 519 } 520 getLteDisplayType()521 private @Annotation.OverrideNetworkType int getLteDisplayType() { 522 int value = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE; 523 if ((getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA 524 || mServiceState.isUsingCarrierAggregation()) 525 && IntStream.of(mServiceState.getCellBandwidths()).sum() 526 > mLtePlusThresholdBandwidth) { 527 value = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA; 528 } 529 if (isLteEnhancedAvailable()) { 530 value = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO; 531 } 532 return value; 533 } 534 isLteEnhancedAvailable()535 private boolean isLteEnhancedAvailable() { 536 if (TextUtils.isEmpty(mLteEnhancedPattern)) { 537 return false; 538 } 539 Pattern stringPattern = Pattern.compile(mLteEnhancedPattern); 540 for (String opName : new String[] {mServiceState.getOperatorAlphaLongRaw(), 541 mServiceState.getOperatorAlphaShortRaw()}) { 542 if (!TextUtils.isEmpty(opName)) { 543 Matcher matcher = stringPattern.matcher(opName); 544 if (matcher.find()) { 545 return true; 546 } 547 } 548 } 549 return false; 550 } 551 552 /** 553 * The parent state for all other states. 554 */ 555 private final class DefaultState extends State { 556 @Override processMessage(Message msg)557 public boolean processMessage(Message msg) { 558 if (DBG) log("DefaultState: process " + getEventName(msg.what)); 559 switch (msg.what) { 560 case EVENT_UPDATE: 561 resetAllTimers(); 562 transitionToCurrentState(); 563 break; 564 case EVENT_QUIT: 565 if (DBG) log("Reset timers on state machine quitting."); 566 resetAllTimers(); 567 unRegisterForAllEvents(); 568 quit(); 569 break; 570 case EVENT_INITIALIZE: 571 // The reason that we do it here is that the work below requires other modules 572 // (e.g. DataNetworkController, ServiceStateTracker), which are not created 573 // when NetworkTypeController is created. 574 registerForAllEvents(); 575 parseCarrierConfigs(); 576 break; 577 case EVENT_SERVICE_STATE_CHANGED: 578 mServiceState = mPhone.getServiceStateTracker().getServiceState(); 579 if (DBG) log("ServiceState updated: " + mServiceState); 580 transitionToCurrentState(); 581 break; 582 case EVENT_PHYSICAL_LINK_STATUS_CHANGED: 583 AsyncResult ar = (AsyncResult) msg.obj; 584 mPhysicalLinkStatus = (int) ar.result; 585 break; 586 case EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED: 587 AsyncResult result = (AsyncResult) msg.obj; 588 mIsPhysicalChannelConfigOn = (boolean) result.result; 589 if (DBG) { 590 log("mIsPhysicalChannelConfigOn changed to: " + mIsPhysicalChannelConfigOn); 591 } 592 if (!mIsPhysicalChannelConfigOn) { 593 if (DBG) { 594 log("Reset timers since physical channel config indications are off."); 595 } 596 resetAllTimers(); 597 mRatchetedNrBands.clear(); 598 mRatchetedNrBandwidths = 0; 599 mLastAnchorNrCellId = PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN; 600 } 601 transitionToCurrentState(); 602 break; 603 case EVENT_CARRIER_CONFIG_CHANGED: 604 parseCarrierConfigs(); 605 if (DBG) log("Reset timers since carrier configurations changed."); 606 resetAllTimers(); 607 transitionToCurrentState(); 608 break; 609 case EVENT_PRIMARY_TIMER_EXPIRED: 610 if (DBG) log("Primary timer expired for state: " + mPrimaryTimerState); 611 transitionWithSecondaryTimerTo((IState) msg.obj); 612 break; 613 case EVENT_SECONDARY_TIMER_EXPIRED: 614 if (DBG) log("Secondary timer expired for state: " + mSecondaryTimerState); 615 mIsSecondaryTimerActive = false; 616 mSecondaryTimerState = ""; 617 updateTimers(); 618 updateOverrideNetworkType(); 619 break; 620 case EVENT_RADIO_OFF_OR_UNAVAILABLE: 621 if (DBG) log("Reset timers since radio is off or unavailable."); 622 resetAllTimers(); 623 transitionTo(mLegacyState); 624 break; 625 case EVENT_PREFERRED_NETWORK_MODE_CHANGED: 626 if (DBG) log("Reset timers since preferred network mode changed."); 627 resetAllTimers(); 628 transitionToCurrentState(); 629 break; 630 case EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED: 631 updatePhysicalChannelConfigs(); 632 if (isUsingPhysicalChannelConfigForRrcDetection()) { 633 mPhysicalLinkStatus = getPhysicalLinkStatusFromPhysicalChannelConfig(); 634 } 635 transitionToCurrentState(); 636 break; 637 case EVENT_DEVICE_IDLE_MODE_CHANGED: 638 PowerManager pm = mPhone.getContext().getSystemService(PowerManager.class); 639 mIsDeviceIdleMode = pm.isDeviceIdleMode(); 640 if (DBG) { 641 log("mIsDeviceIdleMode changed to: " + mIsDeviceIdleMode); 642 } 643 if (mIsDeviceIdleMode) { 644 if (DBG) log("Reset timers since device is in idle mode."); 645 resetAllTimers(); 646 } 647 transitionToCurrentState(); 648 break; 649 default: 650 throw new RuntimeException("Received invalid event: " + msg.what); 651 } 652 return HANDLED; 653 } 654 } 655 656 /** 657 * Device does not have NR available, due to any of the below reasons: 658 * <ul> 659 * <li> LTE cell does not support EN-DC 660 * <li> LTE cell supports EN-DC, but the use of NR is restricted 661 * <li> Data network type is not LTE, NR NSA, or NR SA 662 * </ul> 663 * This is the initial state. 664 */ 665 private final class LegacyState extends State { 666 private boolean mIsNrRestricted = false; 667 668 @Override enter()669 public void enter() { 670 if (DBG) log("Entering LegacyState"); 671 updateTimers(); 672 updateOverrideNetworkType(); 673 if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) { 674 mIsNrRestricted = isNrRestricted(); 675 mPreviousState = getName(); 676 } 677 } 678 679 @Override processMessage(Message msg)680 public boolean processMessage(Message msg) { 681 if (DBG) log("LegacyState: process " + getEventName(msg.what)); 682 updateTimers(); 683 switch (msg.what) { 684 case EVENT_SERVICE_STATE_CHANGED: 685 mServiceState = mPhone.getServiceStateTracker().getServiceState(); 686 if (DBG) log("ServiceState updated: " + mServiceState); 687 // fallthrough 688 case EVENT_UPDATE: 689 int rat = getDataNetworkType(); 690 if (rat == TelephonyManager.NETWORK_TYPE_NR || isLte(rat) && isNrConnected()) { 691 if (isNrAdvanced()) { 692 transitionTo(mNrConnectedAdvancedState); 693 } else { 694 transitionTo(mNrConnectedState); 695 } 696 } else if (isLte(rat) && isNrNotRestricted()) { 697 transitionWithTimerTo(isPhysicalLinkActive() 698 ? mLteConnectedState : mIdleState); 699 } else { 700 if (!isLte(rat)) { 701 if (DBG) log("Reset timers since 2G and 3G don't need NR timers."); 702 resetAllTimers(); 703 } 704 updateOverrideNetworkType(); 705 } 706 mIsNrRestricted = isNrRestricted(); 707 break; 708 case EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED: 709 updatePhysicalChannelConfigs(); 710 if (isUsingPhysicalChannelConfigForRrcDetection()) { 711 mPhysicalLinkStatus = getPhysicalLinkStatusFromPhysicalChannelConfig(); 712 if (mIsTimerResetEnabledForLegacyStateRrcIdle && !isPhysicalLinkActive()) { 713 if (DBG) log("Reset timers since timer reset is enabled for RRC idle."); 714 resetAllTimers(); 715 } 716 } 717 break; 718 case EVENT_PHYSICAL_LINK_STATUS_CHANGED: 719 AsyncResult ar = (AsyncResult) msg.obj; 720 mPhysicalLinkStatus = (int) ar.result; 721 if (mIsTimerResetEnabledForLegacyStateRrcIdle && !isPhysicalLinkActive()) { 722 if (DBG) log("Reset timers since timer reset is enabled for RRC idle."); 723 resetAllTimers(); 724 updateOverrideNetworkType(); 725 } 726 break; 727 default: 728 return NOT_HANDLED; 729 } 730 if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) { 731 mPreviousState = getName(); 732 } 733 return HANDLED; 734 } 735 736 @Override getName()737 public String getName() { 738 return mIsNrRestricted ? STATE_RESTRICTED : STATE_LEGACY; 739 } 740 } 741 742 private final LegacyState mLegacyState = new LegacyState(); 743 744 /** 745 * Device does not have any physical connection with the cell (RRC idle). 746 */ 747 private final class IdleState extends State { 748 @Override enter()749 public void enter() { 750 if (DBG) log("Entering IdleState"); 751 updateTimers(); 752 updateOverrideNetworkType(); 753 if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) { 754 mPreviousState = getName(); 755 } 756 } 757 758 @Override processMessage(Message msg)759 public boolean processMessage(Message msg) { 760 if (DBG) log("IdleState: process " + getEventName(msg.what)); 761 updateTimers(); 762 switch (msg.what) { 763 case EVENT_SERVICE_STATE_CHANGED: 764 mServiceState = mPhone.getServiceStateTracker().getServiceState(); 765 if (DBG) log("ServiceState updated: " + mServiceState); 766 // fallthrough 767 case EVENT_UPDATE: 768 int rat = getDataNetworkType(); 769 if (rat == TelephonyManager.NETWORK_TYPE_NR 770 || (isLte(rat) && isNrConnected())) { 771 if (isNrAdvanced()) { 772 transitionTo(mNrConnectedAdvancedState); 773 } else { 774 transitionTo(mNrConnectedState); 775 } 776 } else if (!isLte(rat) || !isNrNotRestricted()) { 777 transitionWithTimerTo(mLegacyState); 778 } else { 779 if (isPhysicalLinkActive()) { 780 transitionWithTimerTo(mLteConnectedState); 781 } else { 782 // Update in case the override network type changed 783 updateOverrideNetworkType(); 784 } 785 } 786 break; 787 case EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED: 788 updatePhysicalChannelConfigs(); 789 if (isUsingPhysicalChannelConfigForRrcDetection()) { 790 mPhysicalLinkStatus = getPhysicalLinkStatusFromPhysicalChannelConfig(); 791 if (isPhysicalLinkActive()) { 792 transitionWithTimerTo(mLteConnectedState); 793 } else { 794 log("Reevaluating state due to link status changed."); 795 sendMessage(EVENT_UPDATE); 796 } 797 } 798 break; 799 case EVENT_PHYSICAL_LINK_STATUS_CHANGED: 800 AsyncResult ar = (AsyncResult) msg.obj; 801 mPhysicalLinkStatus = (int) ar.result; 802 if (isPhysicalLinkActive()) { 803 transitionWithTimerTo(mLteConnectedState); 804 } else { 805 log("Reevaluating state due to link status changed."); 806 sendMessage(EVENT_UPDATE); 807 } 808 break; 809 default: 810 return NOT_HANDLED; 811 } 812 if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) { 813 mPreviousState = getName(); 814 } 815 return HANDLED; 816 } 817 818 @Override getName()819 public String getName() { 820 return STATE_NOT_RESTRICTED_RRC_IDLE; 821 } 822 } 823 824 private final IdleState mIdleState = new IdleState(); 825 826 /** 827 * Device is connected to LTE as the primary cell (RRC connected). 828 */ 829 private final class LteConnectedState extends State { 830 @Override enter()831 public void enter() { 832 if (DBG) log("Entering LteConnectedState"); 833 updateTimers(); 834 updateOverrideNetworkType(); 835 if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) { 836 mPreviousState = getName(); 837 } 838 } 839 840 @Override processMessage(Message msg)841 public boolean processMessage(Message msg) { 842 if (DBG) log("LteConnectedState: process " + getEventName(msg.what)); 843 updateTimers(); 844 switch (msg.what) { 845 case EVENT_SERVICE_STATE_CHANGED: 846 mServiceState = mPhone.getServiceStateTracker().getServiceState(); 847 if (DBG) log("ServiceState updated: " + mServiceState); 848 // fallthrough 849 case EVENT_UPDATE: 850 int rat = getDataNetworkType(); 851 if (rat == TelephonyManager.NETWORK_TYPE_NR 852 || (isLte(rat) && isNrConnected())) { 853 if (isNrAdvanced()) { 854 transitionTo(mNrConnectedAdvancedState); 855 } else { 856 transitionTo(mNrConnectedState); 857 } 858 } else if (!isLte(rat) || !isNrNotRestricted()) { 859 transitionWithTimerTo(mLegacyState); 860 } else { 861 if (!isPhysicalLinkActive()) { 862 transitionWithTimerTo(mIdleState); 863 } else { 864 // Update in case the override network type changed 865 updateOverrideNetworkType(); 866 } 867 } 868 break; 869 case EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED: 870 updatePhysicalChannelConfigs(); 871 if (isUsingPhysicalChannelConfigForRrcDetection()) { 872 mPhysicalLinkStatus = getPhysicalLinkStatusFromPhysicalChannelConfig(); 873 if (!isPhysicalLinkActive()) { 874 transitionWithTimerTo(mIdleState); 875 } else { 876 log("Reevaluating state due to link status changed."); 877 sendMessage(EVENT_UPDATE); 878 } 879 } 880 break; 881 case EVENT_PHYSICAL_LINK_STATUS_CHANGED: 882 AsyncResult ar = (AsyncResult) msg.obj; 883 mPhysicalLinkStatus = (int) ar.result; 884 if (!isPhysicalLinkActive()) { 885 transitionWithTimerTo(mIdleState); 886 } else { 887 log("Reevaluating state due to link status changed."); 888 sendMessage(EVENT_UPDATE); 889 } 890 break; 891 default: 892 return NOT_HANDLED; 893 } 894 if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) { 895 mPreviousState = getName(); 896 } 897 return HANDLED; 898 } 899 900 @Override getName()901 public String getName() { 902 return STATE_NOT_RESTRICTED_RRC_CON; 903 } 904 } 905 906 private final LteConnectedState mLteConnectedState = new LteConnectedState(); 907 908 /** 909 * Device is connected to 5G NR as the primary or secondary cell. 910 */ 911 private final class NrConnectedState extends State { 912 @Override enter()913 public void enter() { 914 if (DBG) log("Entering NrConnectedState"); 915 updateTimers(); 916 updateOverrideNetworkType(); 917 if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) { 918 mPreviousState = getName(); 919 } 920 } 921 922 @Override processMessage(Message msg)923 public boolean processMessage(Message msg) { 924 if (DBG) log("NrConnectedState: process " + getEventName(msg.what)); 925 updateTimers(); 926 switch (msg.what) { 927 case EVENT_SERVICE_STATE_CHANGED: 928 mServiceState = mPhone.getServiceStateTracker().getServiceState(); 929 if (DBG) log("ServiceState updated: " + mServiceState); 930 // fallthrough 931 case EVENT_UPDATE: 932 int rat = getDataNetworkType(); 933 if (rat == TelephonyManager.NETWORK_TYPE_NR 934 || (isLte(rat) && isNrConnected())) { 935 if (isNrAdvanced()) { 936 transitionTo(mNrConnectedAdvancedState); 937 } else { 938 // Update in case the override network type changed 939 updateOverrideNetworkType(); 940 } 941 } else if (isLte(rat) && isNrNotRestricted()) { 942 transitionWithTimerTo(isPhysicalLinkActive() 943 ? mLteConnectedState : mIdleState); 944 } else { 945 transitionWithTimerTo(mLegacyState); 946 } 947 break; 948 case EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED: 949 updatePhysicalChannelConfigs(); 950 if (isUsingPhysicalChannelConfigForRrcDetection()) { 951 mPhysicalLinkStatus = getPhysicalLinkStatusFromPhysicalChannelConfig(); 952 } 953 // Check NR advanced in case NR advanced bands were added 954 if (isNrAdvanced()) { 955 transitionTo(mNrConnectedAdvancedState); 956 } 957 break; 958 case EVENT_PHYSICAL_LINK_STATUS_CHANGED: 959 AsyncResult ar = (AsyncResult) msg.obj; 960 mPhysicalLinkStatus = (int) ar.result; 961 break; 962 default: 963 return NOT_HANDLED; 964 } 965 if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) { 966 mPreviousState = getName(); 967 } 968 return HANDLED; 969 } 970 971 @Override getName()972 public String getName() { 973 return STATE_CONNECTED; 974 } 975 } 976 977 private final NrConnectedState mNrConnectedState = new NrConnectedState(); 978 979 /** 980 * Device is connected to 5G NR as the primary cell and the data rate is higher than 981 * the generic 5G data rate. 982 */ 983 private final class NrConnectedAdvancedState extends State { 984 @Override enter()985 public void enter() { 986 if (DBG) log("Entering NrConnectedAdvancedState"); 987 updateTimers(); 988 updateOverrideNetworkType(); 989 if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) { 990 mPreviousState = getName(); 991 } 992 } 993 994 @Override processMessage(Message msg)995 public boolean processMessage(Message msg) { 996 if (DBG) log("NrConnectedAdvancedState: process " + getEventName(msg.what)); 997 updateTimers(); 998 switch (msg.what) { 999 case EVENT_SERVICE_STATE_CHANGED: 1000 mServiceState = mPhone.getServiceStateTracker().getServiceState(); 1001 if (DBG) log("ServiceState updated: " + mServiceState); 1002 // fallthrough 1003 case EVENT_UPDATE: 1004 int rat = getDataNetworkType(); 1005 if (rat == TelephonyManager.NETWORK_TYPE_NR 1006 || (isLte(rat) && isNrConnected())) { 1007 if (isNrAdvanced()) { 1008 // Update in case the override network type changed 1009 updateOverrideNetworkType(); 1010 } else { 1011 if (rat == TelephonyManager.NETWORK_TYPE_NR && mOverrideNetworkType 1012 != TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED) { 1013 // manually override network type after data rat changes since 1014 // timer will prevent it from being updated 1015 mOverrideNetworkType = 1016 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE; 1017 } 1018 transitionWithTimerTo(mNrConnectedState); 1019 } 1020 } else if (isLte(rat) && isNrNotRestricted()) { 1021 transitionWithTimerTo(isPhysicalLinkActive() 1022 ? mLteConnectedState : mIdleState); 1023 } else { 1024 transitionWithTimerTo(mLegacyState); 1025 } 1026 break; 1027 case EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED: 1028 updatePhysicalChannelConfigs(); 1029 if (isUsingPhysicalChannelConfigForRrcDetection()) { 1030 mPhysicalLinkStatus = getPhysicalLinkStatusFromPhysicalChannelConfig(); 1031 } 1032 // Check NR advanced in case NR advanced bands were removed 1033 if (!isNrAdvanced()) { 1034 transitionWithTimerTo(mNrConnectedState); 1035 } 1036 break; 1037 case EVENT_PHYSICAL_LINK_STATUS_CHANGED: 1038 AsyncResult ar = (AsyncResult) msg.obj; 1039 mPhysicalLinkStatus = (int) ar.result; 1040 break; 1041 default: 1042 return NOT_HANDLED; 1043 } 1044 if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) { 1045 mPreviousState = getName(); 1046 } 1047 return HANDLED; 1048 } 1049 1050 @Override getName()1051 public String getName() { 1052 return STATE_CONNECTED_NR_ADVANCED; 1053 } 1054 } 1055 1056 private final NrConnectedAdvancedState mNrConnectedAdvancedState = 1057 new NrConnectedAdvancedState(); 1058 updatePhysicalChannelConfigs()1059 private void updatePhysicalChannelConfigs() { 1060 List<PhysicalChannelConfig> physicalChannelConfigs = 1061 mPhone.getServiceStateTracker().getPhysicalChannelConfigList(); 1062 boolean isPccListEmpty = physicalChannelConfigs == null || physicalChannelConfigs.isEmpty(); 1063 if (isPccListEmpty && isUsingPhysicalChannelConfigForRrcDetection()) { 1064 log("Physical channel configs updated: not updating PCC fields for empty PCC list " 1065 + "indicating RRC idle."); 1066 mPhysicalChannelConfigs = physicalChannelConfigs; 1067 return; 1068 } 1069 1070 int anchorNrCellId = PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN; 1071 int anchorLteCellId = PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN; 1072 int nrBandwidths = 0; 1073 Set<Integer> nrBands = new HashSet<>(); 1074 if (physicalChannelConfigs != null) { 1075 for (PhysicalChannelConfig config : physicalChannelConfigs) { 1076 if (config.getNetworkType() == TelephonyManager.NETWORK_TYPE_NR) { 1077 if (config.getConnectionStatus() == CellInfo.CONNECTION_PRIMARY_SERVING 1078 && anchorNrCellId == PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN) { 1079 anchorNrCellId = config.getPhysicalCellId(); 1080 } 1081 nrBandwidths += config.getCellBandwidthDownlinkKhz(); 1082 nrBands.add(config.getBand()); 1083 } else if (config.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE) { 1084 if (config.getConnectionStatus() == CellInfo.CONNECTION_PRIMARY_SERVING 1085 && anchorLteCellId == PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN) { 1086 anchorLteCellId = config.getPhysicalCellId(); 1087 } 1088 if (mIncludeLteForNrAdvancedThresholdBandwidth) { 1089 nrBandwidths += config.getCellBandwidthDownlinkKhz(); 1090 } 1091 } 1092 } 1093 } 1094 1095 // Update anchor NR cell from anchor LTE cell for NR NSA 1096 if (anchorNrCellId == PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN 1097 && anchorLteCellId != PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN) { 1098 anchorNrCellId = anchorLteCellId; 1099 } 1100 1101 if (anchorNrCellId == PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN) { 1102 if (!isPccListEmpty) { 1103 log("Ignoring physical channel config fields without an anchor NR cell, " 1104 + "either due to LTE-only configs or an unspecified cell ID."); 1105 } 1106 mRatchetedNrBandwidths = 0; 1107 mRatchetedNrBands.clear(); 1108 } else if (anchorNrCellId == mLastAnchorNrCellId && mRatchetPccFieldsForSameAnchorNrCell) { 1109 log("Ratchet physical channel config fields since anchor NR cell is the same."); 1110 mRatchetedNrBandwidths = Math.max(mRatchetedNrBandwidths, nrBandwidths); 1111 mRatchetedNrBands.addAll(nrBands); 1112 } else { 1113 if (mRatchetPccFieldsForSameAnchorNrCell) { 1114 log("Not ratcheting physical channel config fields since anchor NR cell changed: " 1115 + mLastAnchorNrCellId + " -> " + anchorNrCellId); 1116 } 1117 mRatchetedNrBandwidths = nrBandwidths; 1118 mRatchetedNrBands = nrBands; 1119 } 1120 1121 mLastAnchorNrCellId = anchorNrCellId; 1122 mPhysicalChannelConfigs = physicalChannelConfigs; 1123 if (DBG) { 1124 log("Physical channel configs updated: anchorNrCell=" + mLastAnchorNrCellId 1125 + ", nrBandwidths=" + mRatchetedNrBandwidths + ", nrBands=" + mRatchetedNrBands 1126 + ", configs=" + mPhysicalChannelConfigs); 1127 } 1128 } 1129 transitionWithTimerTo(IState destState)1130 private void transitionWithTimerTo(IState destState) { 1131 String destName = destState.getName(); 1132 if (DBG) log("Transition with primary timer from " + mPreviousState + " to " + destName); 1133 OverrideTimerRule rule = mOverrideTimerRules.get(mPreviousState); 1134 if (!mIsDeviceIdleMode && rule != null && rule.getTimer(destName) > 0) { 1135 int duration = rule.getTimer(destName); 1136 if (DBG) log(duration + "s primary timer started for state: " + mPreviousState); 1137 mPrimaryTimerState = mPreviousState; 1138 mPreviousState = getCurrentState().getName(); 1139 mIsPrimaryTimerActive = true; 1140 sendMessageDelayed(EVENT_PRIMARY_TIMER_EXPIRED, destState, duration * 1000L); 1141 } 1142 transitionTo(destState); 1143 } 1144 transitionWithSecondaryTimerTo(IState destState)1145 private void transitionWithSecondaryTimerTo(IState destState) { 1146 String currentName = getCurrentState().getName(); 1147 OverrideTimerRule rule = mOverrideTimerRules.get(mPrimaryTimerState); 1148 if (DBG) { 1149 log("Transition with secondary timer from " + currentName + " to " 1150 + destState.getName()); 1151 } 1152 if (!mIsDeviceIdleMode && rule != null && rule.getSecondaryTimer(currentName) > 0) { 1153 int duration = rule.getSecondaryTimer(currentName); 1154 if (DBG) log(duration + "s secondary timer started for state: " + currentName); 1155 mSecondaryTimerState = currentName; 1156 mPreviousState = currentName; 1157 mIsSecondaryTimerActive = true; 1158 sendMessageDelayed(EVENT_SECONDARY_TIMER_EXPIRED, destState, duration * 1000L); 1159 } 1160 mIsPrimaryTimerActive = false; 1161 transitionTo(getCurrentState()); 1162 } 1163 transitionToCurrentState()1164 private void transitionToCurrentState() { 1165 int dataRat = getDataNetworkType(); 1166 IState transitionState; 1167 if (dataRat == TelephonyManager.NETWORK_TYPE_NR || (isLte(dataRat) && isNrConnected())) { 1168 if (isNrAdvanced()) { 1169 transitionState = mNrConnectedAdvancedState; 1170 } else { 1171 transitionState = mNrConnectedState; 1172 } 1173 } else if (isLte(dataRat) && isNrNotRestricted()) { 1174 if (isPhysicalLinkActive()) { 1175 transitionState = mLteConnectedState; 1176 } else { 1177 transitionState = mIdleState; 1178 } 1179 } else { 1180 transitionState = mLegacyState; 1181 } 1182 if (!transitionState.equals(getCurrentState())) { 1183 mPreviousState = getCurrentState().getName(); 1184 transitionTo(transitionState); 1185 } else { 1186 updateOverrideNetworkType(); 1187 } 1188 } 1189 updateTimers()1190 private void updateTimers() { 1191 if ((mPhone.getCachedAllowedNetworkTypesBitmask() 1192 & TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) { 1193 if (DBG) log("Reset timers since NR is not allowed."); 1194 resetAllTimers(); 1195 return; 1196 } 1197 1198 String currentState = getCurrentState().getName(); 1199 1200 if (mIsPrimaryTimerActive && getOverrideNetworkType() == getCurrentOverrideNetworkType()) { 1201 // remove primary timer if device goes back to the original icon 1202 if (DBG) { 1203 log("Remove primary timer since icon of primary state and current icon equal: " 1204 + mPrimaryTimerState); 1205 } 1206 removeMessages(EVENT_PRIMARY_TIMER_EXPIRED); 1207 mIsPrimaryTimerActive = false; 1208 mPrimaryTimerState = ""; 1209 transitionToCurrentState(); 1210 return; 1211 } 1212 1213 if (mIsSecondaryTimerActive && !mSecondaryTimerState.equals(currentState)) { 1214 // remove secondary timer if devices is no longer in secondary timer state 1215 if (DBG) { 1216 log("Remove secondary timer since current state (" + currentState 1217 + ") is no longer secondary timer state (" + mSecondaryTimerState + ")."); 1218 } 1219 removeMessages(EVENT_SECONDARY_TIMER_EXPIRED); 1220 mIsSecondaryTimerActive = false; 1221 mSecondaryTimerState = ""; 1222 transitionToCurrentState(); 1223 return; 1224 } 1225 1226 if (mIsPrimaryTimerActive || mIsSecondaryTimerActive) { 1227 if (currentState.equals(STATE_CONNECTED_NR_ADVANCED)) { 1228 if (DBG) log("Reset timers since state is NR_ADVANCED."); 1229 resetAllTimers(); 1230 } else if (currentState.equals(STATE_CONNECTED) 1231 && !mPrimaryTimerState.equals(STATE_CONNECTED_NR_ADVANCED) 1232 && !mSecondaryTimerState.equals(STATE_CONNECTED_NR_ADVANCED)) { 1233 if (DBG) log("Reset non-NR_ADVANCED timers since state is NR_CONNECTED"); 1234 resetAllTimers(); 1235 } else { 1236 int rat = getDataNetworkType(); 1237 if (!isLte(rat) && rat != TelephonyManager.NETWORK_TYPE_NR) { 1238 if (DBG) log("Reset timers since 2G and 3G don't need NR timers."); 1239 resetAllTimers(); 1240 } 1241 } 1242 } 1243 } 1244 resetAllTimers()1245 private void resetAllTimers() { 1246 removeMessages(EVENT_PRIMARY_TIMER_EXPIRED); 1247 removeMessages(EVENT_SECONDARY_TIMER_EXPIRED); 1248 mIsPrimaryTimerActive = false; 1249 mIsSecondaryTimerActive = false; 1250 mPrimaryTimerState = ""; 1251 mSecondaryTimerState = ""; 1252 } 1253 1254 /** 1255 * Private class defining timer rules between states to prevent flickering. These rules are 1256 * created in {@link #parseCarrierConfigs()} based on various carrier configs. 1257 */ 1258 private static class OverrideTimerRule { 1259 /** The 5G state this timer rule applies for. See {@link #ALL_STATES}. */ 1260 final String mState; 1261 1262 /** 1263 * The override network type associated with this 5G state. This is the icon that will be 1264 * displayed on the status bar. An override type of NONE will display the LTE value instead. 1265 */ 1266 final int mOverrideType; 1267 1268 /** 1269 * A map of destination states and associated timers. If the 5G state changes from mState 1270 * to the destination state, keep the override type until either the primary timer expires 1271 * or mState is regained. 1272 */ 1273 final Map<String, Integer> mPrimaryTimers; 1274 1275 /** 1276 * A map of secondary states and associated timers. After the primary timer expires, keep 1277 * the override type until either the secondary timer expires or the device is no longer in 1278 * the secondary state. 1279 */ 1280 final Map<String, Integer> mSecondaryTimers; 1281 OverrideTimerRule(String state, int overrideType)1282 OverrideTimerRule(String state, int overrideType) { 1283 mState = state; 1284 mOverrideType = overrideType; 1285 mPrimaryTimers = new HashMap<>(); 1286 mSecondaryTimers = new HashMap<>(); 1287 } 1288 1289 /** 1290 * Add a primary timer. 1291 * @param destination Transitions from mState to the destination state. 1292 * @param duration How long to keep the override type after transition to destination state. 1293 */ addTimer(String destination, int duration)1294 public void addTimer(String destination, int duration) { 1295 mPrimaryTimers.put(destination, duration); 1296 } 1297 1298 /** 1299 * Add a secondary timer 1300 * @param secondaryState Stays in secondaryState after primary timer expires. 1301 * @param duration How long to keep the override type while in secondaryState. 1302 */ addSecondaryTimer(String secondaryState, int duration)1303 public void addSecondaryTimer(String secondaryState, int duration) { 1304 mSecondaryTimers.put(secondaryState, duration); 1305 } 1306 1307 /** 1308 * @return Primary timer duration from mState to destination state, or 0 if not defined. 1309 */ getTimer(String destination)1310 public int getTimer(String destination) { 1311 Integer timer = mPrimaryTimers.get(destination); 1312 timer = timer == null ? mPrimaryTimers.get(STATE_ANY) : timer; 1313 return timer == null ? 0 : timer; 1314 } 1315 1316 /** 1317 * @return Secondary timer duration for secondaryState, or 0 if not defined. 1318 */ getSecondaryTimer(String secondaryState)1319 public int getSecondaryTimer(String secondaryState) { 1320 Integer secondaryTimer = mSecondaryTimers.get(secondaryState); 1321 secondaryTimer = secondaryTimer == null 1322 ? mSecondaryTimers.get(STATE_ANY) : secondaryTimer; 1323 return secondaryTimer == null ? 0 : secondaryTimer; 1324 } 1325 1326 @Override toString()1327 public String toString() { 1328 return "{mState=" + mState 1329 + ", mOverrideType=" 1330 + TelephonyDisplayInfo.overrideNetworkTypeToString(mOverrideType) 1331 + ", mPrimaryTimers=" + mPrimaryTimers 1332 + ", mSecondaryTimers=" + mSecondaryTimers + "}"; 1333 } 1334 } 1335 isNrConnected()1336 private boolean isNrConnected() { 1337 return mServiceState.getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED; 1338 } 1339 isNrNotRestricted()1340 private boolean isNrNotRestricted() { 1341 return mServiceState.getNrState() == NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED; 1342 } 1343 isNrRestricted()1344 private boolean isNrRestricted() { 1345 return mServiceState.getNrState() == NetworkRegistrationInfo.NR_STATE_RESTRICTED; 1346 } 1347 1348 /** 1349 * @return {@code true} if the device is in NR advanced mode (i.e. 5G+). 1350 */ isNrAdvanced()1351 private boolean isNrAdvanced() { 1352 // Check PCO requirement. For carriers using PCO to indicate whether the data connection is 1353 // NR advanced capable, mNrAdvancedCapablePcoId should be configured to non-zero. 1354 if (mNrAdvancedCapablePcoId > 0 && !mIsNrAdvancedAllowedByPco) { 1355 if (DBG) log("isNrAdvanced: not allowed by PCO for PCO ID " + mNrAdvancedCapablePcoId); 1356 return false; 1357 } 1358 1359 // Check if NR advanced is enabled when the device is roaming. Some carriers disable it 1360 // while the device is roaming. 1361 if (mServiceState.getDataRoaming() && !mEnableNrAdvancedWhileRoaming) { 1362 if (DBG) log("isNrAdvanced: false because NR advanced is unavailable while roaming."); 1363 return false; 1364 } 1365 1366 // Check if meeting minimum bandwidth requirement. For most carriers, there is no minimum 1367 // bandwidth requirement and mNrAdvancedThresholdBandwidth is 0. 1368 if (mNrAdvancedThresholdBandwidth > 0 1369 && mRatchetedNrBandwidths < mNrAdvancedThresholdBandwidth) { 1370 if (DBG) { 1371 log("isNrAdvanced: false because bandwidths=" + mRatchetedNrBandwidths 1372 + " does not meet the threshold=" + mNrAdvancedThresholdBandwidth); 1373 } 1374 return false; 1375 } 1376 1377 // If all above tests passed, then check if the device is using millimeter wave bands or 1378 // carrier designated bands. 1379 return isNrMmwave() || isAdditionalNrAdvancedBand(); 1380 } 1381 isNrMmwave()1382 private boolean isNrMmwave() { 1383 return mServiceState.getNrFrequencyRange() == ServiceState.FREQUENCY_RANGE_MMWAVE; 1384 } 1385 isAdditionalNrAdvancedBand()1386 private boolean isAdditionalNrAdvancedBand() { 1387 if (mAdditionalNrAdvancedBands.isEmpty() || mRatchetedNrBands.isEmpty()) { 1388 if (DBG && !mAdditionalNrAdvancedBands.isEmpty()) { 1389 // Only log if mAdditionalNrAdvancedBands is empty to prevent log spam 1390 log("isAdditionalNrAdvancedBand: false because bands are empty; configs=" 1391 + mAdditionalNrAdvancedBands + ", bands=" + mRatchetedNrBands); 1392 } 1393 return false; 1394 } 1395 Set<Integer> intersection = new HashSet<>(mAdditionalNrAdvancedBands); 1396 intersection.retainAll(mRatchetedNrBands); 1397 return !intersection.isEmpty(); 1398 } 1399 isLte(int rat)1400 private boolean isLte(int rat) { 1401 return rat == TelephonyManager.NETWORK_TYPE_LTE 1402 || rat == TelephonyManager.NETWORK_TYPE_LTE_CA; 1403 } 1404 isPhysicalLinkActive()1405 private boolean isPhysicalLinkActive() { 1406 return mPhysicalLinkStatus == DataCallResponse.LINK_STATUS_ACTIVE; 1407 } 1408 getPhysicalLinkStatusFromPhysicalChannelConfig()1409 private int getPhysicalLinkStatusFromPhysicalChannelConfig() { 1410 return (mPhysicalChannelConfigs == null || mPhysicalChannelConfigs.isEmpty()) 1411 ? DataCallResponse.LINK_STATUS_DORMANT : DataCallResponse.LINK_STATUS_ACTIVE; 1412 } 1413 getEventName(int event)1414 private String getEventName(int event) { 1415 try { 1416 return sEvents[event]; 1417 } catch (ArrayIndexOutOfBoundsException e) { 1418 return "EVENT_NOT_DEFINED"; 1419 } 1420 } 1421 isUsingPhysicalChannelConfigForRrcDetection()1422 private boolean isUsingPhysicalChannelConfigForRrcDetection() { 1423 return mIsPhysicalChannelConfig16Supported && !mIsUsingUserDataForRrcDetection; 1424 } 1425 log(String s)1426 protected void log(String s) { 1427 Rlog.d(TAG, "[" + mPhone.getPhoneId() + "] " + s); 1428 } 1429 loge(String s)1430 protected void loge(String s) { 1431 Rlog.e(TAG, "[" + mPhone.getPhoneId() + "] " + s); 1432 } 1433 1434 @Override toString()1435 public String toString() { 1436 return "mOverrideTimerRules=" + mOverrideTimerRules.toString() 1437 + ", mLteEnhancedPattern=" + mLteEnhancedPattern 1438 + ", mIsPhysicalChannelConfigOn=" + mIsPhysicalChannelConfigOn 1439 + ", mIsPrimaryTimerActive=" + mIsPrimaryTimerActive 1440 + ", mIsSecondaryTimerActive=" + mIsSecondaryTimerActive 1441 + ", mPrimaryTimerState=" + mPrimaryTimerState 1442 + ", mSecondaryTimerState=" + mSecondaryTimerState 1443 + ", mPreviousState=" + mPreviousState 1444 + ", mIsNrAdvanced=" + isNrAdvanced(); 1445 } 1446 1447 @Override dump(FileDescriptor fd, PrintWriter printWriter, String[] args)1448 public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) { 1449 IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " "); 1450 pw.print("NetworkTypeController: "); 1451 super.dump(fd, pw, args); 1452 pw.flush(); 1453 pw.increaseIndent(); 1454 pw.println("mSubId=" + mPhone.getSubId()); 1455 pw.println("mOverrideTimerRules=" + mOverrideTimerRules.toString()); 1456 pw.println("mLteEnhancedPattern=" + mLteEnhancedPattern); 1457 pw.println("mIsPhysicalChannelConfigOn=" + mIsPhysicalChannelConfigOn); 1458 pw.println("mIsPrimaryTimerActive=" + mIsPrimaryTimerActive); 1459 pw.println("mIsSecondaryTimerActive=" + mIsSecondaryTimerActive); 1460 pw.println("mIsTimerResetEnabledForLegacyStateRrcIdle=" 1461 + mIsTimerResetEnabledForLegacyStateRrcIdle); 1462 pw.println("mLtePlusThresholdBandwidth=" + mLtePlusThresholdBandwidth); 1463 pw.println("mNrAdvancedThresholdBandwidth=" + mNrAdvancedThresholdBandwidth); 1464 pw.println("mIncludeLteForNrAdvancedThresholdBandwidth=" 1465 + mIncludeLteForNrAdvancedThresholdBandwidth); 1466 pw.println("mRatchetPccFieldsForSameAnchorNrCell=" + mRatchetPccFieldsForSameAnchorNrCell); 1467 pw.println("mRatchetedNrBandwidths=" + mRatchetedNrBandwidths); 1468 pw.println("mAdditionalNrAdvancedBandsList=" + mAdditionalNrAdvancedBands); 1469 pw.println("mRatchetedNrBands=" + mRatchetedNrBands); 1470 pw.println("mLastAnchorNrCellId=" + mLastAnchorNrCellId); 1471 pw.println("mPrimaryTimerState=" + mPrimaryTimerState); 1472 pw.println("mSecondaryTimerState=" + mSecondaryTimerState); 1473 pw.println("mPreviousState=" + mPreviousState); 1474 pw.println("mPhysicalLinkStatus=" + DataUtils.linkStatusToString(mPhysicalLinkStatus)); 1475 pw.println("mIsPhysicalChannelConfig16Supported=" + mIsPhysicalChannelConfig16Supported); 1476 pw.println("mIsNrAdvancedAllowedByPco=" + mIsNrAdvancedAllowedByPco); 1477 pw.println("mNrAdvancedCapablePcoId=" + mNrAdvancedCapablePcoId); 1478 pw.println("mIsUsingUserDataForRrcDetection=" + mIsUsingUserDataForRrcDetection); 1479 pw.println("mEnableNrAdvancedWhileRoaming=" + mEnableNrAdvancedWhileRoaming); 1480 pw.println("mIsDeviceIdleMode=" + mIsDeviceIdleMode); 1481 pw.decreaseIndent(); 1482 pw.flush(); 1483 } 1484 } 1485