1 /* 2 * Copyright (C) 2015 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 package com.android.systemui.statusbar.policy; 17 18 import android.content.Context; 19 import android.content.Intent; 20 import android.database.ContentObserver; 21 import android.net.NetworkCapabilities; 22 import android.os.Handler; 23 import android.os.Looper; 24 import android.provider.Settings.Global; 25 import android.telephony.NetworkRegistrationInfo; 26 import android.telephony.PhoneStateListener; 27 import android.telephony.ServiceState; 28 import android.telephony.SignalStrength; 29 import android.telephony.SubscriptionInfo; 30 import android.telephony.SubscriptionManager; 31 import android.telephony.TelephonyManager; 32 import android.text.TextUtils; 33 import android.util.Log; 34 import android.util.SparseArray; 35 36 import com.android.internal.annotations.VisibleForTesting; 37 import com.android.internal.telephony.TelephonyIntents; 38 import com.android.internal.telephony.cdma.EriInfo; 39 import com.android.settingslib.Utils; 40 import com.android.settingslib.graph.SignalDrawable; 41 import com.android.settingslib.net.SignalStrengthUtil; 42 import com.android.systemui.R; 43 import com.android.systemui.statusbar.policy.NetworkController.IconState; 44 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; 45 import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config; 46 import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults; 47 48 import java.io.PrintWriter; 49 import java.util.BitSet; 50 import java.util.Objects; 51 import java.util.regex.Matcher; 52 import java.util.regex.Pattern; 53 54 55 public class MobileSignalController extends SignalController< 56 MobileSignalController.MobileState, MobileSignalController.MobileIconGroup> { 57 private final TelephonyManager mPhone; 58 private final SubscriptionDefaults mDefaults; 59 private final String mNetworkNameDefault; 60 private final String mNetworkNameSeparator; 61 private final ContentObserver mObserver; 62 @VisibleForTesting 63 final PhoneStateListener mPhoneStateListener; 64 // Save entire info for logging, we only use the id. 65 final SubscriptionInfo mSubscriptionInfo; 66 67 // @VisibleForDemoMode 68 final SparseArray<MobileIconGroup> mNetworkToIconLookup; 69 70 // Since some pieces of the phone state are interdependent we store it locally, 71 // this could potentially become part of MobileState for simplification/complication 72 // of code. 73 private int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN; 74 private int mDataState = TelephonyManager.DATA_DISCONNECTED; 75 private ServiceState mServiceState; 76 private SignalStrength mSignalStrength; 77 private MobileIconGroup mDefaultIcons; 78 private Config mConfig; 79 @VisibleForTesting 80 boolean mInflateSignalStrengths = false; 81 // Some specific carriers have 5GE network which is special LTE CA network. 82 private static final int NETWORK_TYPE_LTE_CA_5GE = TelephonyManager.MAX_NETWORK_TYPE + 1; 83 84 // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't 85 // need listener lists anymore. MobileSignalController(Context context, Config config, boolean hasMobileData, TelephonyManager phone, CallbackHandler callbackHandler, NetworkControllerImpl networkController, SubscriptionInfo info, SubscriptionDefaults defaults, Looper receiverLooper)86 public MobileSignalController(Context context, Config config, boolean hasMobileData, 87 TelephonyManager phone, CallbackHandler callbackHandler, 88 NetworkControllerImpl networkController, SubscriptionInfo info, 89 SubscriptionDefaults defaults, Looper receiverLooper) { 90 super("MobileSignalController(" + info.getSubscriptionId() + ")", context, 91 NetworkCapabilities.TRANSPORT_CELLULAR, callbackHandler, 92 networkController); 93 mNetworkToIconLookup = new SparseArray<>(); 94 mConfig = config; 95 mPhone = phone; 96 mDefaults = defaults; 97 mSubscriptionInfo = info; 98 mPhoneStateListener = new MobilePhoneStateListener(receiverLooper); 99 mNetworkNameSeparator = getStringIfExists(R.string.status_bar_network_name_separator); 100 mNetworkNameDefault = getStringIfExists( 101 com.android.internal.R.string.lockscreen_carrier_default); 102 103 mapIconSets(); 104 105 String networkName = info.getCarrierName() != null ? info.getCarrierName().toString() 106 : mNetworkNameDefault; 107 mLastState.networkName = mCurrentState.networkName = networkName; 108 mLastState.networkNameData = mCurrentState.networkNameData = networkName; 109 mLastState.enabled = mCurrentState.enabled = hasMobileData; 110 mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons; 111 // Get initial data sim state. 112 updateDataSim(); 113 mObserver = new ContentObserver(new Handler(receiverLooper)) { 114 @Override 115 public void onChange(boolean selfChange) { 116 updateTelephony(); 117 } 118 }; 119 } 120 setConfiguration(Config config)121 public void setConfiguration(Config config) { 122 mConfig = config; 123 updateInflateSignalStrength(); 124 mapIconSets(); 125 updateTelephony(); 126 } 127 getDataContentDescription()128 public int getDataContentDescription() { 129 return getIcons().mDataContentDescription; 130 } 131 setAirplaneMode(boolean airplaneMode)132 public void setAirplaneMode(boolean airplaneMode) { 133 mCurrentState.airplaneMode = airplaneMode; 134 notifyListenersIfNecessary(); 135 } 136 setUserSetupComplete(boolean userSetup)137 public void setUserSetupComplete(boolean userSetup) { 138 mCurrentState.userSetup = userSetup; 139 notifyListenersIfNecessary(); 140 } 141 142 @Override updateConnectivity(BitSet connectedTransports, BitSet validatedTransports)143 public void updateConnectivity(BitSet connectedTransports, BitSet validatedTransports) { 144 boolean isValidated = validatedTransports.get(mTransportType); 145 mCurrentState.isDefault = connectedTransports.get(mTransportType); 146 // Only show this as not having connectivity if we are default. 147 mCurrentState.inetCondition = (isValidated || !mCurrentState.isDefault) ? 1 : 0; 148 notifyListenersIfNecessary(); 149 } 150 setCarrierNetworkChangeMode(boolean carrierNetworkChangeMode)151 public void setCarrierNetworkChangeMode(boolean carrierNetworkChangeMode) { 152 mCurrentState.carrierNetworkChangeMode = carrierNetworkChangeMode; 153 updateTelephony(); 154 } 155 156 /** 157 * Start listening for phone state changes. 158 */ registerListener()159 public void registerListener() { 160 mPhone.listen(mPhoneStateListener, 161 PhoneStateListener.LISTEN_SERVICE_STATE 162 | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS 163 | PhoneStateListener.LISTEN_CALL_STATE 164 | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE 165 | PhoneStateListener.LISTEN_DATA_ACTIVITY 166 | PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE); 167 mContext.getContentResolver().registerContentObserver(Global.getUriFor(Global.MOBILE_DATA), 168 true, mObserver); 169 mContext.getContentResolver().registerContentObserver(Global.getUriFor( 170 Global.MOBILE_DATA + mSubscriptionInfo.getSubscriptionId()), 171 true, mObserver); 172 } 173 174 /** 175 * Stop listening for phone state changes. 176 */ unregisterListener()177 public void unregisterListener() { 178 mPhone.listen(mPhoneStateListener, 0); 179 mContext.getContentResolver().unregisterContentObserver(mObserver); 180 } 181 182 /** 183 * Produce a mapping of data network types to icon groups for simple and quick use in 184 * updateTelephony. 185 */ mapIconSets()186 private void mapIconSets() { 187 mNetworkToIconLookup.clear(); 188 189 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyIcons.THREE_G); 190 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyIcons.THREE_G); 191 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_B, TelephonyIcons.THREE_G); 192 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyIcons.THREE_G); 193 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UMTS, TelephonyIcons.THREE_G); 194 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_TD_SCDMA, TelephonyIcons.THREE_G); 195 196 if (!mConfig.showAtLeast3G) { 197 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN, 198 TelephonyIcons.UNKNOWN); 199 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE, TelephonyIcons.E); 200 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA, TelephonyIcons.ONE_X); 201 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyIcons.ONE_X); 202 203 mDefaultIcons = TelephonyIcons.G; 204 } else { 205 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN, 206 TelephonyIcons.THREE_G); 207 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE, 208 TelephonyIcons.THREE_G); 209 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA, 210 TelephonyIcons.THREE_G); 211 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT, 212 TelephonyIcons.THREE_G); 213 mDefaultIcons = TelephonyIcons.THREE_G; 214 } 215 216 MobileIconGroup hGroup = TelephonyIcons.THREE_G; 217 MobileIconGroup hPlusGroup = TelephonyIcons.THREE_G; 218 if (mConfig.hspaDataDistinguishable) { 219 hGroup = TelephonyIcons.H; 220 hPlusGroup = TelephonyIcons.H_PLUS; 221 } 222 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSDPA, hGroup); 223 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSUPA, hGroup); 224 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPA, hGroup); 225 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPAP, hPlusGroup); 226 227 if (mConfig.show4gForLte) { 228 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.FOUR_G); 229 if (mConfig.hideLtePlus) { 230 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA, 231 TelephonyIcons.FOUR_G); 232 } else { 233 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA, 234 TelephonyIcons.FOUR_G_PLUS); 235 } 236 } else { 237 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.LTE); 238 if (mConfig.hideLtePlus) { 239 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA, 240 TelephonyIcons.LTE); 241 } else { 242 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA, 243 TelephonyIcons.LTE_PLUS); 244 } 245 } 246 mNetworkToIconLookup.put(NETWORK_TYPE_LTE_CA_5GE, 247 TelephonyIcons.LTE_CA_5G_E); 248 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_IWLAN, TelephonyIcons.WFC); 249 } 250 updateInflateSignalStrength()251 private void updateInflateSignalStrength() { 252 mInflateSignalStrengths = SignalStrengthUtil.shouldInflateSignalStrength(mContext, 253 mSubscriptionInfo.getSubscriptionId()); 254 } 255 getNumLevels()256 private int getNumLevels() { 257 if (mInflateSignalStrengths) { 258 return SignalStrength.NUM_SIGNAL_STRENGTH_BINS + 1; 259 } 260 return SignalStrength.NUM_SIGNAL_STRENGTH_BINS; 261 } 262 263 @Override getCurrentIconId()264 public int getCurrentIconId() { 265 if (mCurrentState.iconGroup == TelephonyIcons.CARRIER_NETWORK_CHANGE) { 266 return SignalDrawable.getCarrierChangeState(getNumLevels()); 267 } else if (mCurrentState.connected) { 268 int level = mCurrentState.level; 269 if (mInflateSignalStrengths) { 270 level++; 271 } 272 boolean dataDisabled = mCurrentState.userSetup 273 && (mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED 274 || mCurrentState.iconGroup == TelephonyIcons.NOT_DEFAULT_DATA); 275 boolean noInternet = mCurrentState.inetCondition == 0; 276 boolean cutOut = dataDisabled || noInternet; 277 return SignalDrawable.getState(level, getNumLevels(), cutOut); 278 } else if (mCurrentState.enabled) { 279 return SignalDrawable.getEmptyState(getNumLevels()); 280 } else { 281 return 0; 282 } 283 } 284 285 @Override getQsCurrentIconId()286 public int getQsCurrentIconId() { 287 return getCurrentIconId(); 288 } 289 290 @Override notifyListeners(SignalCallback callback)291 public void notifyListeners(SignalCallback callback) { 292 MobileIconGroup icons = getIcons(); 293 294 String contentDescription = getStringIfExists(getContentDescription()); 295 String dataContentDescription = getStringIfExists(icons.mDataContentDescription); 296 if (mCurrentState.inetCondition == 0) { 297 dataContentDescription = mContext.getString(R.string.data_connection_no_internet); 298 } 299 final boolean dataDisabled = (mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED 300 || mCurrentState.iconGroup == TelephonyIcons.NOT_DEFAULT_DATA) 301 && mCurrentState.userSetup; 302 303 // Show icon in QS when we are connected or data is disabled. 304 boolean showDataIcon = mCurrentState.dataConnected || dataDisabled; 305 IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode, 306 getCurrentIconId(), contentDescription); 307 308 int qsTypeIcon = 0; 309 IconState qsIcon = null; 310 String description = null; 311 // Only send data sim callbacks to QS. 312 if (mCurrentState.dataSim) { 313 qsTypeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.mQsDataType : 0; 314 qsIcon = new IconState(mCurrentState.enabled 315 && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription); 316 description = mCurrentState.isEmergency ? null : mCurrentState.networkName; 317 } 318 boolean activityIn = mCurrentState.dataConnected 319 && !mCurrentState.carrierNetworkChangeMode 320 && mCurrentState.activityIn; 321 boolean activityOut = mCurrentState.dataConnected 322 && !mCurrentState.carrierNetworkChangeMode 323 && mCurrentState.activityOut; 324 showDataIcon &= mCurrentState.isDefault || dataDisabled; 325 int typeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.mDataType : 0; 326 callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon, 327 activityIn, activityOut, dataContentDescription, description, icons.mIsWide, 328 mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming); 329 } 330 331 @Override cleanState()332 protected MobileState cleanState() { 333 return new MobileState(); 334 } 335 isCdma()336 private boolean isCdma() { 337 return (mSignalStrength != null) && !mSignalStrength.isGsm(); 338 } 339 isEmergencyOnly()340 public boolean isEmergencyOnly() { 341 return (mServiceState != null && mServiceState.isEmergencyOnly()); 342 } 343 isRoaming()344 private boolean isRoaming() { 345 // During a carrier change, roaming indications need to be supressed. 346 if (isCarrierNetworkChangeActive()) { 347 return false; 348 } 349 if (isCdma() && mServiceState != null) { 350 final int iconMode = mServiceState.getCdmaEriIconMode(); 351 return mServiceState.getCdmaEriIconIndex() != EriInfo.ROAMING_INDICATOR_OFF 352 && (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL 353 || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH); 354 } else { 355 return mServiceState != null && mServiceState.getRoaming(); 356 } 357 } 358 isCarrierNetworkChangeActive()359 private boolean isCarrierNetworkChangeActive() { 360 return mCurrentState.carrierNetworkChangeMode; 361 } 362 handleBroadcast(Intent intent)363 public void handleBroadcast(Intent intent) { 364 String action = intent.getAction(); 365 if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) { 366 updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false), 367 intent.getStringExtra(TelephonyIntents.EXTRA_SPN), 368 intent.getStringExtra(TelephonyIntents.EXTRA_DATA_SPN), 369 intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false), 370 intent.getStringExtra(TelephonyIntents.EXTRA_PLMN)); 371 notifyListenersIfNecessary(); 372 } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) { 373 updateDataSim(); 374 notifyListenersIfNecessary(); 375 } 376 } 377 updateDataSim()378 private void updateDataSim() { 379 int defaultDataSub = mDefaults.getDefaultDataSubId(); 380 if (SubscriptionManager.isValidSubscriptionId(defaultDataSub)) { 381 mCurrentState.dataSim = defaultDataSub == mSubscriptionInfo.getSubscriptionId(); 382 } else { 383 // There doesn't seem to be a data sim selected, however if 384 // there isn't a MobileSignalController with dataSim set, then 385 // QS won't get any callbacks and will be blank. Instead 386 // lets just assume we are the data sim (which will basically 387 // show one at random) in QS until one is selected. The user 388 // should pick one soon after, so we shouldn't be in this state 389 // for long. 390 mCurrentState.dataSim = true; 391 } 392 } 393 isCarrierSpecificDataIcon()394 private boolean isCarrierSpecificDataIcon() { 395 if (mConfig.patternOfCarrierSpecificDataIcon == null 396 || mConfig.patternOfCarrierSpecificDataIcon.length() == 0) { 397 return false; 398 } 399 400 Pattern stringPattern = Pattern.compile(mConfig.patternOfCarrierSpecificDataIcon); 401 String[] operatorNames = new String[]{mServiceState.getOperatorAlphaLongRaw(), 402 mServiceState.getOperatorAlphaShortRaw()}; 403 for (String opName : operatorNames) { 404 if (!TextUtils.isEmpty(opName)) { 405 Matcher matcher = stringPattern.matcher(opName); 406 if (matcher.find()) { 407 return true; 408 } 409 } 410 } 411 return false; 412 } 413 414 /** 415 * Updates the network's name based on incoming spn and plmn. 416 */ updateNetworkName(boolean showSpn, String spn, String dataSpn, boolean showPlmn, String plmn)417 void updateNetworkName(boolean showSpn, String spn, String dataSpn, 418 boolean showPlmn, String plmn) { 419 if (CHATTY) { 420 Log.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn 421 + " spn=" + spn + " dataSpn=" + dataSpn 422 + " showPlmn=" + showPlmn + " plmn=" + plmn); 423 } 424 StringBuilder str = new StringBuilder(); 425 StringBuilder strData = new StringBuilder(); 426 if (showPlmn && plmn != null) { 427 str.append(plmn); 428 strData.append(plmn); 429 } 430 if (showSpn && spn != null) { 431 if (str.length() != 0) { 432 str.append(mNetworkNameSeparator); 433 } 434 str.append(spn); 435 } 436 if (str.length() != 0) { 437 mCurrentState.networkName = str.toString(); 438 } else { 439 mCurrentState.networkName = mNetworkNameDefault; 440 } 441 if (showSpn && dataSpn != null) { 442 if (strData.length() != 0) { 443 strData.append(mNetworkNameSeparator); 444 } 445 strData.append(dataSpn); 446 } 447 if (strData.length() != 0) { 448 mCurrentState.networkNameData = strData.toString(); 449 } else { 450 mCurrentState.networkNameData = mNetworkNameDefault; 451 } 452 } 453 454 /** 455 * Updates the current state based on mServiceState, mSignalStrength, mDataNetType, 456 * mDataState, and mSimState. It should be called any time one of these is updated. 457 * This will call listeners if necessary. 458 */ updateTelephony()459 private final void updateTelephony() { 460 if (DEBUG) { 461 Log.d(mTag, "updateTelephonySignalStrength: hasService=" + 462 Utils.isInService(mServiceState) + " ss=" + mSignalStrength); 463 } 464 mCurrentState.connected = Utils.isInService(mServiceState) 465 && mSignalStrength != null; 466 if (mCurrentState.connected) { 467 if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) { 468 mCurrentState.level = mSignalStrength.getCdmaLevel(); 469 } else { 470 mCurrentState.level = mSignalStrength.getLevel(); 471 } 472 } 473 474 // When the device is camped on a 5G Non-Standalone network, the data network type is still 475 // LTE. In this case, we first check which 5G icon should be shown. 476 MobileIconGroup nr5GIconGroup = getNr5GIconGroup(); 477 if (nr5GIconGroup != null) { 478 mCurrentState.iconGroup = nr5GIconGroup; 479 } else if (mNetworkToIconLookup.indexOfKey(mDataNetType) >= 0) { 480 mCurrentState.iconGroup = mNetworkToIconLookup.get(mDataNetType); 481 } else { 482 mCurrentState.iconGroup = mDefaultIcons; 483 } 484 mCurrentState.dataConnected = mCurrentState.connected 485 && mDataState == TelephonyManager.DATA_CONNECTED; 486 487 mCurrentState.roaming = isRoaming(); 488 if (isCarrierNetworkChangeActive()) { 489 mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE; 490 } else if (isDataDisabled() && !mConfig.alwaysShowDataRatIcon) { 491 if (mSubscriptionInfo.getSubscriptionId() 492 != mDefaults.getDefaultDataSubId()) { 493 mCurrentState.iconGroup = TelephonyIcons.NOT_DEFAULT_DATA; 494 } else { 495 mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED; 496 } 497 } 498 if (isEmergencyOnly() != mCurrentState.isEmergency) { 499 mCurrentState.isEmergency = isEmergencyOnly(); 500 mNetworkController.recalculateEmergency(); 501 } 502 // Fill in the network name if we think we have it. 503 if (mCurrentState.networkName.equals(mNetworkNameDefault) && mServiceState != null 504 && !TextUtils.isEmpty(mServiceState.getOperatorAlphaShort())) { 505 mCurrentState.networkName = mServiceState.getOperatorAlphaShort(); 506 } 507 // If this is the data subscription, update the currentState data name 508 if (mCurrentState.networkNameData.equals(mNetworkNameDefault) && mServiceState != null 509 && mCurrentState.dataSim 510 && !TextUtils.isEmpty(mServiceState.getDataOperatorAlphaShort())) { 511 mCurrentState.networkNameData = mServiceState.getDataOperatorAlphaShort(); 512 } 513 514 notifyListenersIfNecessary(); 515 } 516 getNr5GIconGroup()517 private MobileIconGroup getNr5GIconGroup() { 518 if (mServiceState == null) return null; 519 520 int nrState = mServiceState.getNrState(); 521 if (nrState == NetworkRegistrationInfo.NR_STATE_CONNECTED) { 522 // Check if the NR 5G is using millimeter wave and the icon is config. 523 if (mServiceState.getNrFrequencyRange() == ServiceState.FREQUENCY_RANGE_MMWAVE) { 524 if (mConfig.nr5GIconMap.containsKey(Config.NR_CONNECTED_MMWAVE)) { 525 return mConfig.nr5GIconMap.get(Config.NR_CONNECTED_MMWAVE); 526 } 527 } 528 529 // If NR 5G is not using millimeter wave or there is no icon for millimeter wave, we 530 // check the normal 5G icon. 531 if (mConfig.nr5GIconMap.containsKey(Config.NR_CONNECTED)) { 532 return mConfig.nr5GIconMap.get(Config.NR_CONNECTED); 533 } 534 } else if (nrState == NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED) { 535 if (mConfig.nr5GIconMap.containsKey(Config.NR_NOT_RESTRICTED)) { 536 return mConfig.nr5GIconMap.get(Config.NR_NOT_RESTRICTED); 537 } 538 } else if (nrState == NetworkRegistrationInfo.NR_STATE_RESTRICTED) { 539 if (mConfig.nr5GIconMap.containsKey(Config.NR_RESTRICTED)) { 540 return mConfig.nr5GIconMap.get(Config.NR_RESTRICTED); 541 } 542 } 543 544 return null; 545 } 546 isDataDisabled()547 private boolean isDataDisabled() { 548 return !mPhone.isDataCapable(); 549 } 550 551 @VisibleForTesting setActivity(int activity)552 void setActivity(int activity) { 553 mCurrentState.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT 554 || activity == TelephonyManager.DATA_ACTIVITY_IN; 555 mCurrentState.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT 556 || activity == TelephonyManager.DATA_ACTIVITY_OUT; 557 notifyListenersIfNecessary(); 558 } 559 560 @Override dump(PrintWriter pw)561 public void dump(PrintWriter pw) { 562 super.dump(pw); 563 pw.println(" mSubscription=" + mSubscriptionInfo + ","); 564 pw.println(" mServiceState=" + mServiceState + ","); 565 pw.println(" mSignalStrength=" + mSignalStrength + ","); 566 pw.println(" mDataState=" + mDataState + ","); 567 pw.println(" mDataNetType=" + mDataNetType + ","); 568 pw.println(" mInflateSignalStrengths=" + mInflateSignalStrengths + ","); 569 pw.println(" isDataDisabled=" + isDataDisabled() + ","); 570 } 571 572 class MobilePhoneStateListener extends PhoneStateListener { MobilePhoneStateListener(Looper looper)573 public MobilePhoneStateListener(Looper looper) { 574 super(looper); 575 } 576 577 @Override onSignalStrengthsChanged(SignalStrength signalStrength)578 public void onSignalStrengthsChanged(SignalStrength signalStrength) { 579 if (DEBUG) { 580 Log.d(mTag, "onSignalStrengthsChanged signalStrength=" + signalStrength + 581 ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel()))); 582 } 583 mSignalStrength = signalStrength; 584 updateTelephony(); 585 } 586 587 @Override onServiceStateChanged(ServiceState state)588 public void onServiceStateChanged(ServiceState state) { 589 if (DEBUG) { 590 Log.d(mTag, "onServiceStateChanged voiceState=" + state.getVoiceRegState() 591 + " dataState=" + state.getDataRegState()); 592 } 593 mServiceState = state; 594 if (mServiceState != null) { 595 updateDataNetType(mServiceState.getDataNetworkType()); 596 } 597 updateTelephony(); 598 } 599 600 @Override onDataConnectionStateChanged(int state, int networkType)601 public void onDataConnectionStateChanged(int state, int networkType) { 602 if (DEBUG) { 603 Log.d(mTag, "onDataConnectionStateChanged: state=" + state 604 + " type=" + networkType); 605 } 606 mDataState = state; 607 updateDataNetType(networkType); 608 updateTelephony(); 609 } 610 updateDataNetType(int networkType)611 private void updateDataNetType(int networkType) { 612 mDataNetType = networkType; 613 if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE) { 614 if (isCarrierSpecificDataIcon()) { 615 mDataNetType = NETWORK_TYPE_LTE_CA_5GE; 616 } else if (mServiceState != null && mServiceState.isUsingCarrierAggregation()) { 617 mDataNetType = TelephonyManager.NETWORK_TYPE_LTE_CA; 618 } 619 } 620 } 621 622 @Override onDataActivity(int direction)623 public void onDataActivity(int direction) { 624 if (DEBUG) { 625 Log.d(mTag, "onDataActivity: direction=" + direction); 626 } 627 setActivity(direction); 628 } 629 630 @Override onCarrierNetworkChange(boolean active)631 public void onCarrierNetworkChange(boolean active) { 632 if (DEBUG) { 633 Log.d(mTag, "onCarrierNetworkChange: active=" + active); 634 } 635 mCurrentState.carrierNetworkChangeMode = active; 636 637 updateTelephony(); 638 } 639 }; 640 641 static class MobileIconGroup extends SignalController.IconGroup { 642 final int mDataContentDescription; // mContentDescriptionDataType 643 final int mDataType; 644 final boolean mIsWide; 645 final int mQsDataType; 646 MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc, int sbNullState, int qsNullState, int sbDiscState, int qsDiscState, int discContentDesc, int dataContentDesc, int dataType, boolean isWide)647 public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc, 648 int sbNullState, int qsNullState, int sbDiscState, int qsDiscState, 649 int discContentDesc, int dataContentDesc, int dataType, boolean isWide) { 650 super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState, 651 qsDiscState, discContentDesc); 652 mDataContentDescription = dataContentDesc; 653 mDataType = dataType; 654 mIsWide = isWide; 655 mQsDataType = dataType; // TODO: remove this field 656 } 657 } 658 659 static class MobileState extends SignalController.State { 660 String networkName; 661 String networkNameData; 662 boolean dataSim; 663 boolean dataConnected; 664 boolean isEmergency; 665 boolean airplaneMode; 666 boolean carrierNetworkChangeMode; 667 boolean isDefault; 668 boolean userSetup; 669 boolean roaming; 670 671 @Override copyFrom(State s)672 public void copyFrom(State s) { 673 super.copyFrom(s); 674 MobileState state = (MobileState) s; 675 dataSim = state.dataSim; 676 networkName = state.networkName; 677 networkNameData = state.networkNameData; 678 dataConnected = state.dataConnected; 679 isDefault = state.isDefault; 680 isEmergency = state.isEmergency; 681 airplaneMode = state.airplaneMode; 682 carrierNetworkChangeMode = state.carrierNetworkChangeMode; 683 userSetup = state.userSetup; 684 roaming = state.roaming; 685 } 686 687 @Override toString(StringBuilder builder)688 protected void toString(StringBuilder builder) { 689 super.toString(builder); 690 builder.append(','); 691 builder.append("dataSim=").append(dataSim).append(','); 692 builder.append("networkName=").append(networkName).append(','); 693 builder.append("networkNameData=").append(networkNameData).append(','); 694 builder.append("dataConnected=").append(dataConnected).append(','); 695 builder.append("roaming=").append(roaming).append(','); 696 builder.append("isDefault=").append(isDefault).append(','); 697 builder.append("isEmergency=").append(isEmergency).append(','); 698 builder.append("airplaneMode=").append(airplaneMode).append(','); 699 builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode) 700 .append(','); 701 builder.append("userSetup=").append(userSetup); 702 } 703 704 @Override equals(Object o)705 public boolean equals(Object o) { 706 return super.equals(o) 707 && Objects.equals(((MobileState) o).networkName, networkName) 708 && Objects.equals(((MobileState) o).networkNameData, networkNameData) 709 && ((MobileState) o).dataSim == dataSim 710 && ((MobileState) o).dataConnected == dataConnected 711 && ((MobileState) o).isEmergency == isEmergency 712 && ((MobileState) o).airplaneMode == airplaneMode 713 && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode 714 && ((MobileState) o).userSetup == userSetup 715 && ((MobileState) o).isDefault == isDefault 716 && ((MobileState) o).roaming == roaming; 717 } 718 } 719 } 720