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