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