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.net.NetworkCapabilities; 21 import android.os.Looper; 22 import android.telephony.PhoneStateListener; 23 import android.telephony.ServiceState; 24 import android.telephony.SignalStrength; 25 import android.telephony.SubscriptionInfo; 26 import android.telephony.SubscriptionManager; 27 import android.telephony.TelephonyManager; 28 import android.text.TextUtils; 29 import android.util.Log; 30 import android.util.SparseArray; 31 32 import com.android.internal.annotations.VisibleForTesting; 33 import com.android.internal.telephony.TelephonyIntents; 34 import com.android.internal.telephony.cdma.EriInfo; 35 import com.android.systemui.R; 36 import com.android.systemui.statusbar.policy.NetworkController.IconState; 37 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; 38 import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config; 39 import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults; 40 41 import java.io.PrintWriter; 42 import java.util.BitSet; 43 import java.util.Objects; 44 45 46 public class MobileSignalController extends SignalController< 47 MobileSignalController.MobileState, MobileSignalController.MobileIconGroup> { 48 private final TelephonyManager mPhone; 49 private final SubscriptionDefaults mDefaults; 50 private final String mNetworkNameDefault; 51 private final String mNetworkNameSeparator; 52 @VisibleForTesting 53 final PhoneStateListener mPhoneStateListener; 54 // Save entire info for logging, we only use the id. 55 final SubscriptionInfo mSubscriptionInfo; 56 57 // @VisibleForDemoMode 58 final SparseArray<MobileIconGroup> mNetworkToIconLookup; 59 60 // Since some pieces of the phone state are interdependent we store it locally, 61 // this could potentially become part of MobileState for simplification/complication 62 // of code. 63 private int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN; 64 private int mDataState = TelephonyManager.DATA_DISCONNECTED; 65 private ServiceState mServiceState; 66 private SignalStrength mSignalStrength; 67 private MobileIconGroup mDefaultIcons; 68 private Config mConfig; 69 70 // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't 71 // need listener lists anymore. MobileSignalController(Context context, Config config, boolean hasMobileData, TelephonyManager phone, CallbackHandler callbackHandler, NetworkControllerImpl networkController, SubscriptionInfo info, SubscriptionDefaults defaults, Looper receiverLooper)72 public MobileSignalController(Context context, Config config, boolean hasMobileData, 73 TelephonyManager phone, CallbackHandler callbackHandler, 74 NetworkControllerImpl networkController, SubscriptionInfo info, 75 SubscriptionDefaults defaults, Looper receiverLooper) { 76 super("MobileSignalController(" + info.getSubscriptionId() + ")", context, 77 NetworkCapabilities.TRANSPORT_CELLULAR, callbackHandler, 78 networkController); 79 mNetworkToIconLookup = new SparseArray<>(); 80 mConfig = config; 81 mPhone = phone; 82 mDefaults = defaults; 83 mSubscriptionInfo = info; 84 mPhoneStateListener = new MobilePhoneStateListener(info.getSubscriptionId(), 85 receiverLooper); 86 mNetworkNameSeparator = getStringIfExists(R.string.status_bar_network_name_separator); 87 mNetworkNameDefault = getStringIfExists( 88 com.android.internal.R.string.lockscreen_carrier_default); 89 90 mapIconSets(); 91 92 String networkName = info.getCarrierName() != null ? info.getCarrierName().toString() 93 : mNetworkNameDefault; 94 mLastState.networkName = mCurrentState.networkName = networkName; 95 mLastState.networkNameData = mCurrentState.networkNameData = networkName; 96 mLastState.enabled = mCurrentState.enabled = hasMobileData; 97 mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons; 98 // Get initial data sim state. 99 updateDataSim(); 100 } 101 setConfiguration(Config config)102 public void setConfiguration(Config config) { 103 mConfig = config; 104 mapIconSets(); 105 updateTelephony(); 106 } 107 getDataContentDescription()108 public int getDataContentDescription() { 109 return getIcons().mDataContentDescription; 110 } 111 setAirplaneMode(boolean airplaneMode)112 public void setAirplaneMode(boolean airplaneMode) { 113 mCurrentState.airplaneMode = airplaneMode; 114 notifyListenersIfNecessary(); 115 } 116 setUserSetupComplete(boolean userSetup)117 public void setUserSetupComplete(boolean userSetup) { 118 mCurrentState.userSetup = userSetup; 119 notifyListenersIfNecessary(); 120 } 121 122 @Override updateConnectivity(BitSet connectedTransports, BitSet validatedTransports)123 public void updateConnectivity(BitSet connectedTransports, BitSet validatedTransports) { 124 boolean isValidated = validatedTransports.get(mTransportType); 125 mCurrentState.isDefault = connectedTransports.get(mTransportType); 126 // Only show this as not having connectivity if we are default. 127 mCurrentState.inetCondition = (isValidated || !mCurrentState.isDefault) ? 1 : 0; 128 notifyListenersIfNecessary(); 129 } 130 setCarrierNetworkChangeMode(boolean carrierNetworkChangeMode)131 public void setCarrierNetworkChangeMode(boolean carrierNetworkChangeMode) { 132 mCurrentState.carrierNetworkChangeMode = carrierNetworkChangeMode; 133 updateTelephony(); 134 } 135 136 /** 137 * Start listening for phone state changes. 138 */ registerListener()139 public void registerListener() { 140 mPhone.listen(mPhoneStateListener, 141 PhoneStateListener.LISTEN_SERVICE_STATE 142 | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS 143 | PhoneStateListener.LISTEN_CALL_STATE 144 | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE 145 | PhoneStateListener.LISTEN_DATA_ACTIVITY 146 | PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE); 147 } 148 149 /** 150 * Stop listening for phone state changes. 151 */ unregisterListener()152 public void unregisterListener() { 153 mPhone.listen(mPhoneStateListener, 0); 154 } 155 156 /** 157 * Produce a mapping of data network types to icon groups for simple and quick use in 158 * updateTelephony. 159 */ mapIconSets()160 private void mapIconSets() { 161 mNetworkToIconLookup.clear(); 162 163 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyIcons.THREE_G); 164 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyIcons.THREE_G); 165 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_B, TelephonyIcons.THREE_G); 166 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyIcons.THREE_G); 167 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UMTS, TelephonyIcons.THREE_G); 168 169 if (!mConfig.showAtLeast3G) { 170 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN, 171 TelephonyIcons.UNKNOWN); 172 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE, TelephonyIcons.E); 173 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA, TelephonyIcons.ONE_X); 174 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyIcons.ONE_X); 175 176 mDefaultIcons = TelephonyIcons.G; 177 } else { 178 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN, 179 TelephonyIcons.THREE_G); 180 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE, 181 TelephonyIcons.THREE_G); 182 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA, 183 TelephonyIcons.THREE_G); 184 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT, 185 TelephonyIcons.THREE_G); 186 mDefaultIcons = TelephonyIcons.THREE_G; 187 } 188 189 MobileIconGroup hGroup = TelephonyIcons.THREE_G; 190 if (mConfig.hspaDataDistinguishable) { 191 hGroup = TelephonyIcons.H; 192 } 193 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSDPA, hGroup); 194 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSUPA, hGroup); 195 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPA, hGroup); 196 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPAP, hGroup); 197 198 if (mConfig.show4gForLte) { 199 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.FOUR_G); 200 if (mConfig.hideLtePlus) { 201 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA, 202 TelephonyIcons.FOUR_G); 203 } else { 204 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA, 205 TelephonyIcons.FOUR_G_PLUS); 206 } 207 } else { 208 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.LTE); 209 if (mConfig.hideLtePlus) { 210 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA, 211 TelephonyIcons.LTE); 212 } else { 213 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA, 214 TelephonyIcons.LTE_PLUS); 215 } 216 } 217 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_IWLAN, TelephonyIcons.WFC); 218 } 219 220 @Override notifyListeners(SignalCallback callback)221 public void notifyListeners(SignalCallback callback) { 222 MobileIconGroup icons = getIcons(); 223 224 String contentDescription = getStringIfExists(getContentDescription()); 225 String dataContentDescription = getStringIfExists(icons.mDataContentDescription); 226 final boolean dataDisabled = mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED 227 && mCurrentState.userSetup; 228 229 // Show icon in QS when we are connected or need to show roaming or data is disabled. 230 boolean showDataIcon = mCurrentState.dataConnected 231 || mCurrentState.iconGroup == TelephonyIcons.ROAMING 232 || dataDisabled; 233 IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode, 234 getCurrentIconId(), contentDescription); 235 236 int qsTypeIcon = 0; 237 IconState qsIcon = null; 238 String description = null; 239 // Only send data sim callbacks to QS. 240 if (mCurrentState.dataSim) { 241 qsTypeIcon = showDataIcon ? icons.mQsDataType : 0; 242 qsIcon = new IconState(mCurrentState.enabled 243 && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription); 244 description = mCurrentState.isEmergency ? null : mCurrentState.networkName; 245 } 246 boolean activityIn = mCurrentState.dataConnected 247 && !mCurrentState.carrierNetworkChangeMode 248 && mCurrentState.activityIn; 249 boolean activityOut = mCurrentState.dataConnected 250 && !mCurrentState.carrierNetworkChangeMode 251 && mCurrentState.activityOut; 252 showDataIcon &= mCurrentState.isDefault 253 || mCurrentState.iconGroup == TelephonyIcons.ROAMING 254 || dataDisabled; 255 int typeIcon = showDataIcon ? icons.mDataType : 0; 256 callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon, 257 activityIn, activityOut, dataContentDescription, description, icons.mIsWide, 258 mSubscriptionInfo.getSubscriptionId()); 259 } 260 261 @Override cleanState()262 protected MobileState cleanState() { 263 return new MobileState(); 264 } 265 hasService()266 private boolean hasService() { 267 if (mServiceState != null) { 268 // Consider the device to be in service if either voice or data 269 // service is available. Some SIM cards are marketed as data-only 270 // and do not support voice service, and on these SIM cards, we 271 // want to show signal bars for data service as well as the "no 272 // service" or "emergency calls only" text that indicates that voice 273 // is not available. 274 switch (mServiceState.getVoiceRegState()) { 275 case ServiceState.STATE_POWER_OFF: 276 return false; 277 case ServiceState.STATE_OUT_OF_SERVICE: 278 case ServiceState.STATE_EMERGENCY_ONLY: 279 return mServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE; 280 default: 281 return true; 282 } 283 } else { 284 return false; 285 } 286 } 287 isCdma()288 private boolean isCdma() { 289 return (mSignalStrength != null) && !mSignalStrength.isGsm(); 290 } 291 isEmergencyOnly()292 public boolean isEmergencyOnly() { 293 return (mServiceState != null && mServiceState.isEmergencyOnly()); 294 } 295 isRoaming()296 private boolean isRoaming() { 297 if (isCdma()) { 298 final int iconMode = mServiceState.getCdmaEriIconMode(); 299 return mServiceState.getCdmaEriIconIndex() != EriInfo.ROAMING_INDICATOR_OFF 300 && (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL 301 || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH); 302 } else { 303 return mServiceState != null && mServiceState.getRoaming(); 304 } 305 } 306 isCarrierNetworkChangeActive()307 private boolean isCarrierNetworkChangeActive() { 308 return mCurrentState.carrierNetworkChangeMode; 309 } 310 handleBroadcast(Intent intent)311 public void handleBroadcast(Intent intent) { 312 String action = intent.getAction(); 313 if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) { 314 updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false), 315 intent.getStringExtra(TelephonyIntents.EXTRA_SPN), 316 intent.getStringExtra(TelephonyIntents.EXTRA_DATA_SPN), 317 intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false), 318 intent.getStringExtra(TelephonyIntents.EXTRA_PLMN)); 319 notifyListenersIfNecessary(); 320 } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) { 321 updateDataSim(); 322 notifyListenersIfNecessary(); 323 } 324 } 325 updateDataSim()326 private void updateDataSim() { 327 int defaultDataSub = mDefaults.getDefaultDataSubId(); 328 if (SubscriptionManager.isValidSubscriptionId(defaultDataSub)) { 329 mCurrentState.dataSim = defaultDataSub == mSubscriptionInfo.getSubscriptionId(); 330 } else { 331 // There doesn't seem to be a data sim selected, however if 332 // there isn't a MobileSignalController with dataSim set, then 333 // QS won't get any callbacks and will be blank. Instead 334 // lets just assume we are the data sim (which will basically 335 // show one at random) in QS until one is selected. The user 336 // should pick one soon after, so we shouldn't be in this state 337 // for long. 338 mCurrentState.dataSim = true; 339 } 340 } 341 342 /** 343 * Updates the network's name based on incoming spn and plmn. 344 */ updateNetworkName(boolean showSpn, String spn, String dataSpn, boolean showPlmn, String plmn)345 void updateNetworkName(boolean showSpn, String spn, String dataSpn, 346 boolean showPlmn, String plmn) { 347 if (CHATTY) { 348 Log.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn 349 + " spn=" + spn + " dataSpn=" + dataSpn 350 + " showPlmn=" + showPlmn + " plmn=" + plmn); 351 } 352 StringBuilder str = new StringBuilder(); 353 StringBuilder strData = new StringBuilder(); 354 if (showPlmn && plmn != null) { 355 str.append(plmn); 356 strData.append(plmn); 357 } 358 if (showSpn && spn != null) { 359 if (str.length() != 0) { 360 str.append(mNetworkNameSeparator); 361 } 362 str.append(spn); 363 } 364 if (str.length() != 0) { 365 mCurrentState.networkName = str.toString(); 366 } else { 367 mCurrentState.networkName = mNetworkNameDefault; 368 } 369 if (showSpn && dataSpn != null) { 370 if (strData.length() != 0) { 371 strData.append(mNetworkNameSeparator); 372 } 373 strData.append(dataSpn); 374 } 375 if (strData.length() != 0) { 376 mCurrentState.networkNameData = strData.toString(); 377 } else { 378 mCurrentState.networkNameData = mNetworkNameDefault; 379 } 380 } 381 382 /** 383 * Updates the current state based on mServiceState, mSignalStrength, mDataNetType, 384 * mDataState, and mSimState. It should be called any time one of these is updated. 385 * This will call listeners if necessary. 386 */ updateTelephony()387 private final void updateTelephony() { 388 if (DEBUG) { 389 Log.d(mTag, "updateTelephonySignalStrength: hasService=" + hasService() 390 + " ss=" + mSignalStrength); 391 } 392 mCurrentState.connected = hasService() && mSignalStrength != null; 393 if (mCurrentState.connected) { 394 if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) { 395 mCurrentState.level = mSignalStrength.getCdmaLevel(); 396 } else { 397 mCurrentState.level = mSignalStrength.getLevel(); 398 } 399 } 400 if (mNetworkToIconLookup.indexOfKey(mDataNetType) >= 0) { 401 mCurrentState.iconGroup = mNetworkToIconLookup.get(mDataNetType); 402 } else { 403 mCurrentState.iconGroup = mDefaultIcons; 404 } 405 mCurrentState.dataConnected = mCurrentState.connected 406 && mDataState == TelephonyManager.DATA_CONNECTED; 407 408 if (isCarrierNetworkChangeActive()) { 409 mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE; 410 } else if (isRoaming()) { 411 mCurrentState.iconGroup = TelephonyIcons.ROAMING; 412 } else if (isDataDisabled()) { 413 mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED; 414 } 415 if (isEmergencyOnly() != mCurrentState.isEmergency) { 416 mCurrentState.isEmergency = isEmergencyOnly(); 417 mNetworkController.recalculateEmergency(); 418 } 419 // Fill in the network name if we think we have it. 420 if (mCurrentState.networkName == mNetworkNameDefault && mServiceState != null 421 && !TextUtils.isEmpty(mServiceState.getOperatorAlphaShort())) { 422 mCurrentState.networkName = mServiceState.getOperatorAlphaShort(); 423 } 424 425 notifyListenersIfNecessary(); 426 } 427 isDataDisabled()428 private boolean isDataDisabled() { 429 return !mPhone.getDataEnabled(mSubscriptionInfo.getSubscriptionId()); 430 } 431 432 @VisibleForTesting setActivity(int activity)433 void setActivity(int activity) { 434 mCurrentState.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT 435 || activity == TelephonyManager.DATA_ACTIVITY_IN; 436 mCurrentState.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT 437 || activity == TelephonyManager.DATA_ACTIVITY_OUT; 438 notifyListenersIfNecessary(); 439 } 440 441 @Override dump(PrintWriter pw)442 public void dump(PrintWriter pw) { 443 super.dump(pw); 444 pw.println(" mSubscription=" + mSubscriptionInfo + ","); 445 pw.println(" mServiceState=" + mServiceState + ","); 446 pw.println(" mSignalStrength=" + mSignalStrength + ","); 447 pw.println(" mDataState=" + mDataState + ","); 448 pw.println(" mDataNetType=" + mDataNetType + ","); 449 } 450 451 class MobilePhoneStateListener extends PhoneStateListener { MobilePhoneStateListener(int subId, Looper looper)452 public MobilePhoneStateListener(int subId, Looper looper) { 453 super(subId, looper); 454 } 455 456 @Override onSignalStrengthsChanged(SignalStrength signalStrength)457 public void onSignalStrengthsChanged(SignalStrength signalStrength) { 458 if (DEBUG) { 459 Log.d(mTag, "onSignalStrengthsChanged signalStrength=" + signalStrength + 460 ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel()))); 461 } 462 mSignalStrength = signalStrength; 463 updateTelephony(); 464 } 465 466 @Override onServiceStateChanged(ServiceState state)467 public void onServiceStateChanged(ServiceState state) { 468 if (DEBUG) { 469 Log.d(mTag, "onServiceStateChanged voiceState=" + state.getVoiceRegState() 470 + " dataState=" + state.getDataRegState()); 471 } 472 mServiceState = state; 473 mDataNetType = state.getDataNetworkType(); 474 if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE && mServiceState != null && 475 mServiceState.isUsingCarrierAggregation()) { 476 mDataNetType = TelephonyManager.NETWORK_TYPE_LTE_CA; 477 } 478 updateTelephony(); 479 } 480 481 @Override onDataConnectionStateChanged(int state, int networkType)482 public void onDataConnectionStateChanged(int state, int networkType) { 483 if (DEBUG) { 484 Log.d(mTag, "onDataConnectionStateChanged: state=" + state 485 + " type=" + networkType); 486 } 487 mDataState = state; 488 mDataNetType = networkType; 489 if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE && mServiceState != null && 490 mServiceState.isUsingCarrierAggregation()) { 491 mDataNetType = TelephonyManager.NETWORK_TYPE_LTE_CA; 492 } 493 updateTelephony(); 494 } 495 496 @Override onDataActivity(int direction)497 public void onDataActivity(int direction) { 498 if (DEBUG) { 499 Log.d(mTag, "onDataActivity: direction=" + direction); 500 } 501 setActivity(direction); 502 } 503 504 @Override onCarrierNetworkChange(boolean active)505 public void onCarrierNetworkChange(boolean active) { 506 if (DEBUG) { 507 Log.d(mTag, "onCarrierNetworkChange: active=" + active); 508 } 509 mCurrentState.carrierNetworkChangeMode = active; 510 511 updateTelephony(); 512 } 513 }; 514 515 static class MobileIconGroup extends SignalController.IconGroup { 516 final int mDataContentDescription; // mContentDescriptionDataType 517 final int mDataType; 518 final boolean mIsWide; 519 final int mQsDataType; 520 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, int qsDataType)521 public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc, 522 int sbNullState, int qsNullState, int sbDiscState, int qsDiscState, 523 int discContentDesc, int dataContentDesc, int dataType, boolean isWide, 524 int qsDataType) { 525 super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState, 526 qsDiscState, discContentDesc); 527 mDataContentDescription = dataContentDesc; 528 mDataType = dataType; 529 mIsWide = isWide; 530 mQsDataType = qsDataType; 531 } 532 } 533 534 static class MobileState extends SignalController.State { 535 String networkName; 536 String networkNameData; 537 boolean dataSim; 538 boolean dataConnected; 539 boolean isEmergency; 540 boolean airplaneMode; 541 boolean carrierNetworkChangeMode; 542 boolean isDefault; 543 boolean userSetup; 544 545 @Override copyFrom(State s)546 public void copyFrom(State s) { 547 super.copyFrom(s); 548 MobileState state = (MobileState) s; 549 dataSim = state.dataSim; 550 networkName = state.networkName; 551 networkNameData = state.networkNameData; 552 dataConnected = state.dataConnected; 553 isDefault = state.isDefault; 554 isEmergency = state.isEmergency; 555 airplaneMode = state.airplaneMode; 556 carrierNetworkChangeMode = state.carrierNetworkChangeMode; 557 userSetup = state.userSetup; 558 } 559 560 @Override toString(StringBuilder builder)561 protected void toString(StringBuilder builder) { 562 super.toString(builder); 563 builder.append(','); 564 builder.append("dataSim=").append(dataSim).append(','); 565 builder.append("networkName=").append(networkName).append(','); 566 builder.append("networkNameData=").append(networkNameData).append(','); 567 builder.append("dataConnected=").append(dataConnected).append(','); 568 builder.append("isDefault=").append(isDefault).append(','); 569 builder.append("isEmergency=").append(isEmergency).append(','); 570 builder.append("airplaneMode=").append(airplaneMode).append(','); 571 builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode) 572 .append(','); 573 builder.append("userSetup=").append(userSetup); 574 } 575 576 @Override equals(Object o)577 public boolean equals(Object o) { 578 return super.equals(o) 579 && Objects.equals(((MobileState) o).networkName, networkName) 580 && Objects.equals(((MobileState) o).networkNameData, networkNameData) 581 && ((MobileState) o).dataSim == dataSim 582 && ((MobileState) o).dataConnected == dataConnected 583 && ((MobileState) o).isEmergency == isEmergency 584 && ((MobileState) o).airplaneMode == airplaneMode 585 && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode 586 && ((MobileState) o).userSetup == userSetup 587 && ((MobileState) o).isDefault == isDefault; 588 } 589 } 590 } 591