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.content.BroadcastReceiver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.os.AsyncResult; 25 import android.os.Message; 26 import android.os.PersistableBundle; 27 import android.telephony.AccessNetworkConstants; 28 import android.telephony.Annotation; 29 import android.telephony.CarrierConfigManager; 30 import android.telephony.NetworkRegistrationInfo; 31 import android.telephony.PcoData; 32 import android.telephony.PhysicalChannelConfig; 33 import android.telephony.ServiceState; 34 import android.telephony.SubscriptionManager; 35 import android.telephony.TelephonyDisplayInfo; 36 import android.telephony.TelephonyManager; 37 import android.telephony.data.DataCallResponse; 38 import android.text.TextUtils; 39 import android.util.ArrayMap; 40 import android.util.ArraySet; 41 42 import com.android.internal.telephony.dataconnection.DcController; 43 import com.android.internal.telephony.dataconnection.DcController.PhysicalLinkState; 44 import com.android.internal.telephony.uicc.IccUtils; 45 import com.android.internal.telephony.util.ArrayUtils; 46 import com.android.internal.util.IState; 47 import com.android.internal.util.IndentingPrintWriter; 48 import com.android.internal.util.State; 49 import com.android.internal.util.StateMachine; 50 import com.android.telephony.Rlog; 51 52 import java.io.FileDescriptor; 53 import java.io.PrintWriter; 54 import java.util.ArrayList; 55 import java.util.Arrays; 56 import java.util.HashMap; 57 import java.util.List; 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 public static final int EVENT_QUIT = 1; 91 private static final int EVENT_DATA_RAT_CHANGED = 2; 92 private static final int EVENT_NR_STATE_CHANGED = 3; 93 private static final int EVENT_NR_FREQUENCY_CHANGED = 4; 94 private static final int EVENT_PHYSICAL_LINK_STATE_CHANGED = 5; 95 private static final int EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED = 6; 96 private static final int EVENT_CARRIER_CONFIG_CHANGED = 7; 97 private static final int EVENT_PRIMARY_TIMER_EXPIRED = 8; 98 private static final int EVENT_SECONDARY_TIMER_EXPIRED = 9; 99 private static final int EVENT_RADIO_OFF_OR_UNAVAILABLE = 10; 100 private static final int EVENT_PREFERRED_NETWORK_MODE_CHANGED = 11; 101 private static final int EVENT_INITIALIZE = 12; 102 private static final int EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED = 13; 103 private static final int EVENT_PCO_DATA_CHANGED = 14; 104 private static final int EVENT_BANDWIDTH_CHANGED = 15; 105 private static final int EVENT_DATA_CALL_LIST_CHANGED = 16; 106 107 private static final String[] sEvents = new String[EVENT_DATA_CALL_LIST_CHANGED + 1]; 108 static { 109 sEvents[EVENT_UPDATE] = "EVENT_UPDATE"; 110 sEvents[EVENT_QUIT] = "EVENT_QUIT"; 111 sEvents[EVENT_DATA_RAT_CHANGED] = "EVENT_DATA_RAT_CHANGED"; 112 sEvents[EVENT_NR_STATE_CHANGED] = "EVENT_NR_STATE_CHANGED"; 113 sEvents[EVENT_NR_FREQUENCY_CHANGED] = "EVENT_NR_FREQUENCY_CHANGED"; 114 sEvents[EVENT_PHYSICAL_LINK_STATE_CHANGED] = "EVENT_PHYSICAL_LINK_STATE_CHANGED"; 115 sEvents[EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED] = 116 "EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED"; 117 sEvents[EVENT_CARRIER_CONFIG_CHANGED] = "EVENT_CARRIER_CONFIG_CHANGED"; 118 sEvents[EVENT_PRIMARY_TIMER_EXPIRED] = "EVENT_PRIMARY_TIMER_EXPIRED"; 119 sEvents[EVENT_SECONDARY_TIMER_EXPIRED] = "EVENT_SECONDARY_TIMER_EXPIRED"; 120 sEvents[EVENT_RADIO_OFF_OR_UNAVAILABLE] = "EVENT_RADIO_OFF_OR_UNAVAILABLE"; 121 sEvents[EVENT_PREFERRED_NETWORK_MODE_CHANGED] = "EVENT_PREFERRED_NETWORK_MODE_CHANGED"; 122 sEvents[EVENT_INITIALIZE] = "EVENT_INITIALIZE"; 123 sEvents[EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED] = "EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED"; 124 sEvents[EVENT_PCO_DATA_CHANGED] = "EVENT_PCO_DATA_CHANGED"; 125 sEvents[EVENT_DATA_CALL_LIST_CHANGED] = "EVENT_DATA_CALL_LIST_CHANGED"; 126 } 127 128 private final Phone mPhone; 129 private final DisplayInfoController mDisplayInfoController; 130 private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 131 @Override 132 public void onReceive(Context context, Intent intent) { 133 if (intent.getAction().equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED) 134 && intent.getIntExtra(SubscriptionManager.EXTRA_SLOT_INDEX, 135 SubscriptionManager.INVALID_PHONE_INDEX) == mPhone.getPhoneId() 136 && !intent.getBooleanExtra(CarrierConfigManager.EXTRA_REBROADCAST_ON_UNLOCK, 137 false)) { 138 sendMessage(EVENT_CARRIER_CONFIG_CHANGED); 139 } 140 } 141 }; 142 143 private Map<String, OverrideTimerRule> mOverrideTimerRules = new HashMap<>(); 144 private String mLteEnhancedPattern = ""; 145 private int mOverrideNetworkType; 146 private boolean mIsPhysicalChannelConfigOn; 147 private boolean mIsPrimaryTimerActive; 148 private boolean mIsSecondaryTimerActive; 149 private boolean mIsTimerResetEnabledForLegacyStateRRCIdle; 150 private int mLtePlusThresholdBandwidth; 151 private int mNrAdvancedThresholdBandwidth; 152 private int[] mAdditionalNrAdvancedBandsList; 153 private String mPrimaryTimerState; 154 private String mSecondaryTimerState; 155 private String mPreviousState; 156 private @PhysicalLinkState int mPhysicalLinkState; 157 private boolean mIsPhysicalChannelConfig16Supported; 158 private Boolean mIsNrAdvancedAllowedByPco = false; 159 private int mNrAdvancedCapablePcoId = 0; 160 /** The key is the cid, the value is the PCO data. */ 161 private final @NonNull Map<Integer, PcoData> mPcoDataMap = new ArrayMap<>(); 162 /** Active data connection cid set. */ 163 private final @NonNull Set<Integer> mActiveDcCidSet = new ArraySet<>(); 164 private boolean mIsUsingUserDataForRrcDetection = false; 165 private boolean mEnableNrAdvancedWhileRoaming = true; 166 167 /** 168 * NetworkTypeController constructor. 169 * 170 * @param phone Phone object. 171 * @param displayInfoController DisplayInfoController to send override network types to. 172 */ NetworkTypeController(Phone phone, DisplayInfoController displayInfoController)173 public NetworkTypeController(Phone phone, DisplayInfoController displayInfoController) { 174 super(TAG, displayInfoController); 175 mPhone = phone; 176 mDisplayInfoController = displayInfoController; 177 mOverrideNetworkType = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE; 178 mIsPhysicalChannelConfigOn = true; 179 addState(mDefaultState); 180 addState(mLegacyState, mDefaultState); 181 addState(mIdleState, mDefaultState); 182 addState(mLteConnectedState, mDefaultState); 183 addState(mNrConnectedState, mDefaultState); 184 setInitialState(mDefaultState); 185 start(); 186 sendMessage(EVENT_INITIALIZE); 187 } 188 189 /** 190 * @return The current override network type, used to create TelephonyDisplayInfo in 191 * DisplayInfoController. 192 */ getOverrideNetworkType()193 public @Annotation.OverrideNetworkType int getOverrideNetworkType() { 194 return mOverrideNetworkType; 195 } 196 197 /** 198 * @return True if either the primary or secondary 5G hysteresis timer is active, 199 * and false if neither are. 200 */ is5GHysteresisActive()201 public boolean is5GHysteresisActive() { 202 return mIsPrimaryTimerActive || mIsSecondaryTimerActive; 203 } 204 registerForAllEvents()205 private void registerForAllEvents() { 206 mPhone.registerForRadioOffOrNotAvailable(getHandler(), 207 EVENT_RADIO_OFF_OR_UNAVAILABLE, null); 208 mPhone.registerForPreferredNetworkTypeChanged(getHandler(), 209 EVENT_PREFERRED_NETWORK_MODE_CHANGED, null); 210 mPhone.registerForPhysicalChannelConfig(getHandler(), 211 EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED, null); 212 mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged( 213 AccessNetworkConstants.TRANSPORT_TYPE_WWAN, getHandler(), 214 EVENT_DATA_RAT_CHANGED, null); 215 mPhone.getServiceStateTracker().registerForBandwidthChanged( 216 getHandler(), EVENT_BANDWIDTH_CHANGED, null); 217 mIsPhysicalChannelConfig16Supported = mPhone.getContext().getSystemService( 218 TelephonyManager.class).isRadioInterfaceCapabilitySupported( 219 TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED); 220 if (!mIsPhysicalChannelConfig16Supported) { 221 mPhone.getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 222 .registerForPhysicalLinkStateChanged(getHandler(), 223 EVENT_PHYSICAL_LINK_STATE_CHANGED); 224 } 225 mPhone.getServiceStateTracker().registerForNrStateChanged(getHandler(), 226 EVENT_NR_STATE_CHANGED, null); 227 mPhone.getServiceStateTracker().registerForNrFrequencyChanged(getHandler(), 228 EVENT_NR_FREQUENCY_CHANGED, null); 229 mPhone.getDeviceStateMonitor().registerForPhysicalChannelConfigNotifChanged(getHandler(), 230 EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED, null); 231 IntentFilter filter = new IntentFilter(); 232 filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 233 mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone); 234 235 // TODO: This is a temporarily solution for S. Ideally PCO and data call list changed event 236 // should not be exposed outside of the data modules. PCO for 5G icon has been well 237 // supported in the new data architecture in T. This temp solution must be removed in T 238 // along with other old data modules. 239 mPhone.mCi.registerForPcoData(getHandler(), EVENT_PCO_DATA_CHANGED, null); 240 mPhone.mCi.registerForDataCallListChanged(getHandler(), EVENT_DATA_CALL_LIST_CHANGED, null); 241 } 242 unRegisterForAllEvents()243 private void unRegisterForAllEvents() { 244 mPhone.unregisterForRadioOffOrNotAvailable(getHandler()); 245 mPhone.unregisterForPreferredNetworkTypeChanged(getHandler()); 246 mPhone.getServiceStateTracker().unregisterForDataRegStateOrRatChanged( 247 AccessNetworkConstants.TRANSPORT_TYPE_WWAN, getHandler()); 248 mPhone.getServiceStateTracker().unregisterForNrStateChanged(getHandler()); 249 mPhone.getServiceStateTracker().unregisterForNrFrequencyChanged(getHandler()); 250 mPhone.getDeviceStateMonitor().unregisterForPhysicalChannelConfigNotifChanged(getHandler()); 251 mPhone.getContext().unregisterReceiver(mIntentReceiver); 252 mPhone.mCi.unregisterForPcoData(getHandler()); 253 mPhone.mCi.unregisterForDataCallListChanged(getHandler()); 254 } 255 parseCarrierConfigs()256 private void parseCarrierConfigs() { 257 String nrIconConfiguration = CarrierConfigManager.getDefaultConfig().getString( 258 CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING); 259 String overrideTimerRule = CarrierConfigManager.getDefaultConfig().getString( 260 CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING); 261 String overrideSecondaryTimerRule = CarrierConfigManager.getDefaultConfig().getString( 262 CarrierConfigManager.KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING); 263 mLteEnhancedPattern = CarrierConfigManager.getDefaultConfig().getString( 264 CarrierConfigManager.KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING); 265 mIsTimerResetEnabledForLegacyStateRRCIdle = 266 CarrierConfigManager.getDefaultConfig().getBoolean( 267 CarrierConfigManager.KEY_NR_TIMERS_RESET_IF_NON_ENDC_AND_RRC_IDLE_BOOL); 268 mLtePlusThresholdBandwidth = CarrierConfigManager.getDefaultConfig().getInt( 269 CarrierConfigManager.KEY_LTE_PLUS_THRESHOLD_BANDWIDTH_KHZ_INT); 270 mNrAdvancedThresholdBandwidth = CarrierConfigManager.getDefaultConfig().getInt( 271 CarrierConfigManager.KEY_NR_ADVANCED_THRESHOLD_BANDWIDTH_KHZ_INT); 272 mEnableNrAdvancedWhileRoaming = CarrierConfigManager.getDefaultConfig().getBoolean( 273 CarrierConfigManager.KEY_ENABLE_NR_ADVANCED_WHILE_ROAMING_BOOL); 274 275 CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext() 276 .getSystemService(Context.CARRIER_CONFIG_SERVICE); 277 if (configManager != null) { 278 PersistableBundle b = configManager.getConfigForSubId(mPhone.getSubId()); 279 if (b != null) { 280 if (b.getString(CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING) != null) { 281 nrIconConfiguration = b.getString( 282 CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING); 283 } 284 if (b.getString(CarrierConfigManager 285 .KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING) != null) { 286 overrideTimerRule = b.getString( 287 CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING); 288 } 289 if (b.getString(CarrierConfigManager 290 .KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING) != null) { 291 overrideSecondaryTimerRule = b.getString( 292 CarrierConfigManager.KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING); 293 } 294 if (b.getString(CarrierConfigManager 295 .KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING) != null) { 296 mLteEnhancedPattern = b.getString( 297 CarrierConfigManager.KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING); 298 } 299 mIsTimerResetEnabledForLegacyStateRRCIdle = b.getBoolean( 300 CarrierConfigManager.KEY_NR_TIMERS_RESET_IF_NON_ENDC_AND_RRC_IDLE_BOOL); 301 mLtePlusThresholdBandwidth = b.getInt( 302 CarrierConfigManager.KEY_LTE_PLUS_THRESHOLD_BANDWIDTH_KHZ_INT, 303 mLtePlusThresholdBandwidth); 304 mNrAdvancedThresholdBandwidth = b.getInt( 305 CarrierConfigManager.KEY_NR_ADVANCED_THRESHOLD_BANDWIDTH_KHZ_INT, 306 mNrAdvancedThresholdBandwidth); 307 mAdditionalNrAdvancedBandsList = b.getIntArray( 308 CarrierConfigManager.KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY); 309 mNrAdvancedCapablePcoId = b.getInt( 310 CarrierConfigManager.KEY_NR_ADVANCED_CAPABLE_PCO_ID_INT); 311 mEnableNrAdvancedWhileRoaming = b.getBoolean( 312 CarrierConfigManager.KEY_ENABLE_NR_ADVANCED_WHILE_ROAMING_BOOL); 313 mIsUsingUserDataForRrcDetection = b.getBoolean( 314 CarrierConfigManager.KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL); 315 if (mIsPhysicalChannelConfig16Supported && mIsUsingUserDataForRrcDetection) { 316 mPhone.getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 317 .registerForPhysicalLinkStateChanged(getHandler(), 318 EVENT_PHYSICAL_LINK_STATE_CHANGED); 319 } 320 } 321 } 322 createTimerRules(nrIconConfiguration, overrideTimerRule, overrideSecondaryTimerRule); 323 } 324 createTimerRules(String icons, String timers, String secondaryTimers)325 private void createTimerRules(String icons, String timers, String secondaryTimers) { 326 Map<String, OverrideTimerRule> tempRules = new HashMap<>(); 327 if (!TextUtils.isEmpty(icons)) { 328 // Format: "STATE:ICON,STATE2:ICON2" 329 for (String pair : icons.trim().split(",")) { 330 String[] kv = (pair.trim().toLowerCase()).split(":"); 331 if (kv.length != 2) { 332 if (DBG) loge("Invalid 5G icon configuration, config = " + pair); 333 continue; 334 } 335 int icon = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE; 336 if (kv[1].equals(ICON_5G)) { 337 icon = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA; 338 } else if (kv[1].equals(ICON_5G_PLUS)) { 339 icon = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED; 340 } else { 341 if (DBG) loge("Invalid 5G icon = " + kv[1]); 342 } 343 tempRules.put(kv[0], new OverrideTimerRule(kv[0], icon)); 344 } 345 } 346 // Ensure all states have an associated OverrideTimerRule and icon 347 for (String state : ALL_STATES) { 348 if (!tempRules.containsKey(state)) { 349 tempRules.put(state, new OverrideTimerRule( 350 state, TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE)); 351 } 352 } 353 354 if (!TextUtils.isEmpty(timers)) { 355 // Format: "FROM_STATE,TO_STATE,DURATION;FROM_STATE_2,TO_STATE_2,DURATION_2" 356 for (String triple : timers.trim().split(";")) { 357 String[] kv = (triple.trim().toLowerCase()).split(","); 358 if (kv.length != 3) { 359 if (DBG) loge("Invalid 5G icon timer configuration, config = " + triple); 360 continue; 361 } 362 int duration; 363 try { 364 duration = Integer.parseInt(kv[2]); 365 } catch (NumberFormatException e) { 366 continue; 367 } 368 if (kv[0].equals(STATE_ANY)) { 369 for (String state : ALL_STATES) { 370 OverrideTimerRule node = tempRules.get(state); 371 node.addTimer(kv[1], duration); 372 } 373 } else { 374 OverrideTimerRule node = tempRules.get(kv[0]); 375 node.addTimer(kv[1], duration); 376 } 377 } 378 } 379 380 if (!TextUtils.isEmpty(secondaryTimers)) { 381 // Format: "PRIMARY_STATE,TO_STATE,DURATION;PRIMARY_STATE_2,TO_STATE_2,DURATION_2" 382 for (String triple : secondaryTimers.trim().split(";")) { 383 String[] kv = (triple.trim().toLowerCase()).split(","); 384 if (kv.length != 3) { 385 if (DBG) { 386 loge("Invalid 5G icon secondary timer configuration, config = " + triple); 387 } 388 continue; 389 } 390 int duration; 391 try { 392 duration = Integer.parseInt(kv[2]); 393 } catch (NumberFormatException e) { 394 continue; 395 } 396 if (kv[0].equals(STATE_ANY)) { 397 for (String state : ALL_STATES) { 398 OverrideTimerRule node = tempRules.get(state); 399 node.addSecondaryTimer(kv[1], duration); 400 } 401 } else { 402 OverrideTimerRule node = tempRules.get(kv[0]); 403 node.addSecondaryTimer(kv[1], duration); 404 } 405 } 406 } 407 408 mOverrideTimerRules = tempRules; 409 if (DBG) log("mOverrideTimerRules: " + mOverrideTimerRules); 410 } 411 updateOverrideNetworkType()412 private void updateOverrideNetworkType() { 413 if (mIsPrimaryTimerActive || mIsSecondaryTimerActive) { 414 if (DBG) log("Skip updating override network type since timer is active."); 415 return; 416 } 417 mOverrideNetworkType = getCurrentOverrideNetworkType(); 418 mDisplayInfoController.updateTelephonyDisplayInfo(); 419 } 420 getCurrentOverrideNetworkType()421 private @Annotation.OverrideNetworkType int getCurrentOverrideNetworkType() { 422 int displayNetworkType = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE; 423 int dataNetworkType = getDataNetworkType(); 424 boolean nrNsa = isLte(dataNetworkType) 425 && mPhone.getServiceState().getNrState() != NetworkRegistrationInfo.NR_STATE_NONE; 426 boolean nrSa = dataNetworkType == TelephonyManager.NETWORK_TYPE_NR; 427 428 // NR display is not accurate when physical channel config notifications are off 429 if (mIsPhysicalChannelConfigOn && (nrNsa || nrSa)) { 430 // Process NR display network type 431 displayNetworkType = getNrDisplayType(nrSa); 432 if (displayNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) { 433 // Use LTE values if 5G values aren't defined 434 displayNetworkType = getLteDisplayType(); 435 } 436 } else if (isLte(dataNetworkType)) { 437 // Process LTE display network type 438 displayNetworkType = getLteDisplayType(); 439 } 440 return displayNetworkType; 441 } 442 getNrDisplayType(boolean isNrSa)443 private @Annotation.OverrideNetworkType int getNrDisplayType(boolean isNrSa) { 444 // Don't show 5G icon if preferred network type does not include 5G 445 if ((mPhone.getCachedAllowedNetworkTypesBitmask() 446 & TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) { 447 return TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE; 448 } 449 // Icon display keys in order of priority 450 List<String> keys = new ArrayList<>(); 451 if (isNrSa && isNrAdvanced()) { 452 keys.add(STATE_CONNECTED_NR_ADVANCED); 453 } else { 454 switch (mPhone.getServiceState().getNrState()) { 455 case NetworkRegistrationInfo.NR_STATE_CONNECTED: 456 if (isNrAdvanced()) { 457 keys.add(STATE_CONNECTED_NR_ADVANCED); 458 } 459 keys.add(STATE_CONNECTED); 460 break; 461 case NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED: 462 keys.add(isPhysicalLinkActive() ? STATE_NOT_RESTRICTED_RRC_CON 463 : STATE_NOT_RESTRICTED_RRC_IDLE); 464 break; 465 case NetworkRegistrationInfo.NR_STATE_RESTRICTED: 466 keys.add(STATE_RESTRICTED); 467 break; 468 } 469 } 470 471 for (String key : keys) { 472 OverrideTimerRule rule = mOverrideTimerRules.get(key); 473 if (rule != null && rule.mOverrideType 474 != TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) { 475 return rule.mOverrideType; 476 } 477 } 478 return TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE; 479 } 480 getLteDisplayType()481 private @Annotation.OverrideNetworkType int getLteDisplayType() { 482 int value = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE; 483 if ((getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA 484 || mPhone.getServiceState().isUsingCarrierAggregation()) 485 && (IntStream.of(mPhone.getServiceState().getCellBandwidths()).sum() 486 > mLtePlusThresholdBandwidth)) { 487 value = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA; 488 } 489 if (isLteEnhancedAvailable()) { 490 value = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO; 491 } 492 return value; 493 } 494 isLteEnhancedAvailable()495 private boolean isLteEnhancedAvailable() { 496 if (TextUtils.isEmpty(mLteEnhancedPattern)) { 497 return false; 498 } 499 Pattern stringPattern = Pattern.compile(mLteEnhancedPattern); 500 for (String opName : new String[] {mPhone.getServiceState().getOperatorAlphaLongRaw(), 501 mPhone.getServiceState().getOperatorAlphaShortRaw()}) { 502 if (!TextUtils.isEmpty(opName)) { 503 Matcher matcher = stringPattern.matcher(opName); 504 if (matcher.find()) { 505 return true; 506 } 507 } 508 } 509 return false; 510 } 511 512 /** 513 * The parent state for all other states. 514 */ 515 private final class DefaultState extends State { 516 @Override processMessage(Message msg)517 public boolean processMessage(Message msg) { 518 if (DBG) log("DefaultState: process " + getEventName(msg.what)); 519 switch (msg.what) { 520 case EVENT_UPDATE: 521 case EVENT_PREFERRED_NETWORK_MODE_CHANGED: 522 resetAllTimers(); 523 transitionToCurrentState(); 524 break; 525 case EVENT_QUIT: 526 resetAllTimers(); 527 unRegisterForAllEvents(); 528 quit(); 529 break; 530 case EVENT_INITIALIZE: 531 // The reason that we do it here is because some of the works below requires 532 // other modules (e.g. DcTracker, ServiceStateTracker), which is not created 533 // yet when NetworkTypeController is created. 534 registerForAllEvents(); 535 parseCarrierConfigs(); 536 break; 537 case EVENT_PCO_DATA_CHANGED: 538 handlePcoData((AsyncResult) msg.obj); 539 break; 540 case EVENT_DATA_RAT_CHANGED: 541 case EVENT_NR_STATE_CHANGED: 542 case EVENT_NR_FREQUENCY_CHANGED: 543 case EVENT_BANDWIDTH_CHANGED: 544 // ignored 545 break; 546 case EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED: 547 if (isUsingPhysicalChannelConfigForRrcDetection()) { 548 mPhysicalLinkState = getPhysicalLinkStateFromPhysicalChannelConfig(); 549 } 550 break; 551 case EVENT_PHYSICAL_LINK_STATE_CHANGED: 552 AsyncResult ar = (AsyncResult) msg.obj; 553 mPhysicalLinkState = (int) ar.result; 554 break; 555 case EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED: 556 AsyncResult result = (AsyncResult) msg.obj; 557 mIsPhysicalChannelConfigOn = (boolean) result.result; 558 if (DBG) { 559 log("mIsPhysicalChannelConfigOn changed to: " + mIsPhysicalChannelConfigOn); 560 } 561 if (!mIsPhysicalChannelConfigOn) { 562 resetAllTimers(); 563 } 564 transitionToCurrentState(); 565 break; 566 case EVENT_CARRIER_CONFIG_CHANGED: 567 parseCarrierConfigs(); 568 resetAllTimers(); 569 transitionToCurrentState(); 570 break; 571 case EVENT_PRIMARY_TIMER_EXPIRED: 572 transitionWithSecondaryTimerTo((IState) msg.obj); 573 break; 574 case EVENT_SECONDARY_TIMER_EXPIRED: 575 mIsSecondaryTimerActive = false; 576 mSecondaryTimerState = ""; 577 updateTimers(); 578 updateOverrideNetworkType(); 579 break; 580 case EVENT_RADIO_OFF_OR_UNAVAILABLE: 581 resetAllTimers(); 582 transitionTo(mLegacyState); 583 break; 584 case EVENT_DATA_CALL_LIST_CHANGED: 585 ar = (AsyncResult) msg.obj; 586 handleDataCallList((List<DataCallResponse>) ar.result); 587 break; 588 default: 589 throw new RuntimeException("Received invalid event: " + msg.what); 590 } 591 return HANDLED; 592 } 593 } 594 595 private final DefaultState mDefaultState = new DefaultState(); 596 597 /** 598 * Device does not have NR available, due to any of the below reasons: 599 * <ul> 600 * <li> LTE cell does not support EN-DC 601 * <li> LTE cell supports EN-DC, but the use of NR is restricted 602 * <li> Data network type is not LTE, NR NSA, or NR SA 603 * </ul> 604 * This is the initial state. 605 */ 606 private final class LegacyState extends State { 607 private Boolean mIsNrRestricted = false; 608 609 @Override enter()610 public void enter() { 611 if (DBG) log("Entering LegacyState"); 612 updateTimers(); 613 updateOverrideNetworkType(); 614 if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) { 615 mIsNrRestricted = isNrRestricted(); 616 mPreviousState = getName(); 617 } 618 } 619 620 @Override processMessage(Message msg)621 public boolean processMessage(Message msg) { 622 if (DBG) log("LegacyState: process " + getEventName(msg.what)); 623 updateTimers(); 624 int rat = getDataNetworkType(); 625 switch (msg.what) { 626 case EVENT_DATA_RAT_CHANGED: 627 if (rat == TelephonyManager.NETWORK_TYPE_NR || isLte(rat) && isNrConnected()) { 628 transitionTo(mNrConnectedState); 629 } else if (isLte(rat) && isNrNotRestricted()) { 630 transitionWithTimerTo(isPhysicalLinkActive() 631 ? mLteConnectedState : mIdleState); 632 } else { 633 if (!isLte(rat)) { 634 // Rat is 3G or 2G, and it doesn't need NR timer. 635 resetAllTimers(); 636 } 637 updateOverrideNetworkType(); 638 } 639 mIsNrRestricted = isNrRestricted(); 640 break; 641 case EVENT_NR_STATE_CHANGED: 642 if (isNrConnected()) { 643 transitionTo(mNrConnectedState); 644 } else if (isLte(rat) && isNrNotRestricted()) { 645 transitionWithTimerTo(isPhysicalLinkActive() 646 ? mLteConnectedState : mIdleState); 647 } else if (isLte(rat) && isNrRestricted()) { 648 updateOverrideNetworkType(); 649 } 650 mIsNrRestricted = isNrRestricted(); 651 break; 652 case EVENT_NR_FREQUENCY_CHANGED: 653 // ignored 654 break; 655 case EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED: 656 if (isUsingPhysicalChannelConfigForRrcDetection()) { 657 mPhysicalLinkState = getPhysicalLinkStateFromPhysicalChannelConfig(); 658 if (mIsTimerResetEnabledForLegacyStateRRCIdle && !isPhysicalLinkActive()) { 659 resetAllTimers(); 660 } 661 } 662 // Update in case of LTE/LTE+ switch 663 updateOverrideNetworkType(); 664 break; 665 case EVENT_PHYSICAL_LINK_STATE_CHANGED: 666 AsyncResult ar = (AsyncResult) msg.obj; 667 mPhysicalLinkState = (int) ar.result; 668 if (mIsTimerResetEnabledForLegacyStateRRCIdle && !isPhysicalLinkActive()) { 669 resetAllTimers(); 670 updateOverrideNetworkType(); 671 } 672 break; 673 default: 674 return NOT_HANDLED; 675 } 676 if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) { 677 mPreviousState = getName(); 678 } 679 return HANDLED; 680 } 681 682 @Override getName()683 public String getName() { 684 return mIsNrRestricted ? STATE_RESTRICTED : STATE_LEGACY; 685 } 686 } 687 688 private final LegacyState mLegacyState = new LegacyState(); 689 690 /** 691 * Device does not have any physical connection with the cell (RRC idle). 692 */ 693 private final class IdleState extends State { 694 @Override enter()695 public void enter() { 696 if (DBG) log("Entering IdleState"); 697 updateTimers(); 698 updateOverrideNetworkType(); 699 if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) { 700 mPreviousState = getName(); 701 } 702 } 703 704 @Override processMessage(Message msg)705 public boolean processMessage(Message msg) { 706 if (DBG) log("IdleState: process " + getEventName(msg.what)); 707 updateTimers(); 708 switch (msg.what) { 709 case EVENT_DATA_RAT_CHANGED: 710 int rat = getDataNetworkType(); 711 if (rat == TelephonyManager.NETWORK_TYPE_NR) { 712 transitionTo(mNrConnectedState); 713 } else if (!isLte(rat) || !isNrNotRestricted()) { 714 transitionWithTimerTo(mLegacyState); 715 } 716 break; 717 case EVENT_NR_STATE_CHANGED: 718 if (isNrConnected()) { 719 transitionTo(mNrConnectedState); 720 } else if (!isNrNotRestricted()) { 721 transitionWithTimerTo(mLegacyState); 722 } 723 break; 724 case EVENT_NR_FREQUENCY_CHANGED: 725 // ignore 726 break; 727 case EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED: 728 if (isUsingPhysicalChannelConfigForRrcDetection()) { 729 mPhysicalLinkState = getPhysicalLinkStateFromPhysicalChannelConfig(); 730 if (isNrNotRestricted()) { 731 // NOT_RESTRICTED_RRC_IDLE -> NOT_RESTRICTED_RRC_CON 732 if (isPhysicalLinkActive()) { 733 transitionWithTimerTo(mLteConnectedState); 734 break; 735 } 736 } else { 737 log("NR state changed. Sending EVENT_NR_STATE_CHANGED"); 738 sendMessage(EVENT_NR_STATE_CHANGED); 739 } 740 } 741 // Update in case of LTE/LTE+ switch 742 updateOverrideNetworkType(); 743 break; 744 case EVENT_PHYSICAL_LINK_STATE_CHANGED: 745 AsyncResult ar = (AsyncResult) msg.obj; 746 mPhysicalLinkState = (int) ar.result; 747 if (isNrNotRestricted()) { 748 // NOT_RESTRICTED_RRC_IDLE -> NOT_RESTRICTED_RRC_CON 749 if (isPhysicalLinkActive()) { 750 transitionWithTimerTo(mLteConnectedState); 751 } 752 } else { 753 log("NR state changed. Sending EVENT_NR_STATE_CHANGED"); 754 sendMessage(EVENT_NR_STATE_CHANGED); 755 } 756 break; 757 default: 758 return NOT_HANDLED; 759 } 760 if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) { 761 mPreviousState = getName(); 762 } 763 return HANDLED; 764 } 765 766 @Override getName()767 public String getName() { 768 return STATE_NOT_RESTRICTED_RRC_IDLE; 769 } 770 } 771 772 private final IdleState mIdleState = new IdleState(); 773 774 /** 775 * Device is connected to LTE as the primary cell (RRC connected). 776 */ 777 private final class LteConnectedState extends State { 778 @Override enter()779 public void enter() { 780 if (DBG) log("Entering LteConnectedState"); 781 updateTimers(); 782 updateOverrideNetworkType(); 783 if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) { 784 mPreviousState = getName(); 785 } 786 } 787 788 @Override processMessage(Message msg)789 public boolean processMessage(Message msg) { 790 if (DBG) log("LteConnectedState: process " + getEventName(msg.what)); 791 updateTimers(); 792 switch (msg.what) { 793 case EVENT_DATA_RAT_CHANGED: 794 int rat = getDataNetworkType(); 795 if (rat == TelephonyManager.NETWORK_TYPE_NR) { 796 transitionTo(mNrConnectedState); 797 } else if (!isLte(rat) || !isNrNotRestricted()) { 798 transitionWithTimerTo(mLegacyState); 799 } 800 break; 801 case EVENT_NR_STATE_CHANGED: 802 if (isNrConnected()) { 803 transitionTo(mNrConnectedState); 804 } else if (!isNrNotRestricted()) { 805 transitionWithTimerTo(mLegacyState); 806 } 807 break; 808 case EVENT_NR_FREQUENCY_CHANGED: 809 // ignore 810 break; 811 case EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED: 812 if (isUsingPhysicalChannelConfigForRrcDetection()) { 813 mPhysicalLinkState = getPhysicalLinkStateFromPhysicalChannelConfig(); 814 if (isNrNotRestricted()) { 815 // NOT_RESTRICTED_RRC_CON -> NOT_RESTRICTED_RRC_IDLE 816 if (!isPhysicalLinkActive()) { 817 transitionWithTimerTo(mIdleState); 818 break; 819 } 820 } else { 821 log("NR state changed. Sending EVENT_NR_STATE_CHANGED"); 822 sendMessage(EVENT_NR_STATE_CHANGED); 823 } 824 } 825 // Update in case of LTE/LTE+ switch 826 updateOverrideNetworkType(); 827 break; 828 case EVENT_PHYSICAL_LINK_STATE_CHANGED: 829 AsyncResult ar = (AsyncResult) msg.obj; 830 mPhysicalLinkState = (int) ar.result; 831 if (isNrNotRestricted()) { 832 // NOT_RESTRICTED_RRC_CON -> NOT_RESTRICTED_RRC_IDLE 833 if (!isPhysicalLinkActive()) { 834 transitionWithTimerTo(mIdleState); 835 } 836 } else { 837 log("NR state changed. Sending EVENT_NR_STATE_CHANGED"); 838 sendMessage(EVENT_NR_STATE_CHANGED); 839 } 840 break; 841 default: 842 return NOT_HANDLED; 843 } 844 if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) { 845 mPreviousState = getName(); 846 } 847 return HANDLED; 848 } 849 850 @Override getName()851 public String getName() { 852 return STATE_NOT_RESTRICTED_RRC_CON; 853 } 854 } 855 856 private final LteConnectedState mLteConnectedState = new LteConnectedState(); 857 858 /** 859 * Device is connected to 5G NR as the secondary cell. 860 */ 861 private final class NrConnectedState extends State { 862 private Boolean mIsNrAdvanced = false; 863 864 @Override enter()865 public void enter() { 866 if (DBG) log("Entering NrConnectedState"); 867 updateTimers(); 868 updateOverrideNetworkType(); 869 if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) { 870 mIsNrAdvanced = isNrAdvanced(); 871 mPreviousState = getName(); 872 } 873 } 874 875 @Override processMessage(Message msg)876 public boolean processMessage(Message msg) { 877 if (DBG) log("NrConnectedState: process " + getEventName(msg.what)); 878 updateTimers(); 879 int rat = getDataNetworkType(); 880 AsyncResult ar; 881 switch (msg.what) { 882 case EVENT_DATA_RAT_CHANGED: 883 if (rat == TelephonyManager.NETWORK_TYPE_NR || isLte(rat) && isNrConnected()) { 884 updateOverrideNetworkType(); 885 } else if (isLte(rat) && isNrNotRestricted()) { 886 transitionWithTimerTo(isPhysicalLinkActive() 887 ? mLteConnectedState : mIdleState); 888 } else { 889 transitionWithTimerTo(mLegacyState); 890 } 891 break; 892 case EVENT_NR_STATE_CHANGED: 893 if (isLte(rat) && isNrNotRestricted()) { 894 transitionWithTimerTo(isPhysicalLinkActive() 895 ? mLteConnectedState : mIdleState); 896 } else if (rat != TelephonyManager.NETWORK_TYPE_NR && !isNrConnected()) { 897 transitionWithTimerTo(mLegacyState); 898 } 899 break; 900 case EVENT_PCO_DATA_CHANGED: 901 handlePcoData((AsyncResult) msg.obj); 902 updateNrAdvancedState(); 903 break; 904 case EVENT_DATA_CALL_LIST_CHANGED: 905 ar = (AsyncResult) msg.obj; 906 handleDataCallList((List<DataCallResponse>) ar.result); 907 updateNrAdvancedState(); 908 break; 909 case EVENT_NR_FREQUENCY_CHANGED: 910 case EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED: 911 if (isUsingPhysicalChannelConfigForRrcDetection()) { 912 mPhysicalLinkState = getPhysicalLinkStateFromPhysicalChannelConfig(); 913 } 914 updateNrAdvancedState(); 915 break; 916 case EVENT_PHYSICAL_LINK_STATE_CHANGED: 917 ar = (AsyncResult) msg.obj; 918 mPhysicalLinkState = (int) ar.result; 919 if (!isNrConnected()) { 920 log("NR state changed. Sending EVENT_NR_STATE_CHANGED"); 921 sendMessage(EVENT_NR_STATE_CHANGED); 922 } 923 break; 924 case EVENT_BANDWIDTH_CHANGED: 925 updateNrAdvancedState(); 926 break; 927 default: 928 return NOT_HANDLED; 929 } 930 if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) { 931 mPreviousState = getName(); 932 } 933 return HANDLED; 934 } 935 936 @Override getName()937 public String getName() { 938 return mIsNrAdvanced ? STATE_CONNECTED_NR_ADVANCED : STATE_CONNECTED; 939 } 940 updateNrAdvancedState()941 private void updateNrAdvancedState() { 942 if (!isNrConnected()) { 943 log("NR state changed. Sending EVENT_NR_STATE_CHANGED"); 944 sendMessage(EVENT_NR_STATE_CHANGED); 945 return; 946 } 947 if (!isNrAdvanced()) { 948 // STATE_CONNECTED_NR_ADVANCED -> STATE_CONNECTED 949 transitionWithTimerTo(mNrConnectedState); 950 } else { 951 // STATE_CONNECTED -> STATE_CONNECTED_NR_ADVANCED 952 transitionTo(mNrConnectedState); 953 } 954 mIsNrAdvanced = isNrAdvanced(); 955 } 956 } 957 958 private final NrConnectedState mNrConnectedState = new NrConnectedState(); 959 960 // TODO: This is a temporarily solution for S. Ideally PCO and data call list changed event 961 // should not be exposed outside of the data modules. PCO for 5G icon has been well 962 // supported in the new data architecture in T. This temp solution must be removed in T 963 // along with other old data modules. handleDataCallList(@onNull List<DataCallResponse> dataCallResponseList)964 private void handleDataCallList(@NonNull List<DataCallResponse> dataCallResponseList) { 965 if (mNrAdvancedCapablePcoId == 0) return; 966 mActiveDcCidSet.clear(); 967 for (DataCallResponse response : dataCallResponseList) { 968 if (response.getLinkStatus() == DataCallResponse.LINK_STATUS_ACTIVE 969 || response.getLinkStatus() == DataCallResponse.LINK_STATUS_DORMANT) { 970 mActiveDcCidSet.add(response.getId()); 971 } 972 } 973 974 log("Active cids=" + mActiveDcCidSet); 975 boolean nrAdvancedAllowedByPco = mPcoDataMap.values().stream() 976 .anyMatch(pco -> pco.contents[pco.contents.length - 1] == 1 977 && mActiveDcCidSet.contains(pco.cid)); 978 if (mIsNrAdvancedAllowedByPco != nrAdvancedAllowedByPco) { 979 mIsNrAdvancedAllowedByPco = nrAdvancedAllowedByPco; 980 log("nrAdvancedAllowedByPco=" + nrAdvancedAllowedByPco); 981 } 982 } 983 984 // TODO: This is a temporarily solution for S. Ideally PCO and data call list changed event 985 // should not be exposed outside of the data modules. PCO for 5G icon has been well 986 // supported in the new data architecture in T. This temp solution must be removed in T 987 // along with other old data modules. handlePcoData(AsyncResult ar)988 private void handlePcoData(AsyncResult ar) { 989 if (mNrAdvancedCapablePcoId == 0) return; 990 if (ar.exception != null) { 991 loge("PCO_DATA exception: " + ar.exception); 992 return; 993 } 994 PcoData pcodata = (PcoData) ar.result; 995 if (pcodata == null) { 996 return; 997 } 998 log("EVENT_PCO_DATA_CHANGED: pco data: " + pcodata + ", " 999 + IccUtils.bytesToHexString(pcodata.contents)); 1000 if (pcodata.pcoId != mNrAdvancedCapablePcoId || pcodata.contents == null 1001 || pcodata.contents.length == 0) { 1002 log("Dropped irrelevant PCO data"); 1003 return; 1004 } 1005 1006 mPcoDataMap.put(pcodata.cid, pcodata); 1007 boolean nrAdvancedAllowedByPco = mPcoDataMap.values().stream() 1008 .anyMatch(pco -> pco.contents[pco.contents.length - 1] == 1 1009 && mActiveDcCidSet.contains(pco.cid)); 1010 if (mIsNrAdvancedAllowedByPco != nrAdvancedAllowedByPco) { 1011 mIsNrAdvancedAllowedByPco = nrAdvancedAllowedByPco; 1012 log("nrAdvancedAllowedByPco=" + nrAdvancedAllowedByPco); 1013 } 1014 } 1015 transitionWithTimerTo(IState destState)1016 private void transitionWithTimerTo(IState destState) { 1017 String destName = destState.getName(); 1018 OverrideTimerRule rule = mOverrideTimerRules.get(mPreviousState); 1019 if (rule != null && rule.getTimer(destName) > 0) { 1020 if (DBG) log("Primary timer started for state: " + mPreviousState); 1021 mPrimaryTimerState = mPreviousState; 1022 mPreviousState = getCurrentState().getName(); 1023 mIsPrimaryTimerActive = true; 1024 sendMessageDelayed(EVENT_PRIMARY_TIMER_EXPIRED, destState, 1025 rule.getTimer(destName) * 1000); 1026 } 1027 transitionTo(destState); 1028 } 1029 transitionWithSecondaryTimerTo(IState destState)1030 private void transitionWithSecondaryTimerTo(IState destState) { 1031 String currentName = getCurrentState().getName(); 1032 OverrideTimerRule rule = mOverrideTimerRules.get(mPrimaryTimerState); 1033 if (rule != null && rule.getSecondaryTimer(currentName) > 0) { 1034 if (DBG) log("Secondary timer started for state: " + currentName); 1035 mSecondaryTimerState = currentName; 1036 mPreviousState = currentName; 1037 mIsSecondaryTimerActive = true; 1038 sendMessageDelayed(EVENT_SECONDARY_TIMER_EXPIRED, destState, 1039 rule.getSecondaryTimer(currentName) * 1000); 1040 } 1041 mIsPrimaryTimerActive = false; 1042 transitionTo(getCurrentState()); 1043 } 1044 transitionToCurrentState()1045 private void transitionToCurrentState() { 1046 int dataRat = getDataNetworkType(); 1047 IState transitionState; 1048 if (dataRat == TelephonyManager.NETWORK_TYPE_NR || isNrConnected()) { 1049 transitionState = mNrConnectedState; 1050 mPreviousState = isNrAdvanced() ? STATE_CONNECTED_NR_ADVANCED : STATE_CONNECTED; 1051 } else if (isLte(dataRat) && isNrNotRestricted()) { 1052 if (isPhysicalLinkActive()) { 1053 transitionState = mLteConnectedState; 1054 mPreviousState = STATE_NOT_RESTRICTED_RRC_CON; 1055 } else { 1056 transitionState = mIdleState; 1057 mPreviousState = STATE_NOT_RESTRICTED_RRC_IDLE; 1058 } 1059 } else { 1060 transitionState = mLegacyState; 1061 mPreviousState = isNrRestricted() ? STATE_RESTRICTED : STATE_LEGACY; 1062 } 1063 if (!transitionState.equals(getCurrentState())) { 1064 transitionTo(transitionState); 1065 } else { 1066 updateOverrideNetworkType(); 1067 } 1068 } 1069 updateTimers()1070 private void updateTimers() { 1071 if ((mPhone.getCachedAllowedNetworkTypesBitmask() 1072 & TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) { 1073 resetAllTimers(); 1074 return; 1075 } 1076 1077 String currentState = getCurrentState().getName(); 1078 1079 if (mIsPrimaryTimerActive && getOverrideNetworkType() == getCurrentOverrideNetworkType()) { 1080 // remove primary timer if device goes back to the original icon 1081 if (DBG) { 1082 log("Remove primary timer since icon of primary state and current icon equal: " 1083 + mPrimaryTimerState); 1084 } 1085 removeMessages(EVENT_PRIMARY_TIMER_EXPIRED); 1086 mIsPrimaryTimerActive = false; 1087 mPrimaryTimerState = ""; 1088 } 1089 1090 if (mIsSecondaryTimerActive && !mSecondaryTimerState.equals(currentState)) { 1091 // remove secondary timer if devices is no longer in secondary timer state 1092 if (DBG) { 1093 log("Remove secondary timer since current state (" + currentState 1094 + ") is no longer secondary timer state (" + mSecondaryTimerState + ")."); 1095 } 1096 removeMessages(EVENT_SECONDARY_TIMER_EXPIRED); 1097 mIsSecondaryTimerActive = false; 1098 mSecondaryTimerState = ""; 1099 } 1100 1101 if (currentState.equals(STATE_CONNECTED_NR_ADVANCED)) { 1102 resetAllTimers(); 1103 } 1104 1105 int rat = getDataNetworkType(); 1106 if (!isLte(rat) && rat != TelephonyManager.NETWORK_TYPE_NR) { 1107 // Rat is 3G or 2G, and it doesn't need NR timer. 1108 resetAllTimers(); 1109 } 1110 } 1111 resetAllTimers()1112 private void resetAllTimers() { 1113 if (DBG) { 1114 log("Remove all timers"); 1115 } 1116 removeMessages(EVENT_PRIMARY_TIMER_EXPIRED); 1117 removeMessages(EVENT_SECONDARY_TIMER_EXPIRED); 1118 mIsPrimaryTimerActive = false; 1119 mIsSecondaryTimerActive = false; 1120 mPrimaryTimerState = ""; 1121 mSecondaryTimerState = ""; 1122 } 1123 1124 /** 1125 * Private class defining timer rules between states to prevent flickering. These rules are 1126 * created in {@link #parseCarrierConfigs()} based on various carrier configs. 1127 */ 1128 private class OverrideTimerRule { 1129 /** The 5G state this timer rule applies for. See {@link #ALL_STATES}. */ 1130 final String mState; 1131 1132 /** 1133 * The override network type associated with this 5G state. This is the icon that will be 1134 * displayed on the status bar. An override type of NONE will display the LTE value instead. 1135 */ 1136 final int mOverrideType; 1137 1138 /** 1139 * A map of destination states and associated timers. If the 5G state changes from mState 1140 * to the destination state, keep the override type until either the primary timer expires 1141 * or mState is regained. 1142 */ 1143 final Map<String, Integer> mPrimaryTimers; 1144 1145 /** 1146 * A map of secondary states and associated timers. After the primary timer expires, keep 1147 * the override type until either the secondary timer expires or the device is no longer in 1148 * the secondary state. 1149 */ 1150 final Map<String, Integer> mSecondaryTimers; 1151 OverrideTimerRule(String state, int overrideType)1152 OverrideTimerRule(String state, int overrideType) { 1153 mState = state; 1154 mOverrideType = overrideType; 1155 mPrimaryTimers = new HashMap<>(); 1156 mSecondaryTimers = new HashMap<>(); 1157 } 1158 1159 /** 1160 * Add a primary timer. 1161 * @param destination Transitions from mState to the destination state. 1162 * @param duration How long to keep the override type after transition to destination state. 1163 */ addTimer(String destination, int duration)1164 public void addTimer(String destination, int duration) { 1165 mPrimaryTimers.put(destination, duration); 1166 } 1167 1168 /** 1169 * Add a secondary timer 1170 * @param secondaryState Stays in secondaryState after primary timer expires. 1171 * @param duration How long to keep the override type while in secondaryState. 1172 */ addSecondaryTimer(String secondaryState, int duration)1173 public void addSecondaryTimer(String secondaryState, int duration) { 1174 mSecondaryTimers.put(secondaryState, duration); 1175 } 1176 1177 /** 1178 * @return Primary timer duration from mState to destination state, or 0 if not defined. 1179 */ getTimer(String destination)1180 public int getTimer(String destination) { 1181 Integer timer = mPrimaryTimers.get(destination); 1182 timer = timer == null ? mPrimaryTimers.get(STATE_ANY) : timer; 1183 return timer == null ? 0 : timer; 1184 } 1185 1186 /** 1187 * @return Secondary timer duration for secondaryState, or 0 if not defined. 1188 */ getSecondaryTimer(String secondaryState)1189 public int getSecondaryTimer(String secondaryState) { 1190 Integer secondaryTimer = mSecondaryTimers.get(secondaryState); 1191 secondaryTimer = secondaryTimer == null 1192 ? mSecondaryTimers.get(STATE_ANY) : secondaryTimer; 1193 return secondaryTimer == null ? 0 : secondaryTimer; 1194 } 1195 1196 @Override toString()1197 public String toString() { 1198 return "{mState=" + mState 1199 + ", mOverrideType=" 1200 + TelephonyDisplayInfo.overrideNetworkTypeToString(mOverrideType) 1201 + ", mPrimaryTimers=" + mPrimaryTimers 1202 + ", mSecondaryTimers=" + mSecondaryTimers + "}"; 1203 } 1204 } 1205 isNrConnected()1206 private boolean isNrConnected() { 1207 return mPhone.getServiceState().getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED; 1208 } 1209 isNrNotRestricted()1210 private boolean isNrNotRestricted() { 1211 return mPhone.getServiceState().getNrState() 1212 == NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED; 1213 } 1214 isNrRestricted()1215 private boolean isNrRestricted() { 1216 return mPhone.getServiceState().getNrState() 1217 == NetworkRegistrationInfo.NR_STATE_RESTRICTED; 1218 } 1219 1220 /** 1221 * @return {@code true} if the device is in NR advanced mode (i.e. 5G+). 1222 */ isNrAdvanced()1223 private boolean isNrAdvanced() { 1224 // Check PCO requirement. For carriers using PCO to indicate whether the data connection is 1225 // NR advanced capable, mNrAdvancedCapablePcoId should be configured to non-zero. 1226 if (mNrAdvancedCapablePcoId > 0 && !mIsNrAdvancedAllowedByPco) { 1227 return false; 1228 } 1229 1230 // Check if NR advanced is enabled when the device is roaming. Some carriers disable it 1231 // while the device is roaming. 1232 if (mPhone.getServiceState().getDataRoaming() && !mEnableNrAdvancedWhileRoaming) { 1233 return false; 1234 } 1235 1236 // Check if meeting minimum bandwidth requirement. For most carriers, there is no minimum 1237 // bandwidth requirement and mNrAdvancedThresholdBandwidth is 0. 1238 if (IntStream.of(mPhone.getServiceState().getCellBandwidths()).sum() 1239 < mNrAdvancedThresholdBandwidth) { 1240 return false; 1241 } 1242 1243 // If all above tests passed, then check if the device is using millimeter wave bands or 1244 // carrier designated bands. 1245 return isNrMmwave() || isAdditionalNrAdvancedBand(); 1246 } 1247 isNrMmwave()1248 private boolean isNrMmwave() { 1249 return mPhone.getServiceState().getNrFrequencyRange() 1250 == ServiceState.FREQUENCY_RANGE_MMWAVE; 1251 } 1252 isAdditionalNrAdvancedBand()1253 private boolean isAdditionalNrAdvancedBand() { 1254 List<PhysicalChannelConfig> physicalChannelConfigList = 1255 mPhone.getServiceStateTracker().getPhysicalChannelConfigList(); 1256 if (ArrayUtils.isEmpty(mAdditionalNrAdvancedBandsList) 1257 || physicalChannelConfigList == null) { 1258 return false; 1259 } 1260 for (PhysicalChannelConfig item : physicalChannelConfigList) { 1261 if (item.getNetworkType() == TelephonyManager.NETWORK_TYPE_NR 1262 && ArrayUtils.contains(mAdditionalNrAdvancedBandsList, item.getBand())) { 1263 return true; 1264 } 1265 } 1266 return false; 1267 } 1268 isLte(int rat)1269 private boolean isLte(int rat) { 1270 return rat == TelephonyManager.NETWORK_TYPE_LTE 1271 || rat == TelephonyManager.NETWORK_TYPE_LTE_CA; 1272 } 1273 isPhysicalLinkActive()1274 private boolean isPhysicalLinkActive() { 1275 return mPhysicalLinkState == DcController.PHYSICAL_LINK_ACTIVE; 1276 } 1277 getPhysicalLinkStateFromPhysicalChannelConfig()1278 private int getPhysicalLinkStateFromPhysicalChannelConfig() { 1279 List<PhysicalChannelConfig> physicalChannelConfigList = 1280 mPhone.getServiceStateTracker().getPhysicalChannelConfigList(); 1281 return (physicalChannelConfigList == null || physicalChannelConfigList.isEmpty()) 1282 ? DcController.PHYSICAL_LINK_NOT_ACTIVE : DcController.PHYSICAL_LINK_ACTIVE; 1283 } 1284 getDataNetworkType()1285 private int getDataNetworkType() { 1286 NetworkRegistrationInfo nri = mPhone.getServiceState().getNetworkRegistrationInfo( 1287 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 1288 return nri == null ? TelephonyManager.NETWORK_TYPE_UNKNOWN 1289 : nri.getAccessNetworkTechnology(); 1290 } 1291 getEventName(int event)1292 private String getEventName(int event) { 1293 try { 1294 return sEvents[event]; 1295 } catch (ArrayIndexOutOfBoundsException e) { 1296 return "EVENT_NOT_DEFINED"; 1297 } 1298 } 1299 isUsingPhysicalChannelConfigForRrcDetection()1300 private boolean isUsingPhysicalChannelConfigForRrcDetection() { 1301 return mIsPhysicalChannelConfig16Supported && !mIsUsingUserDataForRrcDetection; 1302 } 1303 log(String s)1304 protected void log(String s) { 1305 Rlog.d(TAG, "[" + mPhone.getPhoneId() + "] " + s); 1306 } 1307 loge(String s)1308 protected void loge(String s) { 1309 Rlog.e(TAG, "[" + mPhone.getPhoneId() + "] " + s); 1310 } 1311 1312 @Override toString()1313 public String toString() { 1314 return "mOverrideTimerRules=" + mOverrideTimerRules.toString() 1315 + ", mLteEnhancedPattern=" + mLteEnhancedPattern 1316 + ", mIsPhysicalChannelConfigOn=" + mIsPhysicalChannelConfigOn 1317 + ", mIsPrimaryTimerActive=" + mIsPrimaryTimerActive 1318 + ", mIsSecondaryTimerActive=" + mIsSecondaryTimerActive 1319 + ", mPrimaryTimerState=" + mPrimaryTimerState 1320 + ", mSecondaryTimerState=" + mSecondaryTimerState 1321 + ", mPreviousState=" + mPreviousState 1322 + ", misNrAdvanced=" + isNrAdvanced(); 1323 } 1324 1325 @Override dump(FileDescriptor fd, PrintWriter printWriter, String[] args)1326 public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) { 1327 IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " "); 1328 pw.print("NetworkTypeController: "); 1329 super.dump(fd, pw, args); 1330 pw.flush(); 1331 pw.increaseIndent(); 1332 pw.println("mSubId=" + mPhone.getSubId()); 1333 pw.println("mOverrideTimerRules=" + mOverrideTimerRules.toString()); 1334 pw.println("mLteEnhancedPattern=" + mLteEnhancedPattern); 1335 pw.println("mIsPhysicalChannelConfigOn=" + mIsPhysicalChannelConfigOn); 1336 pw.println("mIsPrimaryTimerActive=" + mIsPrimaryTimerActive); 1337 pw.println("mIsSecondaryTimerActive=" + mIsSecondaryTimerActive); 1338 pw.println("mIsTimerRestEnabledForLegacyStateRRCIdle=" 1339 + mIsTimerResetEnabledForLegacyStateRRCIdle); 1340 pw.println("mLtePlusThresholdBandwidth=" + mLtePlusThresholdBandwidth); 1341 pw.println("mPrimaryTimerState=" + mPrimaryTimerState); 1342 pw.println("mSecondaryTimerState=" + mSecondaryTimerState); 1343 pw.println("mPreviousState=" + mPreviousState); 1344 pw.println("mPhysicalLinkState=" + mPhysicalLinkState); 1345 pw.println("mAdditionalNrAdvancedBandsList=" 1346 + Arrays.toString(mAdditionalNrAdvancedBandsList)); 1347 pw.println("mNrAdvancedCapablePcoId=" + mNrAdvancedCapablePcoId); 1348 pw.decreaseIndent(); 1349 pw.flush(); 1350 } 1351 } 1352