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