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.CellSignalStrength; 27 import android.telephony.CellSignalStrengthCdma; 28 import android.telephony.PhoneStateListener; 29 import android.telephony.ServiceState; 30 import android.telephony.SignalStrength; 31 import android.telephony.SubscriptionInfo; 32 import android.telephony.SubscriptionManager; 33 import android.telephony.TelephonyDisplayInfo; 34 import android.telephony.TelephonyManager; 35 import android.text.Html; 36 import android.text.TextUtils; 37 import android.util.Log; 38 39 import com.android.internal.annotations.VisibleForTesting; 40 import com.android.internal.telephony.TelephonyIntents; 41 import com.android.internal.telephony.cdma.EriInfo; 42 import com.android.settingslib.Utils; 43 import com.android.settingslib.graph.SignalDrawable; 44 import com.android.settingslib.net.SignalStrengthUtil; 45 import com.android.systemui.R; 46 import com.android.systemui.statusbar.policy.NetworkController.IconState; 47 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; 48 import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config; 49 import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults; 50 51 import java.io.PrintWriter; 52 import java.util.BitSet; 53 import java.util.HashMap; 54 import java.util.List; 55 import java.util.Map; 56 import java.util.Objects; 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(receiverLooper); 103 mNetworkNameSeparator = getStringIfExists(R.string.status_bar_network_name_separator) 104 .toString(); 105 mNetworkNameDefault = getStringIfExists( 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 } 288 getIconKey()289 private String getIconKey() { 290 if (mTelephonyDisplayInfo.getOverrideNetworkType() 291 == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) { 292 return toIconKey(mTelephonyDisplayInfo.getNetworkType()); 293 } else { 294 return toDisplayIconKey(mTelephonyDisplayInfo.getOverrideNetworkType()); 295 } 296 } 297 toIconKey(@nnotation.NetworkType int networkType)298 private String toIconKey(@Annotation.NetworkType int networkType) { 299 return Integer.toString(networkType); 300 } 301 toDisplayIconKey(@nnotation.OverrideNetworkType int displayNetworkType)302 private String toDisplayIconKey(@Annotation.OverrideNetworkType int displayNetworkType) { 303 switch (displayNetworkType) { 304 case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA: 305 return toIconKey(TelephonyManager.NETWORK_TYPE_LTE) + "_CA"; 306 case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO: 307 return toIconKey(TelephonyManager.NETWORK_TYPE_LTE) + "_CA_Plus"; 308 case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA: 309 return "5G"; 310 case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE: 311 return "5G_Plus"; 312 default: 313 return "unsupported"; 314 } 315 } 316 updateInflateSignalStrength()317 private void updateInflateSignalStrength() { 318 mInflateSignalStrengths = SignalStrengthUtil.shouldInflateSignalStrength(mContext, 319 mSubscriptionInfo.getSubscriptionId()); 320 } 321 getNumLevels()322 private int getNumLevels() { 323 if (mInflateSignalStrengths) { 324 return SignalStrength.NUM_SIGNAL_STRENGTH_BINS + 1; 325 } 326 return SignalStrength.NUM_SIGNAL_STRENGTH_BINS; 327 } 328 329 @Override getCurrentIconId()330 public int getCurrentIconId() { 331 if (mCurrentState.iconGroup == TelephonyIcons.CARRIER_NETWORK_CHANGE) { 332 return SignalDrawable.getCarrierChangeState(getNumLevels()); 333 } else if (mCurrentState.connected) { 334 int level = mCurrentState.level; 335 if (mInflateSignalStrengths) { 336 level++; 337 } 338 boolean dataDisabled = mCurrentState.userSetup 339 && (mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED 340 || (mCurrentState.iconGroup == TelephonyIcons.NOT_DEFAULT_DATA 341 && mCurrentState.defaultDataOff)); 342 boolean noInternet = mCurrentState.inetCondition == 0; 343 boolean cutOut = dataDisabled || noInternet; 344 return SignalDrawable.getState(level, getNumLevels(), cutOut); 345 } else if (mCurrentState.enabled) { 346 return SignalDrawable.getEmptyState(getNumLevels()); 347 } else { 348 return 0; 349 } 350 } 351 352 @Override getQsCurrentIconId()353 public int getQsCurrentIconId() { 354 return getCurrentIconId(); 355 } 356 357 @Override notifyListeners(SignalCallback callback)358 public void notifyListeners(SignalCallback callback) { 359 MobileIconGroup icons = getIcons(); 360 361 String contentDescription = getStringIfExists(getContentDescription()).toString(); 362 CharSequence dataContentDescriptionHtml = getStringIfExists(icons.mDataContentDescription); 363 364 //TODO: Hacky 365 // The data content description can sometimes be shown in a text view and might come to us 366 // as HTML. Strip any styling here so that listeners don't have to care 367 CharSequence dataContentDescription = Html.fromHtml( 368 dataContentDescriptionHtml.toString(), 0).toString(); 369 if (mCurrentState.inetCondition == 0) { 370 dataContentDescription = mContext.getString(R.string.data_connection_no_internet); 371 } 372 final boolean dataDisabled = (mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED 373 || (mCurrentState.iconGroup == TelephonyIcons.NOT_DEFAULT_DATA)) 374 && mCurrentState.userSetup; 375 376 // Show icon in QS when we are connected or data is disabled. 377 boolean showDataIcon = mCurrentState.dataConnected || dataDisabled; 378 IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode, 379 getCurrentIconId(), contentDescription); 380 381 int qsTypeIcon = 0; 382 IconState qsIcon = null; 383 CharSequence description = null; 384 // Only send data sim callbacks to QS. 385 if (mCurrentState.dataSim) { 386 qsTypeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.mQsDataType : 0; 387 qsIcon = new IconState(mCurrentState.enabled 388 && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription); 389 description = mCurrentState.isEmergency ? null : mCurrentState.networkName; 390 } 391 boolean activityIn = mCurrentState.dataConnected 392 && !mCurrentState.carrierNetworkChangeMode 393 && mCurrentState.activityIn; 394 boolean activityOut = mCurrentState.dataConnected 395 && !mCurrentState.carrierNetworkChangeMode 396 && mCurrentState.activityOut; 397 showDataIcon &= mCurrentState.isDefault || dataDisabled; 398 int typeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.mDataType : 0; 399 callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon, 400 activityIn, activityOut, dataContentDescription, dataContentDescriptionHtml, 401 description, icons.mIsWide, mSubscriptionInfo.getSubscriptionId(), 402 mCurrentState.roaming); 403 } 404 405 @Override cleanState()406 protected MobileState cleanState() { 407 return new MobileState(); 408 } 409 isCdma()410 private boolean isCdma() { 411 return (mSignalStrength != null) && !mSignalStrength.isGsm(); 412 } 413 isEmergencyOnly()414 public boolean isEmergencyOnly() { 415 return (mServiceState != null && mServiceState.isEmergencyOnly()); 416 } 417 isRoaming()418 private boolean isRoaming() { 419 // During a carrier change, roaming indications need to be supressed. 420 if (isCarrierNetworkChangeActive()) { 421 return false; 422 } 423 if (isCdma() && mServiceState != null) { 424 final int iconMode = mServiceState.getCdmaEriIconMode(); 425 return mServiceState.getCdmaEriIconIndex() != EriInfo.ROAMING_INDICATOR_OFF 426 && (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL 427 || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH); 428 } else { 429 return mServiceState != null && mServiceState.getRoaming(); 430 } 431 } 432 isCarrierNetworkChangeActive()433 private boolean isCarrierNetworkChangeActive() { 434 return mCurrentState.carrierNetworkChangeMode; 435 } 436 handleBroadcast(Intent intent)437 public void handleBroadcast(Intent intent) { 438 String action = intent.getAction(); 439 if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) { 440 updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false), 441 intent.getStringExtra(TelephonyIntents.EXTRA_SPN), 442 intent.getStringExtra(TelephonyIntents.EXTRA_DATA_SPN), 443 intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false), 444 intent.getStringExtra(TelephonyIntents.EXTRA_PLMN)); 445 notifyListenersIfNecessary(); 446 } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) { 447 updateDataSim(); 448 notifyListenersIfNecessary(); 449 } 450 } 451 updateDataSim()452 private void updateDataSim() { 453 int activeDataSubId = mDefaults.getActiveDataSubId(); 454 if (SubscriptionManager.isValidSubscriptionId(activeDataSubId)) { 455 mCurrentState.dataSim = activeDataSubId == mSubscriptionInfo.getSubscriptionId(); 456 } else { 457 // There doesn't seem to be a data sim selected, however if 458 // there isn't a MobileSignalController with dataSim set, then 459 // QS won't get any callbacks and will be blank. Instead 460 // lets just assume we are the data sim (which will basically 461 // show one at random) in QS until one is selected. The user 462 // should pick one soon after, so we shouldn't be in this state 463 // for long. 464 mCurrentState.dataSim = true; 465 } 466 } 467 468 /** 469 * Updates the network's name based on incoming spn and plmn. 470 */ updateNetworkName(boolean showSpn, String spn, String dataSpn, boolean showPlmn, String plmn)471 void updateNetworkName(boolean showSpn, String spn, String dataSpn, 472 boolean showPlmn, String plmn) { 473 if (CHATTY) { 474 Log.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn 475 + " spn=" + spn + " dataSpn=" + dataSpn 476 + " showPlmn=" + showPlmn + " plmn=" + plmn); 477 } 478 StringBuilder str = new StringBuilder(); 479 StringBuilder strData = new StringBuilder(); 480 if (showPlmn && plmn != null) { 481 str.append(plmn); 482 strData.append(plmn); 483 } 484 if (showSpn && spn != null) { 485 if (str.length() != 0) { 486 str.append(mNetworkNameSeparator); 487 } 488 str.append(spn); 489 } 490 if (str.length() != 0) { 491 mCurrentState.networkName = str.toString(); 492 } else { 493 mCurrentState.networkName = mNetworkNameDefault; 494 } 495 if (showSpn && dataSpn != null) { 496 if (strData.length() != 0) { 497 strData.append(mNetworkNameSeparator); 498 } 499 strData.append(dataSpn); 500 } 501 if (strData.length() != 0) { 502 mCurrentState.networkNameData = strData.toString(); 503 } else { 504 mCurrentState.networkNameData = mNetworkNameDefault; 505 } 506 } 507 508 /** 509 * Extracts the CellSignalStrengthCdma from SignalStrength then returns the level 510 */ getCdmaLevel()511 private final int getCdmaLevel() { 512 List<CellSignalStrengthCdma> signalStrengthCdma = 513 mSignalStrength.getCellSignalStrengths(CellSignalStrengthCdma.class); 514 if (!signalStrengthCdma.isEmpty()) { 515 return signalStrengthCdma.get(0).getLevel(); 516 } 517 return CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 518 } 519 520 /** 521 * Updates the current state based on mServiceState, mSignalStrength, mDataState, 522 * mTelephonyDisplayInfo, and mSimState. It should be called any time one of these is updated. 523 * This will call listeners if necessary. 524 */ updateTelephony()525 private final void updateTelephony() { 526 if (DEBUG) { 527 Log.d(mTag, "updateTelephonySignalStrength: hasService=" + 528 Utils.isInService(mServiceState) + " ss=" + mSignalStrength 529 + " displayInfo=" + mTelephonyDisplayInfo); 530 } 531 checkDefaultData(); 532 mCurrentState.connected = Utils.isInService(mServiceState) && mSignalStrength != null; 533 if (mCurrentState.connected) { 534 if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) { 535 mCurrentState.level = getCdmaLevel(); 536 } else { 537 mCurrentState.level = mSignalStrength.getLevel(); 538 } 539 } 540 541 String iconKey = getIconKey(); 542 if (mNetworkToIconLookup.get(iconKey) != null) { 543 mCurrentState.iconGroup = mNetworkToIconLookup.get(iconKey); 544 } else { 545 mCurrentState.iconGroup = mDefaultIcons; 546 } 547 mCurrentState.dataConnected = mCurrentState.connected 548 && mDataState == TelephonyManager.DATA_CONNECTED; 549 550 mCurrentState.roaming = isRoaming(); 551 if (isCarrierNetworkChangeActive()) { 552 mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE; 553 } else if (isDataDisabled() && !mConfig.alwaysShowDataRatIcon) { 554 if (mSubscriptionInfo.getSubscriptionId() != mDefaults.getDefaultDataSubId()) { 555 mCurrentState.iconGroup = TelephonyIcons.NOT_DEFAULT_DATA; 556 } else { 557 mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED; 558 } 559 } 560 if (isEmergencyOnly() != mCurrentState.isEmergency) { 561 mCurrentState.isEmergency = isEmergencyOnly(); 562 mNetworkController.recalculateEmergency(); 563 } 564 // Fill in the network name if we think we have it. 565 if (mCurrentState.networkName.equals(mNetworkNameDefault) && mServiceState != null 566 && !TextUtils.isEmpty(mServiceState.getOperatorAlphaShort())) { 567 mCurrentState.networkName = mServiceState.getOperatorAlphaShort(); 568 } 569 // If this is the data subscription, update the currentState data name 570 if (mCurrentState.networkNameData.equals(mNetworkNameDefault) && mServiceState != null 571 && mCurrentState.dataSim 572 && !TextUtils.isEmpty(mServiceState.getOperatorAlphaShort())) { 573 mCurrentState.networkNameData = mServiceState.getOperatorAlphaShort(); 574 } 575 576 notifyListenersIfNecessary(); 577 } 578 579 /** 580 * If we are controlling the NOT_DEFAULT_DATA icon, check the status of the other one 581 */ checkDefaultData()582 private void checkDefaultData() { 583 if (mCurrentState.iconGroup != TelephonyIcons.NOT_DEFAULT_DATA) { 584 mCurrentState.defaultDataOff = false; 585 return; 586 } 587 588 mCurrentState.defaultDataOff = mNetworkController.isDataControllerDisabled(); 589 } 590 onMobileDataChanged()591 void onMobileDataChanged() { 592 checkDefaultData(); 593 notifyListenersIfNecessary(); 594 } 595 isDataDisabled()596 boolean isDataDisabled() { 597 return !mPhone.isDataConnectionAllowed(); 598 } 599 600 @VisibleForTesting setActivity(int activity)601 void setActivity(int activity) { 602 mCurrentState.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT 603 || activity == TelephonyManager.DATA_ACTIVITY_IN; 604 mCurrentState.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT 605 || activity == TelephonyManager.DATA_ACTIVITY_OUT; 606 notifyListenersIfNecessary(); 607 } 608 609 @Override dump(PrintWriter pw)610 public void dump(PrintWriter pw) { 611 super.dump(pw); 612 pw.println(" mSubscription=" + mSubscriptionInfo + ","); 613 pw.println(" mServiceState=" + mServiceState + ","); 614 pw.println(" mSignalStrength=" + mSignalStrength + ","); 615 pw.println(" mTelephonyDisplayInfo=" + mTelephonyDisplayInfo + ","); 616 pw.println(" mDataState=" + mDataState + ","); 617 pw.println(" mInflateSignalStrengths=" + mInflateSignalStrengths + ","); 618 pw.println(" isDataDisabled=" + isDataDisabled() + ","); 619 } 620 621 class MobilePhoneStateListener extends PhoneStateListener { MobilePhoneStateListener(Looper looper)622 public MobilePhoneStateListener(Looper looper) { 623 super(looper); 624 } 625 626 @Override onSignalStrengthsChanged(SignalStrength signalStrength)627 public void onSignalStrengthsChanged(SignalStrength signalStrength) { 628 if (DEBUG) { 629 Log.d(mTag, "onSignalStrengthsChanged signalStrength=" + signalStrength + 630 ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel()))); 631 } 632 mSignalStrength = signalStrength; 633 updateTelephony(); 634 } 635 636 @Override onServiceStateChanged(ServiceState state)637 public void onServiceStateChanged(ServiceState state) { 638 if (DEBUG) { 639 Log.d(mTag, "onServiceStateChanged voiceState=" + state.getState() 640 + " dataState=" + state.getDataRegistrationState()); 641 } 642 mServiceState = state; 643 updateTelephony(); 644 } 645 646 @Override onDataConnectionStateChanged(int state, int networkType)647 public void onDataConnectionStateChanged(int state, int networkType) { 648 if (DEBUG) { 649 Log.d(mTag, "onDataConnectionStateChanged: state=" + state 650 + " type=" + networkType); 651 } 652 mDataState = state; 653 updateTelephony(); 654 } 655 656 @Override onDataActivity(int direction)657 public void onDataActivity(int direction) { 658 if (DEBUG) { 659 Log.d(mTag, "onDataActivity: direction=" + direction); 660 } 661 setActivity(direction); 662 } 663 664 @Override onCarrierNetworkChange(boolean active)665 public void onCarrierNetworkChange(boolean active) { 666 if (DEBUG) { 667 Log.d(mTag, "onCarrierNetworkChange: active=" + active); 668 } 669 mCurrentState.carrierNetworkChangeMode = active; 670 updateTelephony(); 671 } 672 673 @Override onActiveDataSubscriptionIdChanged(int subId)674 public void onActiveDataSubscriptionIdChanged(int subId) { 675 if (DEBUG) Log.d(mTag, "onActiveDataSubscriptionIdChanged: subId=" + subId); 676 updateDataSim(); 677 updateTelephony(); 678 } 679 680 @Override onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo)681 public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) { 682 if (DEBUG) { 683 Log.d(mTag, "onDisplayInfoChanged: telephonyDisplayInfo=" + telephonyDisplayInfo); 684 } 685 mTelephonyDisplayInfo = telephonyDisplayInfo; 686 updateTelephony(); 687 } 688 } 689 690 static class MobileIconGroup extends SignalController.IconGroup { 691 final int mDataContentDescription; // mContentDescriptionDataType 692 final int mDataType; 693 final boolean mIsWide; 694 final int mQsDataType; 695 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)696 public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc, 697 int sbNullState, int qsNullState, int sbDiscState, int qsDiscState, 698 int discContentDesc, int dataContentDesc, int dataType, boolean isWide) { 699 super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState, 700 qsDiscState, discContentDesc); 701 mDataContentDescription = dataContentDesc; 702 mDataType = dataType; 703 mIsWide = isWide; 704 mQsDataType = dataType; // TODO: remove this field 705 } 706 } 707 708 static class MobileState extends SignalController.State { 709 String networkName; 710 String networkNameData; 711 boolean dataSim; 712 boolean dataConnected; 713 boolean isEmergency; 714 boolean airplaneMode; 715 boolean carrierNetworkChangeMode; 716 boolean isDefault; 717 boolean userSetup; 718 boolean roaming; 719 boolean defaultDataOff; // Tracks the on/off state of the defaultDataSubscription 720 721 @Override copyFrom(State s)722 public void copyFrom(State s) { 723 super.copyFrom(s); 724 MobileState state = (MobileState) s; 725 dataSim = state.dataSim; 726 networkName = state.networkName; 727 networkNameData = state.networkNameData; 728 dataConnected = state.dataConnected; 729 isDefault = state.isDefault; 730 isEmergency = state.isEmergency; 731 airplaneMode = state.airplaneMode; 732 carrierNetworkChangeMode = state.carrierNetworkChangeMode; 733 userSetup = state.userSetup; 734 roaming = state.roaming; 735 defaultDataOff = state.defaultDataOff; 736 } 737 738 @Override toString(StringBuilder builder)739 protected void toString(StringBuilder builder) { 740 super.toString(builder); 741 builder.append(','); 742 builder.append("dataSim=").append(dataSim).append(','); 743 builder.append("networkName=").append(networkName).append(','); 744 builder.append("networkNameData=").append(networkNameData).append(','); 745 builder.append("dataConnected=").append(dataConnected).append(','); 746 builder.append("roaming=").append(roaming).append(','); 747 builder.append("isDefault=").append(isDefault).append(','); 748 builder.append("isEmergency=").append(isEmergency).append(','); 749 builder.append("airplaneMode=").append(airplaneMode).append(','); 750 builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode) 751 .append(','); 752 builder.append("userSetup=").append(userSetup).append(','); 753 builder.append("defaultDataOff=").append(defaultDataOff); 754 } 755 756 @Override equals(Object o)757 public boolean equals(Object o) { 758 return super.equals(o) 759 && Objects.equals(((MobileState) o).networkName, networkName) 760 && Objects.equals(((MobileState) o).networkNameData, networkNameData) 761 && ((MobileState) o).dataSim == dataSim 762 && ((MobileState) o).dataConnected == dataConnected 763 && ((MobileState) o).isEmergency == isEmergency 764 && ((MobileState) o).airplaneMode == airplaneMode 765 && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode 766 && ((MobileState) o).userSetup == userSetup 767 && ((MobileState) o).isDefault == isDefault 768 && ((MobileState) o).roaming == roaming 769 && ((MobileState) o).defaultDataOff == defaultDataOff; 770 } 771 } 772 } 773