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