GsmServiceStateTracker.java revision b54cd09892e0676d719e6df00e60c77b663f993c
1/* 2 * Copyright (C) 2006 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 17package com.android.internal.telephony.gsm; 18 19import android.app.AlarmManager; 20import android.app.Notification; 21import android.app.NotificationManager; 22import android.app.PendingIntent; 23import android.content.BroadcastReceiver; 24import android.content.ContentResolver; 25import android.content.Context; 26import android.content.Intent; 27import android.content.IntentFilter; 28import android.content.res.Resources; 29import android.database.ContentObserver; 30import android.os.AsyncResult; 31import android.os.Build; 32import android.os.Handler; 33import android.os.Message; 34import android.os.PowerManager; 35import android.os.SystemClock; 36import android.os.SystemProperties; 37import android.os.UserHandle; 38import android.provider.Settings; 39import android.provider.Settings.SettingNotFoundException; 40import android.telephony.CellIdentityGsm; 41import android.telephony.CellIdentityLte; 42import android.telephony.CellIdentityWcdma; 43import android.telephony.CellInfo; 44import android.telephony.CellInfoGsm; 45import android.telephony.CellInfoLte; 46import android.telephony.CellInfoWcdma; 47import android.telephony.CellLocation; 48import android.telephony.Rlog; 49import android.telephony.ServiceState; 50import android.telephony.SignalStrength; 51import android.telephony.gsm.GsmCellLocation; 52import android.text.TextUtils; 53import android.util.EventLog; 54import android.util.TimeUtils; 55 56import com.android.internal.telephony.CommandException; 57import com.android.internal.telephony.CommandsInterface; 58import com.android.internal.telephony.EventLogTags; 59import com.android.internal.telephony.MccTable; 60import com.android.internal.telephony.Phone; 61import com.android.internal.telephony.RILConstants; 62import com.android.internal.telephony.RestrictedState; 63import com.android.internal.telephony.ServiceStateTracker; 64import com.android.internal.telephony.TelephonyIntents; 65import com.android.internal.telephony.TelephonyProperties; 66import com.android.internal.telephony.dataconnection.DcTrackerBase; 67import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState; 68import com.android.internal.telephony.uicc.IccRecords; 69import com.android.internal.telephony.uicc.SIMRecords; 70import com.android.internal.telephony.uicc.UiccCardApplication; 71import com.android.internal.telephony.uicc.UiccController; 72 73import java.io.FileDescriptor; 74import java.io.PrintWriter; 75import java.util.ArrayList; 76import java.util.Arrays; 77import java.util.Calendar; 78import java.util.Date; 79import java.util.List; 80import java.util.TimeZone; 81 82/** 83 * {@hide} 84 */ 85final class GsmServiceStateTracker extends ServiceStateTracker { 86 private static final String LOG_TAG = "GsmSST"; 87 private static final boolean VDBG = false; 88 89 GSMPhone mPhone; 90 GsmCellLocation mCellLoc; 91 GsmCellLocation mNewCellLoc; 92 int mPreferredNetworkType; 93 94 private int mMaxDataCalls = 1; 95 private int mNewMaxDataCalls = 1; 96 private int mReasonDataDenied = -1; 97 private int mNewReasonDataDenied = -1; 98 99 /** 100 * GSM roaming status solely based on TS 27.007 7.2 CREG. Only used by 101 * handlePollStateResult to store CREG roaming result. 102 */ 103 private boolean mGsmRoaming = false; 104 105 /** 106 * Data roaming status solely based on TS 27.007 10.1.19 CGREG. Only used by 107 * handlePollStateResult to store CGREG roaming result. 108 */ 109 private boolean mDataRoaming = false; 110 111 /** 112 * Mark when service state is in emergency call only mode 113 */ 114 private boolean mEmergencyOnly = false; 115 116 /** 117 * Sometimes we get the NITZ time before we know what country we 118 * are in. Keep the time zone information from the NITZ string so 119 * we can fix the time zone once know the country. 120 */ 121 private boolean mNeedFixZoneAfterNitz = false; 122 private int mZoneOffset; 123 private boolean mZoneDst; 124 private long mZoneTime; 125 private boolean mGotCountryCode = false; 126 private ContentResolver mCr; 127 128 /** Boolean is true is setTimeFromNITZString was called */ 129 private boolean mNitzUpdatedTime = false; 130 131 String mSavedTimeZone; 132 long mSavedTime; 133 long mSavedAtTime; 134 135 /** Started the recheck process after finding gprs should registered but not. */ 136 private boolean mStartedGprsRegCheck = false; 137 138 /** Already sent the event-log for no gprs register. */ 139 private boolean mReportedGprsNoReg = false; 140 141 /** 142 * The Notification object given to the NotificationManager. 143 */ 144 private Notification mNotification; 145 146 /** Wake lock used while setting time of day. */ 147 private PowerManager.WakeLock mWakeLock; 148 private static final String WAKELOCK_TAG = "ServiceStateTracker"; 149 150 /** Keep track of SPN display rules, so we only broadcast intent if something changes. */ 151 private String mCurSpn = null; 152 private String mCurPlmn = null; 153 private boolean mCurShowPlmn = false; 154 private boolean mCurShowSpn = false; 155 156 /** Notification type. */ 157 static final int PS_ENABLED = 1001; // Access Control blocks data service 158 static final int PS_DISABLED = 1002; // Access Control enables data service 159 static final int CS_ENABLED = 1003; // Access Control blocks all voice/sms service 160 static final int CS_DISABLED = 1004; // Access Control enables all voice/sms service 161 static final int CS_NORMAL_ENABLED = 1005; // Access Control blocks normal voice/sms service 162 static final int CS_EMERGENCY_ENABLED = 1006; // Access Control blocks emergency call service 163 164 /** Notification id. */ 165 static final int PS_NOTIFICATION = 888; // Id to update and cancel PS restricted 166 static final int CS_NOTIFICATION = 999; // Id to update and cancel CS restricted 167 168 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 169 @Override 170 public void onReceive(Context context, Intent intent) { 171 if (intent.getAction().equals(Intent.ACTION_LOCALE_CHANGED)) { 172 // update emergency string whenever locale changed 173 updateSpnDisplay(); 174 } 175 } 176 }; 177 178 private ContentObserver mAutoTimeObserver = new ContentObserver(new Handler()) { 179 @Override 180 public void onChange(boolean selfChange) { 181 Rlog.i("GsmServiceStateTracker", "Auto time state changed"); 182 revertToNitzTime(); 183 } 184 }; 185 186 private ContentObserver mAutoTimeZoneObserver = new ContentObserver(new Handler()) { 187 @Override 188 public void onChange(boolean selfChange) { 189 Rlog.i("GsmServiceStateTracker", "Auto time zone state changed"); 190 revertToNitzTimeZone(); 191 } 192 }; 193 194 public GsmServiceStateTracker(GSMPhone phone) { 195 super(phone, phone.mCi, new CellInfoGsm()); 196 197 mPhone = phone; 198 mCellLoc = new GsmCellLocation(); 199 mNewCellLoc = new GsmCellLocation(); 200 201 PowerManager powerManager = 202 (PowerManager)phone.getContext().getSystemService(Context.POWER_SERVICE); 203 mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG); 204 205 mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null); 206 mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null); 207 208 mCi.registerForVoiceNetworkStateChanged(this, EVENT_NETWORK_STATE_CHANGED, null); 209 mCi.setOnNITZTime(this, EVENT_NITZ_TIME, null); 210 mCi.setOnRestrictedStateChanged(this, EVENT_RESTRICTED_STATE_CHANGED, null); 211 212 // system setting property AIRPLANE_MODE_ON is set in Settings. 213 int airplaneMode = Settings.Global.getInt( 214 phone.getContext().getContentResolver(), 215 Settings.Global.AIRPLANE_MODE_ON, 0); 216 mDesiredPowerState = ! (airplaneMode > 0); 217 218 mCr = phone.getContext().getContentResolver(); 219 mCr.registerContentObserver( 220 Settings.Global.getUriFor(Settings.Global.AUTO_TIME), true, 221 mAutoTimeObserver); 222 mCr.registerContentObserver( 223 Settings.Global.getUriFor(Settings.Global.AUTO_TIME_ZONE), true, 224 mAutoTimeZoneObserver); 225 226 setSignalStrengthDefaultValues(); 227 228 // Monitor locale change 229 IntentFilter filter = new IntentFilter(); 230 filter.addAction(Intent.ACTION_LOCALE_CHANGED); 231 phone.getContext().registerReceiver(mIntentReceiver, filter); 232 233 // Gsm doesn't support OTASP so its not needed 234 phone.notifyOtaspChanged(OTASP_NOT_NEEDED); 235 } 236 237 @Override 238 public void dispose() { 239 checkCorrectThread(); 240 // Unregister for all events. 241 mCi.unregisterForAvailable(this); 242 mCi.unregisterForRadioStateChanged(this); 243 mCi.unregisterForVoiceNetworkStateChanged(this); 244 if (mUiccApplcation != null) {mUiccApplcation.unregisterForReady(this);} 245 if (mIccRecords != null) {mIccRecords.unregisterForRecordsLoaded(this);} 246 mCi.unSetOnRestrictedStateChanged(this); 247 mCi.unSetOnNITZTime(this); 248 mCr.unregisterContentObserver(mAutoTimeObserver); 249 mCr.unregisterContentObserver(mAutoTimeZoneObserver); 250 mPhone.getContext().unregisterReceiver(mIntentReceiver); 251 super.dispose(); 252 } 253 254 @Override 255 protected void finalize() { 256 if(DBG) log("finalize"); 257 } 258 259 @Override 260 protected Phone getPhone() { 261 return mPhone; 262 } 263 264 @Override 265 public void handleMessage (Message msg) { 266 AsyncResult ar; 267 int[] ints; 268 String[] strings; 269 Message message; 270 271 if (!mPhone.mIsTheCurrentActivePhone) { 272 Rlog.e(LOG_TAG, "Received message " + msg + 273 "[" + msg.what + "] while being destroyed. Ignoring."); 274 return; 275 } 276 switch (msg.what) { 277 case EVENT_RADIO_AVAILABLE: 278 //this is unnecessary 279 //setPowerStateToDesired(); 280 break; 281 282 case EVENT_SIM_READY: 283 // Set the network type, in case the radio does not restore it. 284 mCi.setCurrentPreferredNetworkType(); 285 286 boolean skipRestoringSelection = mPhone.getContext().getResources().getBoolean( 287 com.android.internal.R.bool.skip_restoring_network_selection); 288 289 if (!skipRestoringSelection) { 290 // restore the previous network selection. 291 mPhone.restoreSavedNetworkSelection(null); 292 } 293 pollState(); 294 // Signal strength polling stops when radio is off 295 queueNextSignalStrengthPoll(); 296 break; 297 298 case EVENT_RADIO_STATE_CHANGED: 299 // This will do nothing in the radio not 300 // available case 301 setPowerStateToDesired(); 302 pollState(); 303 break; 304 305 case EVENT_NETWORK_STATE_CHANGED: 306 pollState(); 307 break; 308 309 case EVENT_GET_SIGNAL_STRENGTH: 310 // This callback is called when signal strength is polled 311 // all by itself 312 313 if (!(mCi.getRadioState().isOn())) { 314 // Polling will continue when radio turns back on 315 return; 316 } 317 ar = (AsyncResult) msg.obj; 318 onSignalStrengthResult(ar, true); 319 queueNextSignalStrengthPoll(); 320 321 break; 322 323 case EVENT_GET_LOC_DONE: 324 ar = (AsyncResult) msg.obj; 325 326 if (ar.exception == null) { 327 String states[] = (String[])ar.result; 328 int lac = -1; 329 int cid = -1; 330 if (states.length >= 3) { 331 try { 332 if (states[1] != null && states[1].length() > 0) { 333 lac = Integer.parseInt(states[1], 16); 334 } 335 if (states[2] != null && states[2].length() > 0) { 336 cid = Integer.parseInt(states[2], 16); 337 } 338 } catch (NumberFormatException ex) { 339 Rlog.w(LOG_TAG, "error parsing location: " + ex); 340 } 341 } 342 mCellLoc.setLacAndCid(lac, cid); 343 mPhone.notifyLocationChanged(); 344 } 345 346 // Release any temporary cell lock, which could have been 347 // acquired to allow a single-shot location update. 348 disableSingleLocationUpdate(); 349 break; 350 351 case EVENT_POLL_STATE_REGISTRATION: 352 case EVENT_POLL_STATE_GPRS: 353 case EVENT_POLL_STATE_OPERATOR: 354 case EVENT_POLL_STATE_NETWORK_SELECTION_MODE: 355 ar = (AsyncResult) msg.obj; 356 357 handlePollStateResult(msg.what, ar); 358 break; 359 360 case EVENT_POLL_SIGNAL_STRENGTH: 361 // Just poll signal strength...not part of pollState() 362 363 mCi.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH)); 364 break; 365 366 case EVENT_NITZ_TIME: 367 ar = (AsyncResult) msg.obj; 368 369 String nitzString = (String)((Object[])ar.result)[0]; 370 long nitzReceiveTime = ((Long)((Object[])ar.result)[1]).longValue(); 371 372 setTimeFromNITZString(nitzString, nitzReceiveTime); 373 break; 374 375 case EVENT_SIGNAL_STRENGTH_UPDATE: 376 // This is a notification from 377 // CommandsInterface.setOnSignalStrengthUpdate 378 379 ar = (AsyncResult) msg.obj; 380 381 // The radio is telling us about signal strength changes 382 // we don't have to ask it 383 mDontPollSignalStrength = true; 384 385 onSignalStrengthResult(ar, true); 386 break; 387 388 case EVENT_SIM_RECORDS_LOADED: 389 log("EVENT_SIM_RECORDS_LOADED: what=" + msg.what); 390 391 updatePhoneObject(); 392 updateSpnDisplay(); 393 break; 394 395 case EVENT_LOCATION_UPDATES_ENABLED: 396 ar = (AsyncResult) msg.obj; 397 398 if (ar.exception == null) { 399 mCi.getVoiceRegistrationState(obtainMessage(EVENT_GET_LOC_DONE, null)); 400 } 401 break; 402 403 case EVENT_SET_PREFERRED_NETWORK_TYPE: 404 ar = (AsyncResult) msg.obj; 405 // Don't care the result, only use for dereg network (COPS=2) 406 message = obtainMessage(EVENT_RESET_PREFERRED_NETWORK_TYPE, ar.userObj); 407 mCi.setPreferredNetworkType(mPreferredNetworkType, message); 408 break; 409 410 case EVENT_RESET_PREFERRED_NETWORK_TYPE: 411 ar = (AsyncResult) msg.obj; 412 if (ar.userObj != null) { 413 AsyncResult.forMessage(((Message) ar.userObj)).exception 414 = ar.exception; 415 ((Message) ar.userObj).sendToTarget(); 416 } 417 break; 418 419 case EVENT_GET_PREFERRED_NETWORK_TYPE: 420 ar = (AsyncResult) msg.obj; 421 422 if (ar.exception == null) { 423 mPreferredNetworkType = ((int[])ar.result)[0]; 424 } else { 425 mPreferredNetworkType = RILConstants.NETWORK_MODE_GLOBAL; 426 } 427 428 message = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE, ar.userObj); 429 int toggledNetworkType = RILConstants.NETWORK_MODE_GLOBAL; 430 431 mCi.setPreferredNetworkType(toggledNetworkType, message); 432 break; 433 434 case EVENT_CHECK_REPORT_GPRS: 435 if (mSS != null && !isGprsConsistent(mSS.getDataRegState(), mSS.getVoiceRegState())) { 436 437 // Can't register data service while voice service is ok 438 // i.e. CREG is ok while CGREG is not 439 // possible a network or baseband side error 440 GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation()); 441 EventLog.writeEvent(EventLogTags.DATA_NETWORK_REGISTRATION_FAIL, 442 mSS.getOperatorNumeric(), loc != null ? loc.getCid() : -1); 443 mReportedGprsNoReg = true; 444 } 445 mStartedGprsRegCheck = false; 446 break; 447 448 case EVENT_RESTRICTED_STATE_CHANGED: 449 // This is a notification from 450 // CommandsInterface.setOnRestrictedStateChanged 451 452 if (DBG) log("EVENT_RESTRICTED_STATE_CHANGED"); 453 454 ar = (AsyncResult) msg.obj; 455 456 onRestrictedStateChanged(ar); 457 break; 458 459 default: 460 super.handleMessage(msg); 461 break; 462 } 463 } 464 465 @Override 466 protected void setPowerStateToDesired() { 467 // If we want it on and it's off, turn it on 468 if (mDesiredPowerState 469 && mCi.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) { 470 mCi.setRadioPower(true, null); 471 } else if (!mDesiredPowerState && mCi.getRadioState().isOn()) { 472 // If it's on and available and we want it off gracefully 473 DcTrackerBase dcTracker = mPhone.mDcTracker; 474 powerOffRadioSafely(dcTracker); 475 } // Otherwise, we're in the desired state 476 } 477 478 @Override 479 protected void hangupAndPowerOff() { 480 // hang up all active voice calls 481 if (mPhone.isInCall()) { 482 mPhone.mCT.mRingingCall.hangupIfAlive(); 483 mPhone.mCT.mBackgroundCall.hangupIfAlive(); 484 mPhone.mCT.mForegroundCall.hangupIfAlive(); 485 } 486 487 mCi.setRadioPower(false, null); 488 } 489 490 @Override 491 protected void updateSpnDisplay() { 492 // The values of plmn/showPlmn change in different scenarios. 493 // 1) No service but emergency call allowed -> expected 494 // to show "Emergency call only" 495 // EXTRA_SHOW_PLMN = true 496 // EXTRA_PLMN = "Emergency call only" 497 498 // 2) No service at all --> expected to show "No service" 499 // EXTRA_SHOW_PLMN = true 500 // EXTRA_PLMN = "No service" 501 502 // 3) Normal operation in either home or roaming service 503 // EXTRA_SHOW_PLMN = depending on IccRecords rule 504 // EXTRA_PLMN = plmn 505 506 // 4) No service due to power off, aka airplane mode 507 // EXTRA_SHOW_PLMN = false 508 // EXTRA_PLMN = null 509 510 IccRecords iccRecords = mIccRecords; 511 String plmn = null; 512 boolean showPlmn = false; 513 int rule = (iccRecords != null) ? iccRecords.getDisplayRule(mSS.getOperatorNumeric()) : 0; 514 if (mSS.getVoiceRegState() == ServiceState.STATE_OUT_OF_SERVICE 515 || mSS.getVoiceRegState() == ServiceState.STATE_EMERGENCY_ONLY) { 516 showPlmn = true; 517 if (mEmergencyOnly) { 518 // No service but emergency call allowed 519 plmn = Resources.getSystem(). 520 getText(com.android.internal.R.string.emergency_calls_only).toString(); 521 } else { 522 // No service at all 523 plmn = Resources.getSystem(). 524 getText(com.android.internal.R.string.lockscreen_carrier_default).toString(); 525 } 526 if (DBG) log("updateSpnDisplay: radio is on but out " + 527 "of service, set plmn='" + plmn + "'"); 528 } else if (mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) { 529 // In either home or roaming service 530 plmn = mSS.getOperatorAlphaLong(); 531 showPlmn = !TextUtils.isEmpty(plmn) && 532 ((rule & SIMRecords.SPN_RULE_SHOW_PLMN) 533 == SIMRecords.SPN_RULE_SHOW_PLMN); 534 } else { 535 // Power off state, such as airplane mode 536 if (DBG) log("updateSpnDisplay: radio is off w/ showPlmn=" 537 + showPlmn + " plmn=" + plmn); 538 } 539 540 // The value of spn/showSpn are same in different scenarios. 541 // EXTRA_SHOW_SPN = depending on IccRecords rule 542 // EXTRA_SPN = spn 543 String spn = (iccRecords != null) ? iccRecords.getServiceProviderName() : ""; 544 boolean showSpn = !TextUtils.isEmpty(spn) 545 && ((rule & SIMRecords.SPN_RULE_SHOW_SPN) 546 == SIMRecords.SPN_RULE_SHOW_SPN); 547 548 // Update SPN_STRINGS_UPDATED_ACTION IFF any value changes 549 if (showPlmn != mCurShowPlmn 550 || showSpn != mCurShowSpn 551 || !TextUtils.equals(spn, mCurSpn) 552 || !TextUtils.equals(plmn, mCurPlmn)) { 553 if (DBG) { 554 log(String.format("updateSpnDisplay: changed" + 555 " sending intent rule=" + rule + 556 " showPlmn='%b' plmn='%s' showSpn='%b' spn='%s'", 557 showPlmn, plmn, showSpn, spn)); 558 } 559 Intent intent = new Intent(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION); 560 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 561 intent.putExtra(TelephonyIntents.EXTRA_SHOW_SPN, showSpn); 562 intent.putExtra(TelephonyIntents.EXTRA_SPN, spn); 563 intent.putExtra(TelephonyIntents.EXTRA_SHOW_PLMN, showPlmn); 564 intent.putExtra(TelephonyIntents.EXTRA_PLMN, plmn); 565 mPhone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL); 566 } 567 568 mCurShowSpn = showSpn; 569 mCurShowPlmn = showPlmn; 570 mCurSpn = spn; 571 mCurPlmn = plmn; 572 } 573 574 /** 575 * Handle the result of one of the pollState()-related requests 576 */ 577 @Override 578 protected void handlePollStateResult (int what, AsyncResult ar) { 579 int ints[]; 580 String states[]; 581 582 // Ignore stale requests from last poll 583 if (ar.userObj != mPollingContext) return; 584 585 if (ar.exception != null) { 586 CommandException.Error err=null; 587 588 if (ar.exception instanceof CommandException) { 589 err = ((CommandException)(ar.exception)).getCommandError(); 590 } 591 592 if (err == CommandException.Error.RADIO_NOT_AVAILABLE) { 593 // Radio has crashed or turned off 594 cancelPollState(); 595 return; 596 } 597 598 if (!mCi.getRadioState().isOn()) { 599 // Radio has crashed or turned off 600 cancelPollState(); 601 return; 602 } 603 604 if (err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW) { 605 loge("RIL implementation has returned an error where it must succeed" + 606 ar.exception); 607 } 608 } else try { 609 switch (what) { 610 case EVENT_POLL_STATE_REGISTRATION: { 611 states = (String[])ar.result; 612 int lac = -1; 613 int cid = -1; 614 int type = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN; 615 int regState = ServiceState.RIL_REG_STATE_UNKNOWN; 616 int reasonRegStateDenied = -1; 617 int psc = -1; 618 if (states.length > 0) { 619 try { 620 regState = Integer.parseInt(states[0]); 621 if (states.length >= 3) { 622 if (states[1] != null && states[1].length() > 0) { 623 lac = Integer.parseInt(states[1], 16); 624 } 625 if (states[2] != null && states[2].length() > 0) { 626 cid = Integer.parseInt(states[2], 16); 627 } 628 629 // states[3] (if present) is the current radio technology 630 if (states.length >= 4 && states[3] != null) { 631 type = Integer.parseInt(states[3]); 632 } 633 } 634 if (states.length > 14) { 635 if (states[14] != null && states[14].length() > 0) { 636 psc = Integer.parseInt(states[14], 16); 637 } 638 } 639 } catch (NumberFormatException ex) { 640 loge("error parsing RegistrationState: " + ex); 641 } 642 } 643 644 mGsmRoaming = regCodeIsRoaming(regState); 645 mNewSS.setState(regCodeToServiceState(regState)); 646 mNewSS.setRilVoiceRadioTechnology(type); 647 648 boolean isVoiceCapable = mPhoneBase.getContext().getResources() 649 .getBoolean(com.android.internal.R.bool.config_voice_capable); 650 if ((regState == ServiceState.RIL_REG_STATE_DENIED_EMERGENCY_CALL_ENABLED 651 || regState == ServiceState.RIL_REG_STATE_NOT_REG_EMERGENCY_CALL_ENABLED 652 || regState == ServiceState.RIL_REG_STATE_SEARCHING_EMERGENCY_CALL_ENABLED 653 || regState == ServiceState.RIL_REG_STATE_UNKNOWN_EMERGENCY_CALL_ENABLED) 654 && isVoiceCapable) { 655 mEmergencyOnly = true; 656 } else { 657 mEmergencyOnly = false; 658 } 659 660 // LAC and CID are -1 if not avail 661 mNewCellLoc.setLacAndCid(lac, cid); 662 mNewCellLoc.setPsc(psc); 663 break; 664 } 665 666 case EVENT_POLL_STATE_GPRS: { 667 states = (String[])ar.result; 668 669 int type = 0; 670 int regState = ServiceState.RIL_REG_STATE_UNKNOWN; 671 mNewReasonDataDenied = -1; 672 mNewMaxDataCalls = 1; 673 if (states.length > 0) { 674 try { 675 regState = Integer.parseInt(states[0]); 676 677 // states[3] (if present) is the current radio technology 678 if (states.length >= 4 && states[3] != null) { 679 type = Integer.parseInt(states[3]); 680 } 681 if ((states.length >= 5 ) && 682 (regState == ServiceState.RIL_REG_STATE_DENIED)) { 683 mNewReasonDataDenied = Integer.parseInt(states[4]); 684 } 685 if (states.length >= 6) { 686 mNewMaxDataCalls = Integer.parseInt(states[5]); 687 } 688 } catch (NumberFormatException ex) { 689 loge("error parsing GprsRegistrationState: " + ex); 690 } 691 } 692 int dataRegState = regCodeToServiceState(regState); 693 mNewSS.setDataRegState(dataRegState); 694 mDataRoaming = regCodeIsRoaming(regState); 695 mNewSS.setRilDataRadioTechnology(type); 696 if (DBG) { 697 log("handlPollStateResultMessage: GsmSST setDataRegState=" + dataRegState 698 + " regState=" + regState 699 + " dataRadioTechnology=" + type); 700 } 701 break; 702 } 703 704 case EVENT_POLL_STATE_OPERATOR: { 705 String opNames[] = (String[])ar.result; 706 707 if (opNames != null && opNames.length >= 3) { 708 mNewSS.setOperatorName (opNames[0], opNames[1], opNames[2]); 709 } 710 break; 711 } 712 713 case EVENT_POLL_STATE_NETWORK_SELECTION_MODE: { 714 ints = (int[])ar.result; 715 mNewSS.setIsManualSelection(ints[0] == 1); 716 break; 717 } 718 } 719 720 } catch (RuntimeException ex) { 721 loge("Exception while polling service state. Probably malformed RIL response." + ex); 722 } 723 724 mPollingContext[0]--; 725 726 if (mPollingContext[0] == 0) { 727 /** 728 * Since the roaming state of gsm service (from +CREG) and 729 * data service (from +CGREG) could be different, the new SS 730 * is set to roaming when either is true. 731 * 732 * There are exceptions for the above rule. 733 * The new SS is not set as roaming while gsm service reports 734 * roaming but indeed it is same operator. 735 * And the operator is considered non roaming. 736 * 737 * The test for the operators is to handle special roaming 738 * agreements and MVNO's. 739 */ 740 boolean roaming = (mGsmRoaming || mDataRoaming); 741 if ((mGsmRoaming && isSameNamedOperators(mNewSS)) 742 || isOperatorConsideredNonRoaming(mNewSS)) { 743 roaming = false; 744 } 745 mNewSS.setRoaming(roaming); 746 mNewSS.setEmergencyOnly(mEmergencyOnly); 747 pollStateDone(); 748 } 749 } 750 751 private void setSignalStrengthDefaultValues() { 752 mSignalStrength = new SignalStrength(true); 753 } 754 755 /** 756 * A complete "service state" from our perspective is 757 * composed of a handful of separate requests to the radio. 758 * 759 * We make all of these requests at once, but then abandon them 760 * and start over again if the radio notifies us that some 761 * event has changed 762 */ 763 private void pollState() { 764 mPollingContext = new int[1]; 765 mPollingContext[0] = 0; 766 767 switch (mCi.getRadioState()) { 768 case RADIO_UNAVAILABLE: 769 mNewSS.setStateOutOfService(); 770 mNewCellLoc.setStateInvalid(); 771 setSignalStrengthDefaultValues(); 772 mGotCountryCode = false; 773 mNitzUpdatedTime = false; 774 pollStateDone(); 775 break; 776 777 case RADIO_OFF: 778 mNewSS.setStateOff(); 779 mNewCellLoc.setStateInvalid(); 780 setSignalStrengthDefaultValues(); 781 mGotCountryCode = false; 782 mNitzUpdatedTime = false; 783 pollStateDone(); 784 break; 785 786 default: 787 // Issue all poll-related commands at once 788 // then count down the responses, which 789 // are allowed to arrive out-of-order 790 791 mPollingContext[0]++; 792 mCi.getOperator( 793 obtainMessage( 794 EVENT_POLL_STATE_OPERATOR, mPollingContext)); 795 796 mPollingContext[0]++; 797 mCi.getDataRegistrationState( 798 obtainMessage( 799 EVENT_POLL_STATE_GPRS, mPollingContext)); 800 801 mPollingContext[0]++; 802 mCi.getVoiceRegistrationState( 803 obtainMessage( 804 EVENT_POLL_STATE_REGISTRATION, mPollingContext)); 805 806 mPollingContext[0]++; 807 mCi.getNetworkSelectionMode( 808 obtainMessage( 809 EVENT_POLL_STATE_NETWORK_SELECTION_MODE, mPollingContext)); 810 break; 811 } 812 } 813 814 private void pollStateDone() { 815 if (DBG) { 816 log("Poll ServiceState done: " + 817 " oldSS=[" + mSS + "] newSS=[" + mNewSS + "]" + 818 " oldMaxDataCalls=" + mMaxDataCalls + 819 " mNewMaxDataCalls=" + mNewMaxDataCalls + 820 " oldReasonDataDenied=" + mReasonDataDenied + 821 " mNewReasonDataDenied=" + mNewReasonDataDenied); 822 } 823 824 if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean(PROP_FORCE_ROAMING, false)) { 825 mNewSS.setRoaming(true); 826 } 827 828 useDataRegStateForDataOnlyDevices(); 829 830 boolean hasRegistered = 831 mSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE 832 && mNewSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE; 833 834 boolean hasDeregistered = 835 mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE 836 && mNewSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE; 837 838 boolean hasGprsAttached = 839 mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE 840 && mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE; 841 842 boolean hasGprsDetached = 843 mSS.getDataRegState() == ServiceState.STATE_IN_SERVICE 844 && mNewSS.getDataRegState() != ServiceState.STATE_IN_SERVICE; 845 846 boolean hasDataRegStateChanged = 847 mSS.getDataRegState() != mNewSS.getDataRegState(); 848 849 boolean hasVoiceRegStateChanged = 850 mSS.getVoiceRegState() != mNewSS.getVoiceRegState(); 851 852 boolean hasRilVoiceRadioTechnologyChanged = 853 mSS.getRilVoiceRadioTechnology() != mNewSS.getRilVoiceRadioTechnology(); 854 855 boolean hasRilDataRadioTechnologyChanged = 856 mSS.getRilDataRadioTechnology() != mNewSS.getRilDataRadioTechnology(); 857 858 boolean hasChanged = !mNewSS.equals(mSS); 859 860 boolean hasRoamingOn = !mSS.getRoaming() && mNewSS.getRoaming(); 861 862 boolean hasRoamingOff = mSS.getRoaming() && !mNewSS.getRoaming(); 863 864 boolean hasLocationChanged = !mNewCellLoc.equals(mCellLoc); 865 866 // Add an event log when connection state changes 867 if (hasVoiceRegStateChanged || hasDataRegStateChanged) { 868 EventLog.writeEvent(EventLogTags.GSM_SERVICE_STATE_CHANGE, 869 mSS.getVoiceRegState(), mSS.getDataRegState(), 870 mNewSS.getVoiceRegState(), mNewSS.getDataRegState()); 871 } 872 873 // Add an event log when network type switched 874 // TODO: we may add filtering to reduce the event logged, 875 // i.e. check preferred network setting, only switch to 2G, etc 876 if (hasRilVoiceRadioTechnologyChanged) { 877 int cid = -1; 878 GsmCellLocation loc = mNewCellLoc; 879 if (loc != null) cid = loc.getCid(); 880 // NOTE: this code was previously located after mSS and mNewSS are swapped, so 881 // existing logs were incorrectly using the new state for "network_from" 882 // and STATE_OUT_OF_SERVICE for "network_to". To avoid confusion, use a new log tag 883 // to record the correct states. 884 EventLog.writeEvent(EventLogTags.GSM_RAT_SWITCHED_NEW, cid, 885 mSS.getRilVoiceRadioTechnology(), 886 mNewSS.getRilVoiceRadioTechnology()); 887 if (DBG) { 888 log("RAT switched " 889 + ServiceState.rilRadioTechnologyToString(mSS.getRilVoiceRadioTechnology()) 890 + " -> " 891 + ServiceState.rilRadioTechnologyToString( 892 mNewSS.getRilVoiceRadioTechnology()) + " at cell " + cid); 893 } 894 } 895 896 // swap mSS and mNewSS to put new state in mSS 897 ServiceState tss = mSS; 898 mSS = mNewSS; 899 mNewSS = tss; 900 // clean slate for next time 901 mNewSS.setStateOutOfService(); 902 903 // swap mCellLoc and mNewCellLoc to put new state in mCellLoc 904 GsmCellLocation tcl = mCellLoc; 905 mCellLoc = mNewCellLoc; 906 mNewCellLoc = tcl; 907 908 mReasonDataDenied = mNewReasonDataDenied; 909 mMaxDataCalls = mNewMaxDataCalls; 910 911 if (hasRilVoiceRadioTechnologyChanged) { 912 updatePhoneObject(); 913 } 914 915 if (hasRilDataRadioTechnologyChanged) { 916 mPhone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE, 917 ServiceState.rilRadioTechnologyToString(mSS.getRilVoiceRadioTechnology())); 918 } 919 920 if (hasRegistered) { 921 mNetworkAttachedRegistrants.notifyRegistrants(); 922 923 if (DBG) { 924 log("pollStateDone: registering current mNitzUpdatedTime=" + 925 mNitzUpdatedTime + " changing to false"); 926 } 927 mNitzUpdatedTime = false; 928 } 929 930 if (hasChanged) { 931 String operatorNumeric; 932 933 updateSpnDisplay(); 934 935 mPhone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA, 936 mSS.getOperatorAlphaLong()); 937 938 String prevOperatorNumeric = 939 SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, ""); 940 operatorNumeric = mSS.getOperatorNumeric(); 941 mPhone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, operatorNumeric); 942 943 if (operatorNumeric == null) { 944 if (DBG) log("operatorNumeric is null"); 945 mPhone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, ""); 946 mGotCountryCode = false; 947 mNitzUpdatedTime = false; 948 } else { 949 String iso = ""; 950 String mcc = ""; 951 try{ 952 mcc = operatorNumeric.substring(0, 3); 953 iso = MccTable.countryCodeForMcc(Integer.parseInt(mcc)); 954 } catch ( NumberFormatException ex){ 955 loge("pollStateDone: countryCodeForMcc error" + ex); 956 } catch ( StringIndexOutOfBoundsException ex) { 957 loge("pollStateDone: countryCodeForMcc error" + ex); 958 } 959 960 mPhone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, iso); 961 mGotCountryCode = true; 962 963 TimeZone zone = null; 964 965 if (!mNitzUpdatedTime && !mcc.equals("000") && !TextUtils.isEmpty(iso) && 966 getAutoTimeZone()) { 967 968 // Test both paths if ignore nitz is true 969 boolean testOneUniqueOffsetPath = SystemProperties.getBoolean( 970 TelephonyProperties.PROPERTY_IGNORE_NITZ, false) && 971 ((SystemClock.uptimeMillis() & 1) == 0); 972 973 ArrayList<TimeZone> uniqueZones = TimeUtils.getTimeZonesWithUniqueOffsets(iso); 974 if ((uniqueZones.size() == 1) || testOneUniqueOffsetPath) { 975 zone = uniqueZones.get(0); 976 if (DBG) { 977 log("pollStateDone: no nitz but one TZ for iso-cc=" + iso + 978 " with zone.getID=" + zone.getID() + 979 " testOneUniqueOffsetPath=" + testOneUniqueOffsetPath); 980 } 981 setAndBroadcastNetworkSetTimeZone(zone.getID()); 982 } else { 983 if (DBG) { 984 log("pollStateDone: there are " + uniqueZones.size() + 985 " unique offsets for iso-cc='" + iso + 986 " testOneUniqueOffsetPath=" + testOneUniqueOffsetPath + 987 "', do nothing"); 988 } 989 } 990 } 991 992 if (shouldFixTimeZoneNow(mPhone, operatorNumeric, prevOperatorNumeric, 993 mNeedFixZoneAfterNitz)) { 994 // If the offset is (0, false) and the timezone property 995 // is set, use the timezone property rather than 996 // GMT. 997 String zoneName = SystemProperties.get(TIMEZONE_PROPERTY); 998 if (DBG) { 999 log("pollStateDone: fix time zone zoneName='" + zoneName + 1000 "' mZoneOffset=" + mZoneOffset + " mZoneDst=" + mZoneDst + 1001 " iso-cc='" + iso + 1002 "' iso-cc-idx=" + Arrays.binarySearch(GMT_COUNTRY_CODES, iso)); 1003 } 1004 1005 // "(mZoneOffset == 0) && (mZoneDst == false) && 1006 // (Arrays.binarySearch(GMT_COUNTRY_CODES, iso) < 0)" 1007 // means that we received a NITZ string telling 1008 // it is in GMT+0 w/ DST time zone 1009 // BUT iso tells is NOT, e.g, a wrong NITZ reporting 1010 // local time w/ 0 offset. 1011 if ((mZoneOffset == 0) && (mZoneDst == false) && 1012 (zoneName != null) && (zoneName.length() > 0) && 1013 (Arrays.binarySearch(GMT_COUNTRY_CODES, iso) < 0)) { 1014 zone = TimeZone.getDefault(); 1015 if (mNeedFixZoneAfterNitz) { 1016 // For wrong NITZ reporting local time w/ 0 offset, 1017 // need adjust time to reflect default timezone setting 1018 long ctm = System.currentTimeMillis(); 1019 long tzOffset = zone.getOffset(ctm); 1020 if (DBG) { 1021 log("pollStateDone: tzOffset=" + tzOffset + " ltod=" + 1022 TimeUtils.logTimeOfDay(ctm)); 1023 } 1024 if (getAutoTime()) { 1025 long adj = ctm - tzOffset; 1026 if (DBG) log("pollStateDone: adj ltod=" + 1027 TimeUtils.logTimeOfDay(adj)); 1028 setAndBroadcastNetworkSetTime(adj); 1029 } else { 1030 // Adjust the saved NITZ time to account for tzOffset. 1031 mSavedTime = mSavedTime - tzOffset; 1032 } 1033 } 1034 if (DBG) log("pollStateDone: using default TimeZone"); 1035 } else if (iso.equals("")){ 1036 // Country code not found. This is likely a test network. 1037 // Get a TimeZone based only on the NITZ parameters (best guess). 1038 zone = getNitzTimeZone(mZoneOffset, mZoneDst, mZoneTime); 1039 if (DBG) log("pollStateDone: using NITZ TimeZone"); 1040 } else { 1041 zone = TimeUtils.getTimeZone(mZoneOffset, mZoneDst, mZoneTime, iso); 1042 if (DBG) log("pollStateDone: using getTimeZone(off, dst, time, iso)"); 1043 } 1044 1045 mNeedFixZoneAfterNitz = false; 1046 1047 if (zone != null) { 1048 log("pollStateDone: zone != null zone.getID=" + zone.getID()); 1049 if (getAutoTimeZone()) { 1050 setAndBroadcastNetworkSetTimeZone(zone.getID()); 1051 } 1052 saveNitzTimeZone(zone.getID()); 1053 } else { 1054 log("pollStateDone: zone == null"); 1055 } 1056 } 1057 } 1058 1059 mPhone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING, 1060 mSS.getRoaming() ? "true" : "false"); 1061 1062 mPhone.notifyServiceStateChanged(mSS); 1063 } 1064 1065 if (hasGprsAttached) { 1066 mAttachedRegistrants.notifyRegistrants(); 1067 } 1068 1069 if (hasGprsDetached) { 1070 mDetachedRegistrants.notifyRegistrants(); 1071 } 1072 1073 if (hasDataRegStateChanged || hasRilDataRadioTechnologyChanged) { 1074 notifyDataRegStateRilRadioTechnologyChanged(); 1075 mPhone.notifyDataConnection(null); 1076 } 1077 1078 if (hasRoamingOn) { 1079 mRoamingOnRegistrants.notifyRegistrants(); 1080 } 1081 1082 if (hasRoamingOff) { 1083 mRoamingOffRegistrants.notifyRegistrants(); 1084 } 1085 1086 if (hasLocationChanged) { 1087 mPhone.notifyLocationChanged(); 1088 } 1089 1090 if (! isGprsConsistent(mSS.getDataRegState(), mSS.getVoiceRegState())) { 1091 if (!mStartedGprsRegCheck && !mReportedGprsNoReg) { 1092 mStartedGprsRegCheck = true; 1093 1094 int check_period = Settings.Global.getInt( 1095 mPhone.getContext().getContentResolver(), 1096 Settings.Global.GPRS_REGISTER_CHECK_PERIOD_MS, 1097 DEFAULT_GPRS_CHECK_PERIOD_MILLIS); 1098 sendMessageDelayed(obtainMessage(EVENT_CHECK_REPORT_GPRS), 1099 check_period); 1100 } 1101 } else { 1102 mReportedGprsNoReg = false; 1103 } 1104 // TODO: Add GsmCellIdenity updating, see CdmaLteServiceStateTracker. 1105 } 1106 1107 /** 1108 * Check if GPRS got registered while voice is registered. 1109 * 1110 * @param dataRegState i.e. CGREG in GSM 1111 * @param voiceRegState i.e. CREG in GSM 1112 * @return false if device only register to voice but not gprs 1113 */ 1114 private boolean isGprsConsistent(int dataRegState, int voiceRegState) { 1115 return !((voiceRegState == ServiceState.STATE_IN_SERVICE) && 1116 (dataRegState != ServiceState.STATE_IN_SERVICE)); 1117 } 1118 1119 /** 1120 * Returns a TimeZone object based only on parameters from the NITZ string. 1121 */ 1122 private TimeZone getNitzTimeZone(int offset, boolean dst, long when) { 1123 TimeZone guess = findTimeZone(offset, dst, when); 1124 if (guess == null) { 1125 // Couldn't find a proper timezone. Perhaps the DST data is wrong. 1126 guess = findTimeZone(offset, !dst, when); 1127 } 1128 if (DBG) log("getNitzTimeZone returning " + (guess == null ? guess : guess.getID())); 1129 return guess; 1130 } 1131 1132 private TimeZone findTimeZone(int offset, boolean dst, long when) { 1133 int rawOffset = offset; 1134 if (dst) { 1135 rawOffset -= 3600000; 1136 } 1137 String[] zones = TimeZone.getAvailableIDs(rawOffset); 1138 TimeZone guess = null; 1139 Date d = new Date(when); 1140 for (String zone : zones) { 1141 TimeZone tz = TimeZone.getTimeZone(zone); 1142 if (tz.getOffset(when) == offset && 1143 tz.inDaylightTime(d) == dst) { 1144 guess = tz; 1145 break; 1146 } 1147 } 1148 1149 return guess; 1150 } 1151 1152 private void queueNextSignalStrengthPoll() { 1153 if (mDontPollSignalStrength) { 1154 // The radio is telling us about signal strength changes 1155 // we don't have to ask it 1156 return; 1157 } 1158 1159 Message msg; 1160 1161 msg = obtainMessage(); 1162 msg.what = EVENT_POLL_SIGNAL_STRENGTH; 1163 1164 long nextTime; 1165 1166 // TODO Don't poll signal strength if screen is off 1167 sendMessageDelayed(msg, POLL_PERIOD_MILLIS); 1168 } 1169 1170 /** 1171 * Set restricted state based on the OnRestrictedStateChanged notification 1172 * If any voice or packet restricted state changes, trigger a UI 1173 * notification and notify registrants when sim is ready. 1174 * 1175 * @param ar an int value of RIL_RESTRICTED_STATE_* 1176 */ 1177 private void onRestrictedStateChanged(AsyncResult ar) { 1178 RestrictedState newRs = new RestrictedState(); 1179 1180 if (DBG) log("onRestrictedStateChanged: E rs "+ mRestrictedState); 1181 1182 if (ar.exception == null) { 1183 int[] ints = (int[])ar.result; 1184 int state = ints[0]; 1185 1186 newRs.setCsEmergencyRestricted( 1187 ((state & RILConstants.RIL_RESTRICTED_STATE_CS_EMERGENCY) != 0) || 1188 ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) ); 1189 //ignore the normal call and data restricted state before SIM READY 1190 if (mUiccApplcation != null && mUiccApplcation.getState() == AppState.APPSTATE_READY) { 1191 newRs.setCsNormalRestricted( 1192 ((state & RILConstants.RIL_RESTRICTED_STATE_CS_NORMAL) != 0) || 1193 ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) ); 1194 newRs.setPsRestricted( 1195 (state & RILConstants.RIL_RESTRICTED_STATE_PS_ALL)!= 0); 1196 } 1197 1198 if (DBG) log("onRestrictedStateChanged: new rs "+ newRs); 1199 1200 if (!mRestrictedState.isPsRestricted() && newRs.isPsRestricted()) { 1201 mPsRestrictEnabledRegistrants.notifyRegistrants(); 1202 setNotification(PS_ENABLED); 1203 } else if (mRestrictedState.isPsRestricted() && !newRs.isPsRestricted()) { 1204 mPsRestrictDisabledRegistrants.notifyRegistrants(); 1205 setNotification(PS_DISABLED); 1206 } 1207 1208 /** 1209 * There are two kind of cs restriction, normal and emergency. So 1210 * there are 4 x 4 combinations in current and new restricted states 1211 * and we only need to notify when state is changed. 1212 */ 1213 if (mRestrictedState.isCsRestricted()) { 1214 if (!newRs.isCsRestricted()) { 1215 // remove all restriction 1216 setNotification(CS_DISABLED); 1217 } else if (!newRs.isCsNormalRestricted()) { 1218 // remove normal restriction 1219 setNotification(CS_EMERGENCY_ENABLED); 1220 } else if (!newRs.isCsEmergencyRestricted()) { 1221 // remove emergency restriction 1222 setNotification(CS_NORMAL_ENABLED); 1223 } 1224 } else if (mRestrictedState.isCsEmergencyRestricted() && 1225 !mRestrictedState.isCsNormalRestricted()) { 1226 if (!newRs.isCsRestricted()) { 1227 // remove all restriction 1228 setNotification(CS_DISABLED); 1229 } else if (newRs.isCsRestricted()) { 1230 // enable all restriction 1231 setNotification(CS_ENABLED); 1232 } else if (newRs.isCsNormalRestricted()) { 1233 // remove emergency restriction and enable normal restriction 1234 setNotification(CS_NORMAL_ENABLED); 1235 } 1236 } else if (!mRestrictedState.isCsEmergencyRestricted() && 1237 mRestrictedState.isCsNormalRestricted()) { 1238 if (!newRs.isCsRestricted()) { 1239 // remove all restriction 1240 setNotification(CS_DISABLED); 1241 } else if (newRs.isCsRestricted()) { 1242 // enable all restriction 1243 setNotification(CS_ENABLED); 1244 } else if (newRs.isCsEmergencyRestricted()) { 1245 // remove normal restriction and enable emergency restriction 1246 setNotification(CS_EMERGENCY_ENABLED); 1247 } 1248 } else { 1249 if (newRs.isCsRestricted()) { 1250 // enable all restriction 1251 setNotification(CS_ENABLED); 1252 } else if (newRs.isCsEmergencyRestricted()) { 1253 // enable emergency restriction 1254 setNotification(CS_EMERGENCY_ENABLED); 1255 } else if (newRs.isCsNormalRestricted()) { 1256 // enable normal restriction 1257 setNotification(CS_NORMAL_ENABLED); 1258 } 1259 } 1260 1261 mRestrictedState = newRs; 1262 } 1263 log("onRestrictedStateChanged: X rs "+ mRestrictedState); 1264 } 1265 1266 /** code is registration state 0-5 from TS 27.007 7.2 */ 1267 private int regCodeToServiceState(int code) { 1268 switch (code) { 1269 case 0: 1270 case 2: // 2 is "searching" 1271 case 3: // 3 is "registration denied" 1272 case 4: // 4 is "unknown" no vaild in current baseband 1273 case 10:// same as 0, but indicates that emergency call is possible. 1274 case 12:// same as 2, but indicates that emergency call is possible. 1275 case 13:// same as 3, but indicates that emergency call is possible. 1276 case 14:// same as 4, but indicates that emergency call is possible. 1277 return ServiceState.STATE_OUT_OF_SERVICE; 1278 1279 case 1: 1280 return ServiceState.STATE_IN_SERVICE; 1281 1282 case 5: 1283 // in service, roam 1284 return ServiceState.STATE_IN_SERVICE; 1285 1286 default: 1287 loge("regCodeToServiceState: unexpected service state " + code); 1288 return ServiceState.STATE_OUT_OF_SERVICE; 1289 } 1290 } 1291 1292 1293 /** 1294 * code is registration state 0-5 from TS 27.007 7.2 1295 * returns true if registered roam, false otherwise 1296 */ 1297 private boolean regCodeIsRoaming (int code) { 1298 return ServiceState.RIL_REG_STATE_ROAMING == code; 1299 } 1300 1301 /** 1302 * Set roaming state if operator mcc is the same as sim mcc 1303 * and ons is different from spn 1304 * 1305 * @param s ServiceState hold current ons 1306 * @return true if same operator 1307 */ 1308 private boolean isSameNamedOperators(ServiceState s) { 1309 String spn = SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA, "empty"); 1310 1311 String onsl = s.getOperatorAlphaLong(); 1312 String onss = s.getOperatorAlphaShort(); 1313 1314 boolean equalsOnsl = onsl != null && spn.equals(onsl); 1315 boolean equalsOnss = onss != null && spn.equals(onss); 1316 1317 return currentMccEqualsSimMcc(s) && (equalsOnsl || equalsOnss); 1318 } 1319 1320 /** 1321 * Compare SIM MCC with Operator MCC 1322 * 1323 * @param s ServiceState hold current ons 1324 * @return true if both are same 1325 */ 1326 private boolean currentMccEqualsSimMcc(ServiceState s) { 1327 String simNumeric = SystemProperties.get( 1328 TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, ""); 1329 String operatorNumeric = s.getOperatorNumeric(); 1330 boolean equalsMcc = true; 1331 1332 try { 1333 equalsMcc = simNumeric.substring(0, 3). 1334 equals(operatorNumeric.substring(0, 3)); 1335 } catch (Exception e){ 1336 } 1337 return equalsMcc; 1338 } 1339 1340 /** 1341 * Do not set roaming state in case of oprators considered non-roaming. 1342 * 1343 + Can use mcc or mcc+mnc as item of config_operatorConsideredNonRoaming. 1344 * For example, 302 or 21407. If mcc or mcc+mnc match with operator, 1345 * don't set roaming state. 1346 * 1347 * @param s ServiceState hold current ons 1348 * @return false for roaming state set 1349 */ 1350 private boolean isOperatorConsideredNonRoaming(ServiceState s) { 1351 String operatorNumeric = s.getOperatorNumeric(); 1352 String[] numericArray = mPhone.getContext().getResources().getStringArray( 1353 com.android.internal.R.array.config_operatorConsideredNonRoaming); 1354 1355 if (numericArray.length == 0 || operatorNumeric == null) 1356 return false; 1357 1358 for (String numeric : numericArray) { 1359 if (operatorNumeric.startsWith(numeric)) 1360 return true; 1361 else 1362 return false; 1363 } 1364 return false; 1365 } 1366 1367 /** 1368 * @return The current GPRS state. IN_SERVICE is the same as "attached" 1369 * and OUT_OF_SERVICE is the same as detached. 1370 */ 1371 @Override 1372 public int getCurrentDataConnectionState() { 1373 return mSS.getDataRegState(); 1374 } 1375 1376 /** 1377 * @return true if phone is camping on a technology (eg UMTS) 1378 * that could support voice and data simultaneously. 1379 */ 1380 @Override 1381 public boolean isConcurrentVoiceAndDataAllowed() { 1382 return (mSS.getRilVoiceRadioTechnology() >= ServiceState.RIL_RADIO_TECHNOLOGY_UMTS); 1383 } 1384 1385 /** 1386 * @return the current cell location information. Prefer Gsm location 1387 * information if available otherwise return LTE location information 1388 */ 1389 public CellLocation getCellLocation() { 1390 if ((mCellLoc.getLac() >= 0) && (mCellLoc.getCid() >= 0)) { 1391 if (DBG) log("getCellLocation(): X good mCellLoc=" + mCellLoc); 1392 return mCellLoc; 1393 } else { 1394 List<CellInfo> result = getAllCellInfo(); 1395 if (result != null) { 1396 // A hack to allow tunneling of LTE information via GsmCellLocation 1397 // so that older Network Location Providers can return some information 1398 // on LTE only networks, see bug 9228974. 1399 // 1400 // We'll search the return CellInfo array preferring GSM/WCDMA 1401 // data, but if there is none we'll tunnel the first LTE information 1402 // in the list. 1403 // 1404 // The tunnel'd LTE information is returned as follows: 1405 // LAC = TAC field 1406 // CID = CI field 1407 // PSC = 0. 1408 GsmCellLocation cellLocOther = new GsmCellLocation(); 1409 for (CellInfo ci : result) { 1410 if (ci instanceof CellInfoGsm) { 1411 CellInfoGsm cellInfoGsm = (CellInfoGsm)ci; 1412 CellIdentityGsm cellIdentityGsm = cellInfoGsm.getCellIdentity(); 1413 cellLocOther.setLacAndCid(cellIdentityGsm.getLac(), 1414 cellIdentityGsm.getCid()); 1415 cellLocOther.setPsc(cellIdentityGsm.getPsc()); 1416 if (DBG) log("getCellLocation(): X ret GSM info=" + cellLocOther); 1417 return cellLocOther; 1418 } else if (ci instanceof CellInfoWcdma) { 1419 CellInfoWcdma cellInfoWcdma = (CellInfoWcdma)ci; 1420 CellIdentityWcdma cellIdentityWcdma = cellInfoWcdma.getCellIdentity(); 1421 cellLocOther.setLacAndCid(cellIdentityWcdma.getLac(), 1422 cellIdentityWcdma.getCid()); 1423 cellLocOther.setPsc(cellIdentityWcdma.getPsc()); 1424 if (DBG) log("getCellLocation(): X ret WCDMA info=" + cellLocOther); 1425 return cellLocOther; 1426 } else if ((ci instanceof CellInfoLte) && 1427 ((cellLocOther.getLac() < 0) || (cellLocOther.getCid() < 0))) { 1428 // We'll return the first good LTE info we get if there is no better answer 1429 CellInfoLte cellInfoLte = (CellInfoLte)ci; 1430 CellIdentityLte cellIdentityLte = cellInfoLte.getCellIdentity(); 1431 if ((cellIdentityLte.getTac() != Integer.MAX_VALUE) 1432 && (cellIdentityLte.getCi() != Integer.MAX_VALUE)) { 1433 cellLocOther.setLacAndCid(cellIdentityLte.getTac(), 1434 cellIdentityLte.getCi()); 1435 cellLocOther.setPsc(0); 1436 if (DBG) { 1437 log("getCellLocation(): possible LTE cellLocOther=" + cellLocOther); 1438 } 1439 } 1440 } 1441 } 1442 if (DBG) { 1443 log("getCellLocation(): X ret best answer cellLocOther=" + cellLocOther); 1444 } 1445 return cellLocOther; 1446 } else { 1447 if (DBG) { 1448 log("getCellLocation(): X empty mCellLoc and CellInfo mCellLoc=" + mCellLoc); 1449 } 1450 return mCellLoc; 1451 } 1452 } 1453 } 1454 1455 /** 1456 * nitzReceiveTime is time_t that the NITZ time was posted 1457 */ 1458 private void setTimeFromNITZString (String nitz, long nitzReceiveTime) { 1459 // "yy/mm/dd,hh:mm:ss(+/-)tz" 1460 // tz is in number of quarter-hours 1461 1462 long start = SystemClock.elapsedRealtime(); 1463 if (DBG) {log("NITZ: " + nitz + "," + nitzReceiveTime + 1464 " start=" + start + " delay=" + (start - nitzReceiveTime)); 1465 } 1466 1467 try { 1468 /* NITZ time (hour:min:sec) will be in UTC but it supplies the timezone 1469 * offset as well (which we won't worry about until later) */ 1470 Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); 1471 1472 c.clear(); 1473 c.set(Calendar.DST_OFFSET, 0); 1474 1475 String[] nitzSubs = nitz.split("[/:,+-]"); 1476 1477 int year = 2000 + Integer.parseInt(nitzSubs[0]); 1478 c.set(Calendar.YEAR, year); 1479 1480 // month is 0 based! 1481 int month = Integer.parseInt(nitzSubs[1]) - 1; 1482 c.set(Calendar.MONTH, month); 1483 1484 int date = Integer.parseInt(nitzSubs[2]); 1485 c.set(Calendar.DATE, date); 1486 1487 int hour = Integer.parseInt(nitzSubs[3]); 1488 c.set(Calendar.HOUR, hour); 1489 1490 int minute = Integer.parseInt(nitzSubs[4]); 1491 c.set(Calendar.MINUTE, minute); 1492 1493 int second = Integer.parseInt(nitzSubs[5]); 1494 c.set(Calendar.SECOND, second); 1495 1496 boolean sign = (nitz.indexOf('-') == -1); 1497 1498 int tzOffset = Integer.parseInt(nitzSubs[6]); 1499 1500 int dst = (nitzSubs.length >= 8 ) ? Integer.parseInt(nitzSubs[7]) 1501 : 0; 1502 1503 // The zone offset received from NITZ is for current local time, 1504 // so DST correction is already applied. Don't add it again. 1505 // 1506 // tzOffset += dst * 4; 1507 // 1508 // We could unapply it if we wanted the raw offset. 1509 1510 tzOffset = (sign ? 1 : -1) * tzOffset * 15 * 60 * 1000; 1511 1512 TimeZone zone = null; 1513 1514 // As a special extension, the Android emulator appends the name of 1515 // the host computer's timezone to the nitz string. this is zoneinfo 1516 // timezone name of the form Area!Location or Area!Location!SubLocation 1517 // so we need to convert the ! into / 1518 if (nitzSubs.length >= 9) { 1519 String tzname = nitzSubs[8].replace('!','/'); 1520 zone = TimeZone.getTimeZone( tzname ); 1521 } 1522 1523 String iso = SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY); 1524 1525 if (zone == null) { 1526 1527 if (mGotCountryCode) { 1528 if (iso != null && iso.length() > 0) { 1529 zone = TimeUtils.getTimeZone(tzOffset, dst != 0, 1530 c.getTimeInMillis(), 1531 iso); 1532 } else { 1533 // We don't have a valid iso country code. This is 1534 // most likely because we're on a test network that's 1535 // using a bogus MCC (eg, "001"), so get a TimeZone 1536 // based only on the NITZ parameters. 1537 zone = getNitzTimeZone(tzOffset, (dst != 0), c.getTimeInMillis()); 1538 } 1539 } 1540 } 1541 1542 if ((zone == null) || (mZoneOffset != tzOffset) || (mZoneDst != (dst != 0))){ 1543 // We got the time before the country or the zone has changed 1544 // so we don't know how to identify the DST rules yet. Save 1545 // the information and hope to fix it up later. 1546 1547 mNeedFixZoneAfterNitz = true; 1548 mZoneOffset = tzOffset; 1549 mZoneDst = dst != 0; 1550 mZoneTime = c.getTimeInMillis(); 1551 } 1552 1553 if (zone != null) { 1554 if (getAutoTimeZone()) { 1555 setAndBroadcastNetworkSetTimeZone(zone.getID()); 1556 } 1557 saveNitzTimeZone(zone.getID()); 1558 } 1559 1560 String ignore = SystemProperties.get("gsm.ignore-nitz"); 1561 if (ignore != null && ignore.equals("yes")) { 1562 log("NITZ: Not setting clock because gsm.ignore-nitz is set"); 1563 return; 1564 } 1565 1566 try { 1567 mWakeLock.acquire(); 1568 1569 if (getAutoTime()) { 1570 long millisSinceNitzReceived 1571 = SystemClock.elapsedRealtime() - nitzReceiveTime; 1572 1573 if (millisSinceNitzReceived < 0) { 1574 // Sanity check: something is wrong 1575 if (DBG) { 1576 log("NITZ: not setting time, clock has rolled " 1577 + "backwards since NITZ time was received, " 1578 + nitz); 1579 } 1580 return; 1581 } 1582 1583 if (millisSinceNitzReceived > Integer.MAX_VALUE) { 1584 // If the time is this far off, something is wrong > 24 days! 1585 if (DBG) { 1586 log("NITZ: not setting time, processing has taken " 1587 + (millisSinceNitzReceived / (1000 * 60 * 60 * 24)) 1588 + " days"); 1589 } 1590 return; 1591 } 1592 1593 // Note: with range checks above, cast to int is safe 1594 c.add(Calendar.MILLISECOND, (int)millisSinceNitzReceived); 1595 1596 if (DBG) { 1597 log("NITZ: Setting time of day to " + c.getTime() 1598 + " NITZ receive delay(ms): " + millisSinceNitzReceived 1599 + " gained(ms): " 1600 + (c.getTimeInMillis() - System.currentTimeMillis()) 1601 + " from " + nitz); 1602 } 1603 1604 setAndBroadcastNetworkSetTime(c.getTimeInMillis()); 1605 Rlog.i(LOG_TAG, "NITZ: after Setting time of day"); 1606 } 1607 SystemProperties.set("gsm.nitz.time", String.valueOf(c.getTimeInMillis())); 1608 saveNitzTime(c.getTimeInMillis()); 1609 if (VDBG) { 1610 long end = SystemClock.elapsedRealtime(); 1611 log("NITZ: end=" + end + " dur=" + (end - start)); 1612 } 1613 mNitzUpdatedTime = true; 1614 } finally { 1615 mWakeLock.release(); 1616 } 1617 } catch (RuntimeException ex) { 1618 loge("NITZ: Parsing NITZ time " + nitz + " ex=" + ex); 1619 } 1620 } 1621 1622 private boolean getAutoTime() { 1623 try { 1624 return Settings.Global.getInt(mPhone.getContext().getContentResolver(), 1625 Settings.Global.AUTO_TIME) > 0; 1626 } catch (SettingNotFoundException snfe) { 1627 return true; 1628 } 1629 } 1630 1631 private boolean getAutoTimeZone() { 1632 try { 1633 return Settings.Global.getInt(mPhone.getContext().getContentResolver(), 1634 Settings.Global.AUTO_TIME_ZONE) > 0; 1635 } catch (SettingNotFoundException snfe) { 1636 return true; 1637 } 1638 } 1639 1640 private void saveNitzTimeZone(String zoneId) { 1641 mSavedTimeZone = zoneId; 1642 } 1643 1644 private void saveNitzTime(long time) { 1645 mSavedTime = time; 1646 mSavedAtTime = SystemClock.elapsedRealtime(); 1647 } 1648 1649 /** 1650 * Set the timezone and send out a sticky broadcast so the system can 1651 * determine if the timezone was set by the carrier. 1652 * 1653 * @param zoneId timezone set by carrier 1654 */ 1655 private void setAndBroadcastNetworkSetTimeZone(String zoneId) { 1656 if (DBG) log("setAndBroadcastNetworkSetTimeZone: setTimeZone=" + zoneId); 1657 AlarmManager alarm = 1658 (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE); 1659 alarm.setTimeZone(zoneId); 1660 Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE); 1661 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 1662 intent.putExtra("time-zone", zoneId); 1663 mPhone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL); 1664 if (DBG) { 1665 log("setAndBroadcastNetworkSetTimeZone: call alarm.setTimeZone and broadcast zoneId=" + 1666 zoneId); 1667 } 1668 } 1669 1670 /** 1671 * Set the time and Send out a sticky broadcast so the system can determine 1672 * if the time was set by the carrier. 1673 * 1674 * @param time time set by network 1675 */ 1676 private void setAndBroadcastNetworkSetTime(long time) { 1677 if (DBG) log("setAndBroadcastNetworkSetTime: time=" + time + "ms"); 1678 SystemClock.setCurrentTimeMillis(time); 1679 Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIME); 1680 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 1681 intent.putExtra("time", time); 1682 mPhone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL); 1683 } 1684 1685 private void revertToNitzTime() { 1686 if (Settings.Global.getInt(mPhone.getContext().getContentResolver(), 1687 Settings.Global.AUTO_TIME, 0) == 0) { 1688 return; 1689 } 1690 if (DBG) { 1691 log("Reverting to NITZ Time: mSavedTime=" + mSavedTime 1692 + " mSavedAtTime=" + mSavedAtTime); 1693 } 1694 if (mSavedTime != 0 && mSavedAtTime != 0) { 1695 setAndBroadcastNetworkSetTime(mSavedTime 1696 + (SystemClock.elapsedRealtime() - mSavedAtTime)); 1697 } 1698 } 1699 1700 private void revertToNitzTimeZone() { 1701 if (Settings.Global.getInt(mPhone.getContext().getContentResolver(), 1702 Settings.Global.AUTO_TIME_ZONE, 0) == 0) { 1703 return; 1704 } 1705 if (DBG) log("Reverting to NITZ TimeZone: tz='" + mSavedTimeZone); 1706 if (mSavedTimeZone != null) { 1707 setAndBroadcastNetworkSetTimeZone(mSavedTimeZone); 1708 } 1709 } 1710 1711 /** 1712 * Post a notification to NotificationManager for restricted state 1713 * 1714 * @param notifyType is one state of PS/CS_*_ENABLE/DISABLE 1715 */ 1716 private void setNotification(int notifyType) { 1717 1718 if (DBG) log("setNotification: create notification " + notifyType); 1719 Context context = mPhone.getContext(); 1720 1721 mNotification = new Notification(); 1722 mNotification.when = System.currentTimeMillis(); 1723 mNotification.flags = Notification.FLAG_AUTO_CANCEL; 1724 mNotification.icon = com.android.internal.R.drawable.stat_sys_warning; 1725 Intent intent = new Intent(); 1726 mNotification.contentIntent = PendingIntent 1727 .getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); 1728 1729 CharSequence details = ""; 1730 CharSequence title = context.getText(com.android.internal.R.string.RestrictedChangedTitle); 1731 int notificationId = CS_NOTIFICATION; 1732 1733 switch (notifyType) { 1734 case PS_ENABLED: 1735 notificationId = PS_NOTIFICATION; 1736 details = context.getText(com.android.internal.R.string.RestrictedOnData); 1737 break; 1738 case PS_DISABLED: 1739 notificationId = PS_NOTIFICATION; 1740 break; 1741 case CS_ENABLED: 1742 details = context.getText(com.android.internal.R.string.RestrictedOnAllVoice); 1743 break; 1744 case CS_NORMAL_ENABLED: 1745 details = context.getText(com.android.internal.R.string.RestrictedOnNormal); 1746 break; 1747 case CS_EMERGENCY_ENABLED: 1748 details = context.getText(com.android.internal.R.string.RestrictedOnEmergency); 1749 break; 1750 case CS_DISABLED: 1751 // do nothing and cancel the notification later 1752 break; 1753 } 1754 1755 if (DBG) log("setNotification: put notification " + title + " / " +details); 1756 mNotification.tickerText = title; 1757 mNotification.setLatestEventInfo(context, title, details, 1758 mNotification.contentIntent); 1759 1760 NotificationManager notificationManager = (NotificationManager) 1761 context.getSystemService(Context.NOTIFICATION_SERVICE); 1762 1763 if (notifyType == PS_DISABLED || notifyType == CS_DISABLED) { 1764 // cancel previous post notification 1765 notificationManager.cancel(notificationId); 1766 } else { 1767 // update restricted state notification 1768 notificationManager.notify(notificationId, mNotification); 1769 } 1770 } 1771 1772 @Override 1773 protected void onUpdateIccAvailability() { 1774 if (mUiccController == null ) { 1775 return; 1776 } 1777 1778 UiccCardApplication newUiccApplication = 1779 mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP); 1780 1781 if (mUiccApplcation != newUiccApplication) { 1782 if (mUiccApplcation != null) { 1783 log("Removing stale icc objects."); 1784 mUiccApplcation.unregisterForReady(this); 1785 if (mIccRecords != null) { 1786 mIccRecords.unregisterForRecordsLoaded(this); 1787 } 1788 mIccRecords = null; 1789 mUiccApplcation = null; 1790 } 1791 if (newUiccApplication != null) { 1792 log("New card found"); 1793 mUiccApplcation = newUiccApplication; 1794 mIccRecords = mUiccApplcation.getIccRecords(); 1795 mUiccApplcation.registerForReady(this, EVENT_SIM_READY, null); 1796 if (mIccRecords != null) { 1797 mIccRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null); 1798 } 1799 } 1800 } 1801 } 1802 @Override 1803 protected void log(String s) { 1804 Rlog.d(LOG_TAG, "[GsmSST] " + s); 1805 } 1806 1807 @Override 1808 protected void loge(String s) { 1809 Rlog.e(LOG_TAG, "[GsmSST] " + s); 1810 } 1811 1812 @Override 1813 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1814 pw.println("GsmServiceStateTracker extends:"); 1815 super.dump(fd, pw, args); 1816 pw.println(" mPhone=" + mPhone); 1817 pw.println(" mSS=" + mSS); 1818 pw.println(" mNewSS=" + mNewSS); 1819 pw.println(" mCellLoc=" + mCellLoc); 1820 pw.println(" mNewCellLoc=" + mNewCellLoc); 1821 pw.println(" mPreferredNetworkType=" + mPreferredNetworkType); 1822 pw.println(" mMaxDataCalls=" + mMaxDataCalls); 1823 pw.println(" mNewMaxDataCalls=" + mNewMaxDataCalls); 1824 pw.println(" mReasonDataDenied=" + mReasonDataDenied); 1825 pw.println(" mNewReasonDataDenied=" + mNewReasonDataDenied); 1826 pw.println(" mGsmRoaming=" + mGsmRoaming); 1827 pw.println(" mDataRoaming=" + mDataRoaming); 1828 pw.println(" mEmergencyOnly=" + mEmergencyOnly); 1829 pw.println(" mNeedFixZoneAfterNitz=" + mNeedFixZoneAfterNitz); 1830 pw.println(" mZoneOffset=" + mZoneOffset); 1831 pw.println(" mZoneDst=" + mZoneDst); 1832 pw.println(" mZoneTime=" + mZoneTime); 1833 pw.println(" mGotCountryCode=" + mGotCountryCode); 1834 pw.println(" mNitzUpdatedTime=" + mNitzUpdatedTime); 1835 pw.println(" mSavedTimeZone=" + mSavedTimeZone); 1836 pw.println(" mSavedTime=" + mSavedTime); 1837 pw.println(" mSavedAtTime=" + mSavedAtTime); 1838 pw.println(" mStartedGprsRegCheck=" + mStartedGprsRegCheck); 1839 pw.println(" mReportedGprsNoReg=" + mReportedGprsNoReg); 1840 pw.println(" mNotification=" + mNotification); 1841 pw.println(" mWakeLock=" + mWakeLock); 1842 pw.println(" mCurSpn=" + mCurSpn); 1843 pw.println(" mCurShowSpn=" + mCurShowSpn); 1844 pw.println(" mCurPlmn=" + mCurPlmn); 1845 pw.println(" mCurShowPlmn=" + mCurShowPlmn); 1846 } 1847} 1848