1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony.cdma; 18 19 import android.content.Intent; 20 import com.android.internal.telephony.TelephonyProperties; 21 import com.android.internal.telephony.MccTable; 22 import com.android.internal.telephony.EventLogTags; 23 import com.android.internal.telephony.uicc.RuimRecords; 24 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState; 25 import com.android.internal.telephony.TelephonyIntents; 26 import com.android.internal.telephony.Phone; 27 import com.android.internal.telephony.PhoneFactory; 28 29 import android.telephony.CellInfo; 30 import android.telephony.CellInfoLte; 31 import android.telephony.CellSignalStrengthLte; 32 import android.telephony.CellIdentityLte; 33 import android.telephony.SignalStrength; 34 import android.telephony.ServiceState; 35 import android.telephony.cdma.CdmaCellLocation; 36 import android.telephony.TelephonyManager; 37 import android.text.TextUtils; 38 import android.os.AsyncResult; 39 import android.os.Message; 40 import android.os.UserHandle; 41 import android.os.SystemClock; 42 import android.os.SystemProperties; 43 44 import android.telephony.Rlog; 45 import android.util.EventLog; 46 47 import com.android.internal.telephony.dataconnection.DcTrackerBase; 48 import com.android.internal.telephony.ProxyController; 49 import android.telephony.SubscriptionManager; 50 import com.android.internal.telephony.uicc.UiccCardApplication; 51 import com.android.internal.telephony.uicc.UiccController; 52 53 import java.io.FileDescriptor; 54 import java.io.PrintWriter; 55 import java.util.ArrayList; 56 import java.util.List; 57 58 public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker { 59 private CDMALTEPhone mCdmaLtePhone; 60 private final CellInfoLte mCellInfoLte; 61 private static final int EVENT_ALL_DATA_DISCONNECTED = 1001; 62 63 private CellIdentityLte mNewCellIdentityLte = new CellIdentityLte(); 64 private CellIdentityLte mLasteCellIdentityLte = new CellIdentityLte(); 65 66 public CdmaLteServiceStateTracker(CDMALTEPhone phone) { 67 super(phone, new CellInfoLte()); 68 mCdmaLtePhone = phone; 69 mCellInfoLte = (CellInfoLte) mCellInfo; 70 71 ((CellInfoLte)mCellInfo).setCellSignalStrength(new CellSignalStrengthLte()); 72 ((CellInfoLte)mCellInfo).setCellIdentity(new CellIdentityLte()); 73 74 if (DBG) log("CdmaLteServiceStateTracker Constructors"); 75 } 76 77 @Override 78 public void handleMessage(Message msg) { 79 AsyncResult ar; 80 int[] ints; 81 String[] strings; 82 83 if (!mPhone.mIsTheCurrentActivePhone) { 84 loge("Received message " + msg + "[" + msg.what + "]" + 85 " while being destroyed. Ignoring."); 86 return; 87 } 88 89 if (DBG) log("handleMessage: " + msg.what); 90 switch (msg.what) { 91 case EVENT_POLL_STATE_GPRS: 92 if (DBG) log("handleMessage EVENT_POLL_STATE_GPRS"); 93 ar = (AsyncResult)msg.obj; 94 handlePollStateResult(msg.what, ar); 95 break; 96 case EVENT_RUIM_RECORDS_LOADED: 97 updatePhoneObject(); 98 RuimRecords ruim = (RuimRecords)mIccRecords; 99 if (ruim != null) { 100 if (ruim.isProvisioned()) { 101 mMdn = ruim.getMdn(); 102 mMin = ruim.getMin(); 103 parseSidNid(ruim.getSid(), ruim.getNid()); 104 mPrlVersion = ruim.getPrlVersion(); 105 mIsMinInfoReady = true; 106 } 107 updateOtaspState(); 108 } 109 // reload eri in case of IMSI changed 110 // eri.xml can be defined by mcc mnc 111 mPhone.prepareEri(); 112 // SID/NID/PRL is loaded. Poll service state 113 // again to update to the roaming state with 114 // the latest variables. 115 pollState(); 116 break; 117 case EVENT_ALL_DATA_DISCONNECTED: 118 long dds = SubscriptionManager.getDefaultDataSubId(); 119 ProxyController.getInstance().unregisterForAllDataDisconnected(dds, this); 120 synchronized(this) { 121 if (mPendingRadioPowerOffAfterDataOff) { 122 if (DBG) log("EVENT_ALL_DATA_DISCONNECTED, turn radio off now."); 123 hangupAndPowerOff(); 124 mPendingRadioPowerOffAfterDataOff = false; 125 } else { 126 log("EVENT_ALL_DATA_DISCONNECTED is stale"); 127 } 128 } 129 break; 130 default: 131 super.handleMessage(msg); 132 } 133 } 134 135 /** 136 * Handle the result of one of the pollState()-related requests 137 */ 138 @Override 139 protected void handlePollStateResultMessage(int what, AsyncResult ar) { 140 if (what == EVENT_POLL_STATE_GPRS) { 141 String states[] = (String[])ar.result; 142 if (DBG) { 143 log("handlePollStateResultMessage: EVENT_POLL_STATE_GPRS states.length=" + 144 states.length + " states=" + states); 145 } 146 147 int type = 0; 148 int regState = -1; 149 if (states.length > 0) { 150 try { 151 regState = Integer.parseInt(states[0]); 152 153 // states[3] (if present) is the current radio technology 154 if (states.length >= 4 && states[3] != null) { 155 type = Integer.parseInt(states[3]); 156 } 157 } catch (NumberFormatException ex) { 158 loge("handlePollStateResultMessage: error parsing GprsRegistrationState: " 159 + ex); 160 } 161 if (states.length >= 10) { 162 int mcc; 163 int mnc; 164 int tac; 165 int pci; 166 int eci; 167 int csgid; 168 String operatorNumeric = null; 169 170 try { 171 operatorNumeric = mNewSS.getOperatorNumeric(); 172 mcc = Integer.parseInt(operatorNumeric.substring(0,3)); 173 } catch (Exception e) { 174 try { 175 operatorNumeric = mSS.getOperatorNumeric(); 176 mcc = Integer.parseInt(operatorNumeric.substring(0,3)); 177 } catch (Exception ex) { 178 loge("handlePollStateResultMessage: bad mcc operatorNumeric=" + 179 operatorNumeric + " ex=" + ex); 180 operatorNumeric = ""; 181 mcc = Integer.MAX_VALUE; 182 } 183 } 184 try { 185 mnc = Integer.parseInt(operatorNumeric.substring(3)); 186 } catch (Exception e) { 187 loge("handlePollStateResultMessage: bad mnc operatorNumeric=" + 188 operatorNumeric + " e=" + e); 189 mnc = Integer.MAX_VALUE; 190 } 191 192 // Use Integer#decode to be generous in what we receive and allow 193 // decimal, hex or octal values. 194 try { 195 tac = Integer.decode(states[6]); 196 } catch (Exception e) { 197 loge("handlePollStateResultMessage: bad tac states[6]=" + 198 states[6] + " e=" + e); 199 tac = Integer.MAX_VALUE; 200 } 201 try { 202 pci = Integer.decode(states[7]); 203 } catch (Exception e) { 204 loge("handlePollStateResultMessage: bad pci states[7]=" + 205 states[7] + " e=" + e); 206 pci = Integer.MAX_VALUE; 207 } 208 try { 209 eci = Integer.decode(states[8]); 210 } catch (Exception e) { 211 loge("handlePollStateResultMessage: bad eci states[8]=" + 212 states[8] + " e=" + e); 213 eci = Integer.MAX_VALUE; 214 } 215 try { 216 csgid = Integer.decode(states[9]); 217 } catch (Exception e) { 218 // FIX: Always bad so don't pollute the logs 219 // loge("handlePollStateResultMessage: bad csgid states[9]=" + 220 // states[9] + " e=" + e); 221 csgid = Integer.MAX_VALUE; 222 } 223 mNewCellIdentityLte = new CellIdentityLte(mcc, mnc, eci, pci, tac); 224 if (DBG) { 225 log("handlePollStateResultMessage: mNewLteCellIdentity=" + 226 mNewCellIdentityLte); 227 } 228 } 229 } 230 231 mNewSS.setRilDataRadioTechnology(type); 232 int dataRegState = regCodeToServiceState(regState); 233 mNewSS.setDataRegState(dataRegState); 234 if (DBG) { 235 log("handlPollStateResultMessage: CdmaLteSST setDataRegState=" + dataRegState 236 + " regState=" + regState 237 + " dataRadioTechnology=" + type); 238 } 239 } else { 240 super.handlePollStateResultMessage(what, ar); 241 } 242 } 243 244 @Override 245 public void pollState() { 246 mPollingContext = new int[1]; 247 mPollingContext[0] = 0; 248 249 switch (mCi.getRadioState()) { 250 case RADIO_UNAVAILABLE: 251 mNewSS.setStateOutOfService(); 252 mNewCellLoc.setStateInvalid(); 253 setSignalStrengthDefaultValues(); 254 mGotCountryCode = false; 255 256 pollStateDone(); 257 break; 258 259 case RADIO_OFF: 260 mNewSS.setStateOff(); 261 mNewCellLoc.setStateInvalid(); 262 setSignalStrengthDefaultValues(); 263 mGotCountryCode = false; 264 265 pollStateDone(); 266 break; 267 268 default: 269 // Issue all poll-related commands at once, then count 270 // down the responses which are allowed to arrive 271 // out-of-order. 272 273 mPollingContext[0]++; 274 // RIL_REQUEST_OPERATOR is necessary for CDMA 275 mCi.getOperator(obtainMessage(EVENT_POLL_STATE_OPERATOR_CDMA, mPollingContext)); 276 277 mPollingContext[0]++; 278 // RIL_REQUEST_VOICE_REGISTRATION_STATE is necessary for CDMA 279 mCi.getVoiceRegistrationState(obtainMessage(EVENT_POLL_STATE_REGISTRATION_CDMA, 280 mPollingContext)); 281 282 mPollingContext[0]++; 283 // RIL_REQUEST_DATA_REGISTRATION_STATE 284 mCi.getDataRegistrationState(obtainMessage(EVENT_POLL_STATE_GPRS, 285 mPollingContext)); 286 break; 287 } 288 } 289 290 @Override 291 protected void pollStateDone() { 292 log("pollStateDone: lte 1 ss=[" + mSS + "] newSS=[" + mNewSS + "]"); 293 294 useDataRegStateForDataOnlyDevices(); 295 296 boolean hasRegistered = mSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE 297 && mNewSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE; 298 299 boolean hasDeregistered = mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE 300 && mNewSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE; 301 302 boolean hasCdmaDataConnectionAttached = 303 mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE 304 && mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE; 305 306 boolean hasCdmaDataConnectionDetached = 307 mSS.getDataRegState() == ServiceState.STATE_IN_SERVICE 308 && mNewSS.getDataRegState() != ServiceState.STATE_IN_SERVICE; 309 310 boolean hasCdmaDataConnectionChanged = 311 mSS.getDataRegState() != mNewSS.getDataRegState(); 312 313 boolean hasVoiceRadioTechnologyChanged = mSS.getRilVoiceRadioTechnology() 314 != mNewSS.getRilVoiceRadioTechnology(); 315 316 boolean hasDataRadioTechnologyChanged = mSS.getRilDataRadioTechnology() 317 != mNewSS.getRilDataRadioTechnology(); 318 319 boolean hasChanged = !mNewSS.equals(mSS); 320 321 boolean hasRoamingOn = !mSS.getRoaming() && mNewSS.getRoaming(); 322 323 boolean hasRoamingOff = mSS.getRoaming() && !mNewSS.getRoaming(); 324 325 boolean hasLocationChanged = !mNewCellLoc.equals(mCellLoc); 326 327 boolean has4gHandoff = 328 mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE && 329 (((mSS.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_LTE) && 330 (mNewSS.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)) || 331 ((mSS.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD) && 332 (mNewSS.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_LTE))); 333 334 boolean hasMultiApnSupport = 335 (((mNewSS.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_LTE) || 336 (mNewSS.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)) && 337 ((mSS.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_LTE) && 338 (mSS.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD))); 339 340 boolean hasLostMultiApnSupport = 341 ((mNewSS.getRilDataRadioTechnology() >= ServiceState.RIL_RADIO_TECHNOLOGY_IS95A) && 342 (mNewSS.getRilDataRadioTechnology() <= ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A)); 343 344 if (DBG) { 345 log("pollStateDone:" 346 + " hasRegistered=" + hasRegistered 347 + " hasDeegistered=" + hasDeregistered 348 + " hasCdmaDataConnectionAttached=" + hasCdmaDataConnectionAttached 349 + " hasCdmaDataConnectionDetached=" + hasCdmaDataConnectionDetached 350 + " hasCdmaDataConnectionChanged=" + hasCdmaDataConnectionChanged 351 + " hasVoiceRadioTechnologyChanged= " + hasVoiceRadioTechnologyChanged 352 + " hasDataRadioTechnologyChanged=" + hasDataRadioTechnologyChanged 353 + " hasChanged=" + hasChanged 354 + " hasRoamingOn=" + hasRoamingOn 355 + " hasRoamingOff=" + hasRoamingOff 356 + " hasLocationChanged=" + hasLocationChanged 357 + " has4gHandoff = " + has4gHandoff 358 + " hasMultiApnSupport=" + hasMultiApnSupport 359 + " hasLostMultiApnSupport=" + hasLostMultiApnSupport); 360 } 361 // Add an event log when connection state changes 362 if (mSS.getVoiceRegState() != mNewSS.getVoiceRegState() 363 || mSS.getDataRegState() != mNewSS.getDataRegState()) { 364 EventLog.writeEvent(EventLogTags.CDMA_SERVICE_STATE_CHANGE, mSS.getVoiceRegState(), 365 mSS.getDataRegState(), mNewSS.getVoiceRegState(), mNewSS.getDataRegState()); 366 } 367 368 ServiceState tss; 369 tss = mSS; 370 mSS = mNewSS; 371 mNewSS = tss; 372 // clean slate for next time 373 mNewSS.setStateOutOfService(); 374 375 CdmaCellLocation tcl = mCellLoc; 376 mCellLoc = mNewCellLoc; 377 mNewCellLoc = tcl; 378 379 mNewSS.setStateOutOfService(); // clean slate for next time 380 381 if (hasVoiceRadioTechnologyChanged) { 382 updatePhoneObject(); 383 } 384 385 if (hasDataRadioTechnologyChanged) { 386 mPhone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE, 387 ServiceState.rilRadioTechnologyToString(mSS.getRilDataRadioTechnology())); 388 } 389 390 if (hasRegistered) { 391 mNetworkAttachedRegistrants.notifyRegistrants(); 392 } 393 394 if (hasChanged) { 395 boolean hasBrandOverride = mUiccController.getUiccCard() == null ? false : 396 (mUiccController.getUiccCard().getOperatorBrandOverride() != null); 397 if (!hasBrandOverride && (mCi.getRadioState().isOn()) && (mPhone.isEriFileLoaded())) { 398 String eriText; 399 // Now the CDMAPhone sees the new ServiceState so it can get the 400 // new ERI text 401 if (mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) { 402 eriText = mPhone.getCdmaEriText(); 403 } else if (mSS.getVoiceRegState() == ServiceState.STATE_POWER_OFF) { 404 eriText = (mIccRecords != null) ? mIccRecords.getServiceProviderName() : null; 405 if (TextUtils.isEmpty(eriText)) { 406 // Sets operator alpha property by retrieving from 407 // build-time system property 408 eriText = SystemProperties.get("ro.cdma.home.operator.alpha"); 409 } 410 } else { 411 // Note that ServiceState.STATE_OUT_OF_SERVICE is valid used 412 // for mRegistrationState 0,2,3 and 4 413 eriText = mPhone.getContext() 414 .getText(com.android.internal.R.string.roamingTextSearching).toString(); 415 } 416 mSS.setOperatorAlphaLong(eriText); 417 } 418 419 if (mUiccApplcation != null && mUiccApplcation.getState() == AppState.APPSTATE_READY && 420 mIccRecords != null) { 421 // SIM is found on the device. If ERI roaming is OFF, and SID/NID matches 422 // one configured in SIM, use operator name from CSIM record. 423 boolean showSpn = 424 ((RuimRecords)mIccRecords).getCsimSpnDisplayCondition(); 425 int iconIndex = mSS.getCdmaEriIconIndex(); 426 427 if (showSpn && (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) && 428 isInHomeSidNid(mSS.getSystemId(), mSS.getNetworkId()) && 429 mIccRecords != null) { 430 mSS.setOperatorAlphaLong(mIccRecords.getServiceProviderName()); 431 } 432 } 433 434 String operatorNumeric; 435 436 mPhone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA, 437 mSS.getOperatorAlphaLong()); 438 439 String prevOperatorNumeric = 440 SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, ""); 441 operatorNumeric = mSS.getOperatorNumeric(); 442 // try to fix the invalid Operator Numeric 443 if (isInvalidOperatorNumeric(operatorNumeric)) { 444 int sid = mSS.getSystemId(); 445 operatorNumeric = fixUnknownMcc(operatorNumeric, sid); 446 } 447 mPhone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, operatorNumeric); 448 updateCarrierMccMncConfiguration(operatorNumeric, 449 prevOperatorNumeric, mPhone.getContext()); 450 451 if (isInvalidOperatorNumeric(operatorNumeric)) { 452 if (DBG) log("operatorNumeric is null"); 453 mPhone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, ""); 454 mGotCountryCode = false; 455 } else { 456 String isoCountryCode = ""; 457 String mcc = operatorNumeric.substring(0, 3); 458 try { 459 isoCountryCode = MccTable.countryCodeForMcc(Integer.parseInt(operatorNumeric 460 .substring(0, 3))); 461 } catch (NumberFormatException ex) { 462 loge("countryCodeForMcc error" + ex); 463 } catch (StringIndexOutOfBoundsException ex) { 464 loge("countryCodeForMcc error" + ex); 465 } 466 467 mPhone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, 468 isoCountryCode); 469 mGotCountryCode = true; 470 471 setOperatorIdd(operatorNumeric); 472 473 if (shouldFixTimeZoneNow(mPhone, operatorNumeric, prevOperatorNumeric, 474 mNeedFixZone)) { 475 fixTimeZone(isoCountryCode); 476 } 477 } 478 479 mPhone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING, 480 mSS.getRoaming() ? "true" : "false"); 481 482 updateSpnDisplay(); 483 mPhone.notifyServiceStateChanged(mSS); 484 } 485 486 if (hasCdmaDataConnectionAttached || has4gHandoff) { 487 mAttachedRegistrants.notifyRegistrants(); 488 } 489 490 if (hasCdmaDataConnectionDetached) { 491 mDetachedRegistrants.notifyRegistrants(); 492 } 493 494 if ((hasCdmaDataConnectionChanged || hasDataRadioTechnologyChanged)) { 495 notifyDataRegStateRilRadioTechnologyChanged(); 496 mPhone.notifyDataConnection(null); 497 } 498 499 if (hasRoamingOn) { 500 mRoamingOnRegistrants.notifyRegistrants(); 501 } 502 503 if (hasRoamingOff) { 504 mRoamingOffRegistrants.notifyRegistrants(); 505 } 506 507 if (hasLocationChanged) { 508 mPhone.notifyLocationChanged(); 509 } 510 511 ArrayList<CellInfo> arrayCi = new ArrayList<CellInfo>(); 512 synchronized(mCellInfo) { 513 CellInfoLte cil = (CellInfoLte)mCellInfo; 514 515 boolean cidChanged = ! mNewCellIdentityLte.equals(mLasteCellIdentityLte); 516 if (hasRegistered || hasDeregistered || cidChanged) { 517 // TODO: Handle the absence of LteCellIdentity 518 long timeStamp = SystemClock.elapsedRealtime() * 1000; 519 boolean registered = mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE; 520 mLasteCellIdentityLte = mNewCellIdentityLte; 521 522 cil.setRegistered(registered); 523 cil.setCellIdentity(mLasteCellIdentityLte); 524 if (DBG) { 525 log("pollStateDone: hasRegistered=" + hasRegistered + 526 " hasDeregistered=" + hasDeregistered + 527 " cidChanged=" + cidChanged + 528 " mCellInfo=" + mCellInfo); 529 } 530 arrayCi.add(mCellInfo); 531 } 532 mPhoneBase.notifyCellInfo(arrayCi); 533 } 534 } 535 536 @Override 537 protected boolean onSignalStrengthResult(AsyncResult ar, boolean isGsm) { 538 if (mSS.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_LTE) { 539 isGsm = true; 540 } 541 boolean ssChanged = super.onSignalStrengthResult(ar, isGsm); 542 543 synchronized (mCellInfo) { 544 if (mSS.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_LTE) { 545 mCellInfoLte.setTimeStamp(SystemClock.elapsedRealtime() * 1000); 546 mCellInfoLte.setTimeStampType(CellInfo.TIMESTAMP_TYPE_JAVA_RIL); 547 mCellInfoLte.getCellSignalStrength() 548 .initialize(mSignalStrength,SignalStrength.INVALID); 549 } 550 if (mCellInfoLte.getCellIdentity() != null) { 551 ArrayList<CellInfo> arrayCi = new ArrayList<CellInfo>(); 552 arrayCi.add(mCellInfoLte); 553 mPhoneBase.notifyCellInfo(arrayCi); 554 } 555 } 556 return ssChanged; 557 } 558 559 @Override 560 public boolean isConcurrentVoiceAndDataAllowed() { 561 // Using the Conncurrent Service Supported flag for CdmaLte devices. 562 return mSS.getCssIndicator() == 1; 563 } 564 565 /** 566 * Check whether the specified SID and NID pair appears in the HOME SID/NID list 567 * read from NV or SIM. 568 * 569 * @return true if provided sid/nid pair belongs to operator's home network. 570 */ 571 private boolean isInHomeSidNid(int sid, int nid) { 572 // if SID/NID is not available, assume this is home network. 573 if (isSidsAllZeros()) return true; 574 575 // length of SID/NID shold be same 576 if (mHomeSystemId.length != mHomeNetworkId.length) return true; 577 578 if (sid == 0) return true; 579 580 for (int i = 0; i < mHomeSystemId.length; i++) { 581 // Use SID only if NID is a reserved value. 582 // SID 0 and NID 0 and 65535 are reserved. (C.0005 2.6.5.2) 583 if ((mHomeSystemId[i] == sid) && 584 ((mHomeNetworkId[i] == 0) || (mHomeNetworkId[i] == 65535) || 585 (nid == 0) || (nid == 65535) || (mHomeNetworkId[i] == nid))) { 586 return true; 587 } 588 } 589 // SID/NID are not in the list. So device is not in home network 590 return false; 591 } 592 593 /** 594 * TODO: Remove when we get new ril/modem for Galaxy Nexus. 595 * 596 * @return all available cell information, the returned List maybe empty but never null. 597 */ 598 @Override 599 public List<CellInfo> getAllCellInfo() { 600 if (mCi.getRilVersion() >= 8) { 601 return super.getAllCellInfo(); 602 } else { 603 ArrayList<CellInfo> arrayList = new ArrayList<CellInfo>(); 604 CellInfo ci; 605 synchronized(mCellInfo) { 606 arrayList.add(mCellInfoLte); 607 } 608 if (DBG) log ("getAllCellInfo: arrayList=" + arrayList); 609 return arrayList; 610 } 611 } 612 613 @Override 614 protected UiccCardApplication getUiccCardApplication() { 615 return mUiccController.getUiccCardApplication(((CDMALTEPhone)mPhone). 616 getPhoneId(), UiccController.APP_FAM_3GPP2); 617 } 618 619 protected void updateCdmaSubscription() { 620 mCi.getCDMASubscription(obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION)); 621 } 622 623 /** 624 * Clean up existing voice and data connection then turn off radio power. 625 * 626 * Hang up the existing voice calls to decrease call drop rate. 627 */ 628 @Override 629 public void powerOffRadioSafely(DcTrackerBase dcTracker) { 630 synchronized (this) { 631 if (!mPendingRadioPowerOffAfterDataOff) { 632 long dds = SubscriptionManager.getDefaultDataSubId(); 633 // To minimize race conditions we call cleanUpAllConnections on 634 // both if else paths instead of before this isDisconnected test. 635 if (dcTracker.isDisconnected() 636 && (dds == mPhone.getSubId() 637 || (dds != mPhone.getSubId() 638 && ProxyController.getInstance().isDataDisconnected(dds)))) { 639 // To minimize race conditions we do this after isDisconnected 640 dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF); 641 if (DBG) log("Data disconnected, turn off radio right away."); 642 hangupAndPowerOff(); 643 } else { 644 dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF); 645 if (dds != mPhone.getSubId() 646 && !ProxyController.getInstance().isDataDisconnected(dds)) { 647 if (DBG) log("Data is active on DDS. Wait for all data disconnect"); 648 // Data is not disconnected on DDS. Wait for the data disconnect complete 649 // before sending the RADIO_POWER off. 650 ProxyController.getInstance().registerForAllDataDisconnected(dds, this, 651 EVENT_ALL_DATA_DISCONNECTED, null); 652 mPendingRadioPowerOffAfterDataOff = true; 653 } 654 Message msg = Message.obtain(this); 655 msg.what = EVENT_SET_RADIO_POWER_OFF; 656 msg.arg1 = ++mPendingRadioPowerOffAfterDataOffTag; 657 if (sendMessageDelayed(msg, 30000)) { 658 if (DBG) log("Wait upto 30s for data to disconnect, then turn off radio."); 659 mPendingRadioPowerOffAfterDataOff = true; 660 } else { 661 log("Cannot send delayed Msg, turn off radio right away."); 662 hangupAndPowerOff(); 663 mPendingRadioPowerOffAfterDataOff = false; 664 } 665 } 666 } 667 } 668 } 669 670 @Override 671 protected void updatePhoneObject() { 672 int voiceRat = mSS.getRilVoiceRadioTechnology(); 673 if (mPhone.getContext().getResources(). 674 getBoolean(com.android.internal.R.bool.config_switch_phone_on_voice_reg_state_change)) { 675 // For CDMA-LTE phone don't update phone to GSM 676 // if replacement RAT is unknown 677 // If there is a real need to switch to LTE, then it will be done via 678 // RIL_UNSOL_VOICE_RADIO_TECH_CHANGED from RIL. 679 680 int volteReplacementRat = mPhoneBase.getContext().getResources().getInteger( 681 com.android.internal.R.integer.config_volte_replacement_rat); 682 Rlog.d(LOG_TAG, "updatePhoneObject: volteReplacementRat=" + volteReplacementRat); 683 684 if (voiceRat == ServiceState.RIL_RADIO_TECHNOLOGY_LTE && 685 volteReplacementRat == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN) { 686 voiceRat = ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT; 687 } 688 mPhoneBase.updatePhoneObject(voiceRat); 689 } 690 } 691 692 @Override 693 protected void log(String s) { 694 Rlog.d(LOG_TAG, "[CdmaLteSST] " + s); 695 } 696 697 @Override 698 protected void loge(String s) { 699 Rlog.e(LOG_TAG, "[CdmaLteSST] " + s); 700 } 701 702 @Override 703 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 704 pw.println("CdmaLteServiceStateTracker extends:"); 705 super.dump(fd, pw, args); 706 pw.println(" mCdmaLtePhone=" + mCdmaLtePhone); 707 } 708 } 709