CDMAPhone.java revision 1260f1c6c909f2940989b72afe1b91fd83845eaa
1/* 2 * Copyright (C) 2006 The Android Open Source Project 3 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package com.android.internal.telephony.cdma; 19 20import android.app.ActivityManagerNative; 21import android.content.ContentValues; 22import android.content.Context; 23import android.content.Intent; 24import android.content.SharedPreferences; 25import android.database.SQLException; 26import android.net.Uri; 27import android.os.AsyncResult; 28import android.os.Handler; 29import android.os.Message; 30import android.os.PowerManager; 31import android.os.PowerManager.WakeLock; 32import android.os.Registrant; 33import android.os.RegistrantList; 34import android.os.SystemProperties; 35import android.os.UserHandle; 36import android.preference.PreferenceManager; 37import android.provider.Telephony; 38import android.telephony.CellLocation; 39import android.telephony.PhoneNumberUtils; 40import android.telephony.ServiceState; 41import android.text.TextUtils; 42import android.telephony.Rlog; 43 44import com.android.internal.telephony.CallStateException; 45import com.android.internal.telephony.CallTracker; 46import com.android.internal.telephony.CommandException; 47import com.android.internal.telephony.CommandsInterface; 48import com.android.internal.telephony.Connection; 49import com.android.internal.telephony.IccPhoneBookInterfaceManager; 50import com.android.internal.telephony.IccSmsInterfaceManager; 51import com.android.internal.telephony.MccTable; 52import com.android.internal.telephony.MmiCode; 53import com.android.internal.telephony.OperatorInfo; 54import com.android.internal.telephony.PhoneBase; 55import com.android.internal.telephony.PhoneConstants; 56import com.android.internal.telephony.PhoneNotifier; 57import com.android.internal.telephony.PhoneProxy; 58import com.android.internal.telephony.PhoneSubInfo; 59import com.android.internal.telephony.ServiceStateTracker; 60import com.android.internal.telephony.SmsBroadcastUndelivered; 61import com.android.internal.telephony.TelephonyIntents; 62import com.android.internal.telephony.TelephonyProperties; 63import com.android.internal.telephony.UUSInfo; 64import com.android.internal.telephony.dataconnection.DcTracker; 65import com.android.internal.telephony.uicc.IccException; 66import com.android.internal.telephony.uicc.IccRecords; 67import com.android.internal.telephony.uicc.RuimRecords; 68import com.android.internal.telephony.uicc.UiccCardApplication; 69import com.android.internal.telephony.uicc.UiccController; 70import java.io.FileDescriptor; 71import java.io.PrintWriter; 72import java.util.ArrayList; 73import java.util.List; 74import java.util.regex.Matcher; 75import java.util.regex.Pattern; 76 77import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA; 78import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY; 79import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC; 80 81/** 82 * {@hide} 83 */ 84public class CDMAPhone extends PhoneBase { 85 static final String LOG_TAG = "CDMAPhone"; 86 private static final boolean DBG = true; 87 private static final boolean VDBG = false; /* STOP SHIP if true */ 88 89 // Default Emergency Callback Mode exit timer 90 private static final int DEFAULT_ECM_EXIT_TIMER_VALUE = 300000; 91 92 static final String VM_COUNT_CDMA = "vm_count_key_cdma"; 93 private static final String VM_NUMBER_CDMA = "vm_number_key_cdma"; 94 private String mVmNumber = null; 95 96 static final int RESTART_ECM_TIMER = 0; // restart Ecm timer 97 static final int CANCEL_ECM_TIMER = 1; // cancel Ecm timer 98 99 // Instance Variables 100 CdmaCallTracker mCT; 101 CdmaServiceStateTracker mSST; 102 CdmaSubscriptionSourceManager mCdmaSSM; 103 ArrayList <CdmaMmiCode> mPendingMmis = new ArrayList<CdmaMmiCode>(); 104 RuimPhoneBookInterfaceManager mRuimPhoneBookInterfaceManager; 105 int mCdmaSubscriptionSource = CdmaSubscriptionSourceManager.SUBSCRIPTION_SOURCE_UNKNOWN; 106 PhoneSubInfo mSubInfo; 107 EriManager mEriManager; 108 WakeLock mWakeLock; 109 110 // mEriFileLoadedRegistrants are informed after the ERI text has been loaded 111 private final RegistrantList mEriFileLoadedRegistrants = new RegistrantList(); 112 113 // mEcmTimerResetRegistrants are informed after Ecm timer is canceled or re-started 114 private final RegistrantList mEcmTimerResetRegistrants = new RegistrantList(); 115 116 // mEcmExitRespRegistrant is informed after the phone has been exited 117 //the emergency callback mode 118 //keep track of if phone is in emergency callback mode 119 private boolean mIsPhoneInEcmState; 120 private Registrant mEcmExitRespRegistrant; 121 protected String mImei; 122 protected String mImeiSv; 123 private String mEsn; 124 private String mMeid; 125 // string to define how the carrier specifies its own ota sp number 126 private String mCarrierOtaSpNumSchema; 127 128 // A runnable which is used to automatically exit from Ecm after a period of time. 129 private Runnable mExitEcmRunnable = new Runnable() { 130 @Override 131 public void run() { 132 exitEmergencyCallbackMode(); 133 } 134 }; 135 136 Registrant mPostDialHandler; 137 138 static String PROPERTY_CDMA_HOME_OPERATOR_NUMERIC = "ro.cdma.home.operator.numeric"; 139 140 // Constructors 141 public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) { 142 super("CDMA", notifier, context, ci, false); 143 initSstIcc(); 144 init(context, notifier); 145 } 146 147 public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, 148 boolean unitTestMode) { 149 super("CDMA", notifier, context, ci, unitTestMode); 150 initSstIcc(); 151 init(context, notifier); 152 } 153 154 protected void initSstIcc() { 155 mSST = new CdmaServiceStateTracker(this); 156 } 157 158 protected void init(Context context, PhoneNotifier notifier) { 159 mCi.setPhoneType(PhoneConstants.PHONE_TYPE_CDMA); 160 mCT = new CdmaCallTracker(this); 161 mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(context, mCi, this, 162 EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null); 163 mDcTracker = new DcTracker(this); 164 mRuimPhoneBookInterfaceManager = new RuimPhoneBookInterfaceManager(this); 165 mSubInfo = new PhoneSubInfo(this); 166 mEriManager = new EriManager(this, context, EriManager.ERI_FROM_XML); 167 168 mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null); 169 mCi.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null); 170 mCi.registerForOn(this, EVENT_RADIO_ON, null); 171 mCi.setOnSuppServiceNotification(this, EVENT_SSN, null); 172 mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null); 173 mCi.setEmergencyCallbackMode(this, EVENT_EMERGENCY_CALLBACK_MODE_ENTER, null); 174 mCi.registerForExitEmergencyCallbackMode(this, EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE, 175 null); 176 177 PowerManager pm 178 = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 179 mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,LOG_TAG); 180 181 //Change the system setting 182 SystemProperties.set(TelephonyProperties.CURRENT_ACTIVE_PHONE, 183 Integer.toString(PhoneConstants.PHONE_TYPE_CDMA)); 184 185 // This is needed to handle phone process crashes 186 String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false"); 187 mIsPhoneInEcmState = inEcm.equals("true"); 188 if (mIsPhoneInEcmState) { 189 // Send a message which will invoke handleExitEmergencyCallbackMode 190 mCi.exitEmergencyCallbackMode(obtainMessage(EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE)); 191 } 192 193 // get the string that specifies the carrier OTA Sp number 194 mCarrierOtaSpNumSchema = SystemProperties.get( 195 TelephonyProperties.PROPERTY_OTASP_NUM_SCHEMA,""); 196 197 // Sets operator alpha property by retrieving from build-time system property 198 String operatorAlpha = SystemProperties.get("ro.cdma.home.operator.alpha"); 199 setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, operatorAlpha); 200 201 // Sets operator numeric property by retrieving from build-time system property 202 String operatorNumeric = SystemProperties.get(PROPERTY_CDMA_HOME_OPERATOR_NUMERIC); 203 if (!TextUtils.isEmpty(operatorNumeric) && 204 (mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP) == null)) { 205 log("CDMAPhone: init set 'gsm.sim.operator.numeric' to operator='" + 206 operatorNumeric + "'"); 207 setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, operatorNumeric); 208 } 209 210 // Sets iso country property by retrieving from build-time system property 211 setIsoCountryProperty(operatorNumeric); 212 213 // Sets current entry in the telephony carrier table 214 updateCurrentCarrierInProvider(operatorNumeric); 215 216 // Notify voicemails. 217 notifier.notifyMessageWaitingChanged(this); 218 } 219 220 @Override 221 public void dispose() { 222 synchronized(PhoneProxy.lockForRadioTechnologyChange) { 223 super.dispose(); 224 log("dispose"); 225 226 //Unregister from all former registered events 227 unregisterForRuimRecordEvents(); 228 mCi.unregisterForAvailable(this); //EVENT_RADIO_AVAILABLE 229 mCi.unregisterForOffOrNotAvailable(this); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE 230 mCi.unregisterForOn(this); //EVENT_RADIO_ON 231 mSST.unregisterForNetworkAttached(this); //EVENT_REGISTERED_TO_NETWORK 232 mCi.unSetOnSuppServiceNotification(this); 233 mCi.unregisterForExitEmergencyCallbackMode(this); 234 removeCallbacks(mExitEcmRunnable); 235 236 mPendingMmis.clear(); 237 238 //Force all referenced classes to unregister their former registered events 239 mCT.dispose(); 240 mDcTracker.dispose(); 241 mSST.dispose(); 242 mCdmaSSM.dispose(this); 243 mRuimPhoneBookInterfaceManager.dispose(); 244 mSubInfo.dispose(); 245 mEriManager.dispose(); 246 } 247 } 248 249 @Override 250 public void removeReferences() { 251 log("removeReferences"); 252 mRuimPhoneBookInterfaceManager = null; 253 mSubInfo = null; 254 mCT = null; 255 mSST = null; 256 mEriManager = null; 257 mExitEcmRunnable = null; 258 super.removeReferences(); 259 } 260 261 @Override 262 protected void finalize() { 263 if(DBG) Rlog.d(LOG_TAG, "CDMAPhone finalized"); 264 if (mWakeLock.isHeld()) { 265 Rlog.e(LOG_TAG, "UNEXPECTED; mWakeLock is held when finalizing."); 266 mWakeLock.release(); 267 } 268 } 269 270 @Override 271 public ServiceState getServiceState() { 272 return mSST.mSS; 273 } 274 275 @Override 276 public CallTracker getCallTracker() { 277 return mCT; 278 } 279 280 @Override 281 public PhoneConstants.State getState() { 282 return mCT.mState; 283 } 284 285 @Override 286 public ServiceStateTracker getServiceStateTracker() { 287 return mSST; 288 } 289 290 @Override 291 public int getPhoneType() { 292 return PhoneConstants.PHONE_TYPE_CDMA; 293 } 294 295 @Override 296 public boolean canTransfer() { 297 Rlog.e(LOG_TAG, "canTransfer: not possible in CDMA"); 298 return false; 299 } 300 301 @Override 302 public CdmaCall getRingingCall() { 303 return mCT.mRingingCall; 304 } 305 306 @Override 307 public void setMute(boolean muted) { 308 mCT.setMute(muted); 309 } 310 311 @Override 312 public boolean getMute() { 313 return mCT.getMute(); 314 } 315 316 @Override 317 public void conference() { 318 // three way calls in CDMA will be handled by feature codes 319 Rlog.e(LOG_TAG, "conference: not possible in CDMA"); 320 } 321 322 @Override 323 public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) { 324 mCi.setPreferredVoicePrivacy(enable, onComplete); 325 } 326 327 @Override 328 public void getEnhancedVoicePrivacy(Message onComplete) { 329 mCi.getPreferredVoicePrivacy(onComplete); 330 } 331 332 @Override 333 public void clearDisconnected() { 334 mCT.clearDisconnected(); 335 } 336 337 @Override 338 public DataActivityState getDataActivityState() { 339 DataActivityState ret = DataActivityState.NONE; 340 341 if (mSST.getCurrentDataConnectionState() == ServiceState.STATE_IN_SERVICE) { 342 343 switch (mDcTracker.getActivity()) { 344 case DATAIN: 345 ret = DataActivityState.DATAIN; 346 break; 347 348 case DATAOUT: 349 ret = DataActivityState.DATAOUT; 350 break; 351 352 case DATAINANDOUT: 353 ret = DataActivityState.DATAINANDOUT; 354 break; 355 356 case DORMANT: 357 ret = DataActivityState.DORMANT; 358 break; 359 360 default: 361 ret = DataActivityState.NONE; 362 break; 363 } 364 } 365 return ret; 366 } 367 368 @Override 369 public Connection 370 dial (String dialString) throws CallStateException { 371 // Need to make sure dialString gets parsed properly 372 String newDialString = PhoneNumberUtils.stripSeparators(dialString); 373 return mCT.dial(newDialString); 374 } 375 376 @Override 377 public Connection dial(String dialString, UUSInfo uusInfo) throws CallStateException { 378 throw new CallStateException("Sending UUS information NOT supported in CDMA!"); 379 } 380 381 @Override 382 public boolean 383 getMessageWaitingIndicator() { 384 return (getVoiceMessageCount() > 0); 385 } 386 387 @Override 388 public List<? extends MmiCode> 389 getPendingMmiCodes() { 390 return mPendingMmis; 391 } 392 393 @Override 394 public void registerForSuppServiceNotification( 395 Handler h, int what, Object obj) { 396 Rlog.e(LOG_TAG, "method registerForSuppServiceNotification is NOT supported in CDMA!"); 397 } 398 399 @Override 400 public CdmaCall getBackgroundCall() { 401 return mCT.mBackgroundCall; 402 } 403 404 @Override 405 public boolean handleInCallMmiCommands(String dialString) { 406 Rlog.e(LOG_TAG, "method handleInCallMmiCommands is NOT supported in CDMA!"); 407 return false; 408 } 409 410 boolean isInCall() { 411 CdmaCall.State foregroundCallState = getForegroundCall().getState(); 412 CdmaCall.State backgroundCallState = getBackgroundCall().getState(); 413 CdmaCall.State ringingCallState = getRingingCall().getState(); 414 415 return (foregroundCallState.isAlive() || backgroundCallState.isAlive() || ringingCallState 416 .isAlive()); 417 } 418 419 @Override 420 public void 421 setNetworkSelectionModeAutomatic(Message response) { 422 Rlog.e(LOG_TAG, "method setNetworkSelectionModeAutomatic is NOT supported in CDMA!"); 423 } 424 425 @Override 426 public void unregisterForSuppServiceNotification(Handler h) { 427 Rlog.e(LOG_TAG, "method unregisterForSuppServiceNotification is NOT supported in CDMA!"); 428 } 429 430 @Override 431 public void 432 acceptCall() throws CallStateException { 433 mCT.acceptCall(); 434 } 435 436 @Override 437 public void 438 rejectCall() throws CallStateException { 439 mCT.rejectCall(); 440 } 441 442 @Override 443 public void 444 switchHoldingAndActive() throws CallStateException { 445 mCT.switchWaitingOrHoldingAndActive(); 446 } 447 448 @Override 449 public String getIccSerialNumber() { 450 IccRecords r = mIccRecords.get(); 451 if (r == null) { 452 // to get ICCID form SIMRecords because it is on MF. 453 r = mUiccController.getIccRecords(UiccController.APP_FAM_3GPP); 454 } 455 return (r != null) ? r.getIccId() : null; 456 } 457 458 @Override 459 public String getLine1Number() { 460 return mSST.getMdnNumber(); 461 } 462 463 @Override 464 public String getCdmaPrlVersion(){ 465 return mSST.getPrlVersion(); 466 } 467 468 @Override 469 public String getCdmaMin() { 470 return mSST.getCdmaMin(); 471 } 472 473 @Override 474 public boolean isMinInfoReady() { 475 return mSST.isMinInfoReady(); 476 } 477 478 @Override 479 public void getCallWaiting(Message onComplete) { 480 mCi.queryCallWaiting(CommandsInterface.SERVICE_CLASS_VOICE, onComplete); 481 } 482 483 @Override 484 public void 485 setRadioPower(boolean power) { 486 mSST.setRadioPower(power); 487 } 488 489 @Override 490 public String getEsn() { 491 return mEsn; 492 } 493 494 @Override 495 public String getMeid() { 496 return mMeid; 497 } 498 499 //returns MEID or ESN in CDMA 500 @Override 501 public String getDeviceId() { 502 String id = getMeid(); 503 if ((id == null) || id.matches("^0*$")) { 504 Rlog.d(LOG_TAG, "getDeviceId(): MEID is not initialized use ESN"); 505 id = getEsn(); 506 } 507 return id; 508 } 509 510 @Override 511 public String getDeviceSvn() { 512 Rlog.d(LOG_TAG, "getDeviceSvn(): return 0"); 513 return "0"; 514 } 515 516 @Override 517 public String getSubscriberId() { 518 return mSST.getImsi(); 519 } 520 521 @Override 522 public String getGroupIdLevel1() { 523 Rlog.e(LOG_TAG, "GID1 is not available in CDMA"); 524 return null; 525 } 526 527 @Override 528 public String getImei() { 529 Rlog.e(LOG_TAG, "IMEI is not available in CDMA"); 530 return null; 531 } 532 533 @Override 534 public boolean canConference() { 535 Rlog.e(LOG_TAG, "canConference: not possible in CDMA"); 536 return false; 537 } 538 539 @Override 540 public CellLocation getCellLocation() { 541 return mSST.mCellLoc; 542 } 543 544 @Override 545 public CdmaCall getForegroundCall() { 546 return mCT.mForegroundCall; 547 } 548 549 @Override 550 public void 551 selectNetworkManually(OperatorInfo network, 552 Message response) { 553 Rlog.e(LOG_TAG, "selectNetworkManually: not possible in CDMA"); 554 } 555 556 @Override 557 public void setOnPostDialCharacter(Handler h, int what, Object obj) { 558 mPostDialHandler = new Registrant(h, what, obj); 559 } 560 561 @Override 562 public boolean handlePinMmi(String dialString) { 563 CdmaMmiCode mmi = CdmaMmiCode.newFromDialString(dialString, this); 564 565 if (mmi == null) { 566 Rlog.e(LOG_TAG, "Mmi is NULL!"); 567 return false; 568 } else if (mmi.isPukCommand()) { 569 mPendingMmis.add(mmi); 570 mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null)); 571 mmi.processCode(); 572 return true; 573 } 574 Rlog.e(LOG_TAG, "Unrecognized mmi!"); 575 return false; 576 } 577 578 /** 579 * Removes the given MMI from the pending list and notifies registrants that 580 * it is complete. 581 * 582 * @param mmi MMI that is done 583 */ 584 void onMMIDone(CdmaMmiCode mmi) { 585 /* 586 * Only notify complete if it's on the pending list. Otherwise, it's 587 * already been handled (eg, previously canceled). 588 */ 589 if (mPendingMmis.remove(mmi)) { 590 mMmiCompleteRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null)); 591 } 592 } 593 594 @Override 595 public void setLine1Number(String alphaTag, String number, Message onComplete) { 596 Rlog.e(LOG_TAG, "setLine1Number: not possible in CDMA"); 597 } 598 599 @Override 600 public void setCallWaiting(boolean enable, Message onComplete) { 601 Rlog.e(LOG_TAG, "method setCallWaiting is NOT supported in CDMA!"); 602 } 603 604 @Override 605 public void updateServiceLocation() { 606 mSST.enableSingleLocationUpdate(); 607 } 608 609 @Override 610 public void setDataRoamingEnabled(boolean enable) { 611 mDcTracker.setDataOnRoamingEnabled(enable); 612 } 613 614 @Override 615 public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) { 616 mCi.registerForCdmaOtaProvision(h, what, obj); 617 } 618 619 @Override 620 public void unregisterForCdmaOtaStatusChange(Handler h) { 621 mCi.unregisterForCdmaOtaProvision(h); 622 } 623 624 @Override 625 public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) { 626 mSST.registerForSubscriptionInfoReady(h, what, obj); 627 } 628 629 @Override 630 public void unregisterForSubscriptionInfoReady(Handler h) { 631 mSST.unregisterForSubscriptionInfoReady(h); 632 } 633 634 @Override 635 public void setOnEcbModeExitResponse(Handler h, int what, Object obj) { 636 mEcmExitRespRegistrant = new Registrant (h, what, obj); 637 } 638 639 @Override 640 public void unsetOnEcbModeExitResponse(Handler h) { 641 mEcmExitRespRegistrant.clear(); 642 } 643 644 @Override 645 public void registerForCallWaiting(Handler h, int what, Object obj) { 646 mCT.registerForCallWaiting(h, what, obj); 647 } 648 649 @Override 650 public void unregisterForCallWaiting(Handler h) { 651 mCT.unregisterForCallWaiting(h); 652 } 653 654 @Override 655 public void 656 getNeighboringCids(Message response) { 657 /* 658 * This is currently not implemented. At least as of June 659 * 2009, there is no neighbor cell information available for 660 * CDMA because some party is resisting making this 661 * information readily available. Consequently, calling this 662 * function can have no useful effect. This situation may 663 * (and hopefully will) change in the future. 664 */ 665 if (response != null) { 666 CommandException ce = new CommandException( 667 CommandException.Error.REQUEST_NOT_SUPPORTED); 668 AsyncResult.forMessage(response).exception = ce; 669 response.sendToTarget(); 670 } 671 } 672 673 @Override 674 public PhoneConstants.DataState getDataConnectionState(String apnType) { 675 PhoneConstants.DataState ret = PhoneConstants.DataState.DISCONNECTED; 676 677 if (mSST == null) { 678 // Radio Technology Change is ongoning, dispose() and removeReferences() have 679 // already been called 680 681 ret = PhoneConstants.DataState.DISCONNECTED; 682 } else if (mSST.getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) { 683 // If we're out of service, open TCP sockets may still work 684 // but no data will flow 685 ret = PhoneConstants.DataState.DISCONNECTED; 686 } else if (mDcTracker.isApnTypeEnabled(apnType) == false || 687 mDcTracker.isApnTypeActive(apnType) == false) { 688 ret = PhoneConstants.DataState.DISCONNECTED; 689 } else { 690 switch (mDcTracker.getState(apnType)) { 691 case RETRYING: 692 case FAILED: 693 case IDLE: 694 ret = PhoneConstants.DataState.DISCONNECTED; 695 break; 696 697 case CONNECTED: 698 case DISCONNECTING: 699 if ( mCT.mState != PhoneConstants.State.IDLE 700 && !mSST.isConcurrentVoiceAndDataAllowed()) { 701 ret = PhoneConstants.DataState.SUSPENDED; 702 } else { 703 ret = PhoneConstants.DataState.CONNECTED; 704 } 705 break; 706 707 case CONNECTING: 708 case SCANNING: 709 ret = PhoneConstants.DataState.CONNECTING; 710 break; 711 } 712 } 713 714 log("getDataConnectionState apnType=" + apnType + " ret=" + ret); 715 return ret; 716 } 717 718 @Override 719 public void sendUssdResponse(String ussdMessge) { 720 Rlog.e(LOG_TAG, "sendUssdResponse: not possible in CDMA"); 721 } 722 723 @Override 724 public void sendDtmf(char c) { 725 if (!PhoneNumberUtils.is12Key(c)) { 726 Rlog.e(LOG_TAG, 727 "sendDtmf called with invalid character '" + c + "'"); 728 } else { 729 if (mCT.mState == PhoneConstants.State.OFFHOOK) { 730 mCi.sendDtmf(c, null); 731 } 732 } 733 } 734 735 @Override 736 public void startDtmf(char c) { 737 if (!PhoneNumberUtils.is12Key(c)) { 738 Rlog.e(LOG_TAG, 739 "startDtmf called with invalid character '" + c + "'"); 740 } else { 741 mCi.startDtmf(c, null); 742 } 743 } 744 745 @Override 746 public void stopDtmf() { 747 mCi.stopDtmf(null); 748 } 749 750 @Override 751 public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) { 752 boolean check = true; 753 for (int itr = 0;itr < dtmfString.length(); itr++) { 754 if (!PhoneNumberUtils.is12Key(dtmfString.charAt(itr))) { 755 Rlog.e(LOG_TAG, 756 "sendDtmf called with invalid character '" + dtmfString.charAt(itr)+ "'"); 757 check = false; 758 break; 759 } 760 } 761 if ((mCT.mState == PhoneConstants.State.OFFHOOK)&&(check)) { 762 mCi.sendBurstDtmf(dtmfString, on, off, onComplete); 763 } 764 } 765 766 @Override 767 public void getAvailableNetworks(Message response) { 768 Rlog.e(LOG_TAG, "getAvailableNetworks: not possible in CDMA"); 769 } 770 771 @Override 772 public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete) { 773 Rlog.e(LOG_TAG, "setOutgoingCallerIdDisplay: not possible in CDMA"); 774 } 775 776 @Override 777 public void enableLocationUpdates() { 778 mSST.enableLocationUpdates(); 779 } 780 781 @Override 782 public void disableLocationUpdates() { 783 mSST.disableLocationUpdates(); 784 } 785 786 @Override 787 public void getDataCallList(Message response) { 788 mCi.getDataCallList(response); 789 } 790 791 @Override 792 public boolean getDataRoamingEnabled() { 793 return mDcTracker.getDataOnRoamingEnabled(); 794 } 795 796 @Override 797 public void setVoiceMailNumber(String alphaTag, 798 String voiceMailNumber, 799 Message onComplete) { 800 Message resp; 801 mVmNumber = voiceMailNumber; 802 resp = obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete); 803 IccRecords r = mIccRecords.get(); 804 if (r != null) { 805 r.setVoiceMailNumber(alphaTag, mVmNumber, resp); 806 } 807 } 808 809 @Override 810 public String getVoiceMailNumber() { 811 String number = null; 812 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 813 // TODO: The default value of voicemail number should be read from a system property 814 815 // Read platform settings for dynamic voicemail number 816 if (getContext().getResources().getBoolean(com.android.internal 817 .R.bool.config_telephony_use_own_number_for_voicemail)) { 818 number = sp.getString(VM_NUMBER_CDMA, getLine1Number()); 819 } else { 820 number = sp.getString(VM_NUMBER_CDMA, "*86"); 821 } 822 return number; 823 } 824 825 /* Returns Number of Voicemails 826 * @hide 827 */ 828 @Override 829 public int getVoiceMessageCount() { 830 IccRecords r = mIccRecords.get(); 831 int voicemailCount = (r != null) ? r.getVoiceMessageCount() : 0; 832 // If mRuimRecords.getVoiceMessageCount returns zero, then there is possibility 833 // that phone was power cycled and would have lost the voicemail count. 834 // So get the count from preferences. 835 if (voicemailCount == 0) { 836 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 837 voicemailCount = sp.getInt(VM_COUNT_CDMA, 0); 838 } 839 return voicemailCount; 840 } 841 842 @Override 843 public String getVoiceMailAlphaTag() { 844 // TODO: Where can we get this value has to be clarified with QC. 845 String ret = "";//TODO: Remove = "", if we know where to get this value. 846 847 //ret = mSIMRecords.getVoiceMailAlphaTag(); 848 849 if (ret == null || ret.length() == 0) { 850 return mContext.getText( 851 com.android.internal.R.string.defaultVoiceMailAlphaTag).toString(); 852 } 853 854 return ret; 855 } 856 857 @Override 858 public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) { 859 Rlog.e(LOG_TAG, "getCallForwardingOption: not possible in CDMA"); 860 } 861 862 @Override 863 public void setCallForwardingOption(int commandInterfaceCFAction, 864 int commandInterfaceCFReason, 865 String dialingNumber, 866 int timerSeconds, 867 Message onComplete) { 868 Rlog.e(LOG_TAG, "setCallForwardingOption: not possible in CDMA"); 869 } 870 871 @Override 872 public void 873 getOutgoingCallerIdDisplay(Message onComplete) { 874 Rlog.e(LOG_TAG, "getOutgoingCallerIdDisplay: not possible in CDMA"); 875 } 876 877 @Override 878 public boolean 879 getCallForwardingIndicator() { 880 Rlog.e(LOG_TAG, "getCallForwardingIndicator: not possible in CDMA"); 881 return false; 882 } 883 884 @Override 885 public void explicitCallTransfer() { 886 Rlog.e(LOG_TAG, "explicitCallTransfer: not possible in CDMA"); 887 } 888 889 @Override 890 public String getLine1AlphaTag() { 891 Rlog.e(LOG_TAG, "getLine1AlphaTag: not possible in CDMA"); 892 return null; 893 } 894 895 /** 896 * Notify any interested party of a Phone state change 897 * {@link com.android.internal.telephony.PhoneConstants.State} 898 */ 899 /*package*/ void notifyPhoneStateChanged() { 900 mNotifier.notifyPhoneState(this); 901 } 902 903 /** 904 * Notify registrants of a change in the call state. This notifies changes in 905 * {@link com.android.internal.telephony.Call.State}. Use this when changes 906 * in the precise call state are needed, else use notifyPhoneStateChanged. 907 */ 908 /*package*/ void notifyPreciseCallStateChanged() { 909 /* we'd love it if this was package-scoped*/ 910 super.notifyPreciseCallStateChangedP(); 911 } 912 913 void notifyServiceStateChanged(ServiceState ss) { 914 super.notifyServiceStateChangedP(ss); 915 } 916 917 void notifyLocationChanged() { 918 mNotifier.notifyCellLocation(this); 919 } 920 921 /*package*/ void notifyNewRingingConnection(Connection c) { 922 /* we'd love it if this was package-scoped*/ 923 super.notifyNewRingingConnectionP(c); 924 } 925 926 /*package*/ void notifyDisconnect(Connection cn) { 927 mDisconnectRegistrants.notifyResult(cn); 928 } 929 930 void notifyUnknownConnection() { 931 mUnknownConnectionRegistrants.notifyResult(this); 932 } 933 934 @Override 935 public boolean isInEmergencyCall() { 936 return mCT.isInEmergencyCall(); 937 } 938 939 @Override 940 public boolean isInEcm() { 941 return mIsPhoneInEcmState; 942 } 943 944 void sendEmergencyCallbackModeChange(){ 945 //Send an Intent 946 Intent intent = new Intent(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); 947 intent.putExtra(PhoneConstants.PHONE_IN_ECM_STATE, mIsPhoneInEcmState); 948 ActivityManagerNative.broadcastStickyIntent(intent,null,UserHandle.USER_ALL); 949 if (DBG) Rlog.d(LOG_TAG, "sendEmergencyCallbackModeChange"); 950 } 951 952 @Override 953 public void exitEmergencyCallbackMode() { 954 if (mWakeLock.isHeld()) { 955 mWakeLock.release(); 956 } 957 // Send a message which will invoke handleExitEmergencyCallbackMode 958 mCi.exitEmergencyCallbackMode(obtainMessage(EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE)); 959 } 960 961 private void handleEnterEmergencyCallbackMode(Message msg) { 962 if (DBG) { 963 Rlog.d(LOG_TAG, "handleEnterEmergencyCallbackMode,mIsPhoneInEcmState= " 964 + mIsPhoneInEcmState); 965 } 966 // if phone is not in Ecm mode, and it's changed to Ecm mode 967 if (mIsPhoneInEcmState == false) { 968 mIsPhoneInEcmState = true; 969 // notify change 970 sendEmergencyCallbackModeChange(); 971 setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE, "true"); 972 973 // Post this runnable so we will automatically exit 974 // if no one invokes exitEmergencyCallbackMode() directly. 975 long delayInMillis = SystemProperties.getLong( 976 TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE); 977 postDelayed(mExitEcmRunnable, delayInMillis); 978 // We don't want to go to sleep while in Ecm 979 mWakeLock.acquire(); 980 } 981 } 982 983 private void handleExitEmergencyCallbackMode(Message msg) { 984 AsyncResult ar = (AsyncResult)msg.obj; 985 if (DBG) { 986 Rlog.d(LOG_TAG, "handleExitEmergencyCallbackMode,ar.exception , mIsPhoneInEcmState " 987 + ar.exception + mIsPhoneInEcmState); 988 } 989 // Remove pending exit Ecm runnable, if any 990 removeCallbacks(mExitEcmRunnable); 991 992 if (mEcmExitRespRegistrant != null) { 993 mEcmExitRespRegistrant.notifyRegistrant(ar); 994 } 995 // if exiting ecm success 996 if (ar.exception == null) { 997 if (mIsPhoneInEcmState) { 998 mIsPhoneInEcmState = false; 999 setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE, "false"); 1000 } 1001 // send an Intent 1002 sendEmergencyCallbackModeChange(); 1003 // Re-initiate data connection 1004 mDcTracker.setInternalDataEnabled(true); 1005 } 1006 } 1007 1008 /** 1009 * Handle to cancel or restart Ecm timer in emergency call back mode 1010 * if action is CANCEL_ECM_TIMER, cancel Ecm timer and notify apps the timer is canceled; 1011 * otherwise, restart Ecm timer and notify apps the timer is restarted. 1012 */ 1013 void handleTimerInEmergencyCallbackMode(int action) { 1014 switch(action) { 1015 case CANCEL_ECM_TIMER: 1016 removeCallbacks(mExitEcmRunnable); 1017 mEcmTimerResetRegistrants.notifyResult(Boolean.TRUE); 1018 break; 1019 case RESTART_ECM_TIMER: 1020 long delayInMillis = SystemProperties.getLong( 1021 TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE); 1022 postDelayed(mExitEcmRunnable, delayInMillis); 1023 mEcmTimerResetRegistrants.notifyResult(Boolean.FALSE); 1024 break; 1025 default: 1026 Rlog.e(LOG_TAG, "handleTimerInEmergencyCallbackMode, unsupported action " + action); 1027 } 1028 } 1029 1030 /** 1031 * Registration point for Ecm timer reset 1032 * @param h handler to notify 1033 * @param what User-defined message code 1034 * @param obj placed in Message.obj 1035 */ 1036 @Override 1037 public void registerForEcmTimerReset(Handler h, int what, Object obj) { 1038 mEcmTimerResetRegistrants.addUnique(h, what, obj); 1039 } 1040 1041 @Override 1042 public void unregisterForEcmTimerReset(Handler h) { 1043 mEcmTimerResetRegistrants.remove(h); 1044 } 1045 1046 @Override 1047 public void handleMessage(Message msg) { 1048 AsyncResult ar; 1049 Message onComplete; 1050 1051 if (!mIsTheCurrentActivePhone) { 1052 Rlog.e(LOG_TAG, "Received message " + msg + 1053 "[" + msg.what + "] while being destroyed. Ignoring."); 1054 return; 1055 } 1056 switch(msg.what) { 1057 case EVENT_RADIO_AVAILABLE: { 1058 mCi.getBasebandVersion(obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE)); 1059 1060 mCi.getDeviceIdentity(obtainMessage(EVENT_GET_DEVICE_IDENTITY_DONE)); 1061 } 1062 break; 1063 1064 case EVENT_GET_BASEBAND_VERSION_DONE:{ 1065 ar = (AsyncResult)msg.obj; 1066 1067 if (ar.exception != null) { 1068 break; 1069 } 1070 1071 if (DBG) Rlog.d(LOG_TAG, "Baseband version: " + ar.result); 1072 setSystemProperty(TelephonyProperties.PROPERTY_BASEBAND_VERSION, (String)ar.result); 1073 } 1074 break; 1075 1076 case EVENT_GET_DEVICE_IDENTITY_DONE:{ 1077 ar = (AsyncResult)msg.obj; 1078 1079 if (ar.exception != null) { 1080 break; 1081 } 1082 String[] respId = (String[])ar.result; 1083 mImei = respId[0]; 1084 mImeiSv = respId[1]; 1085 mEsn = respId[2]; 1086 mMeid = respId[3]; 1087 } 1088 break; 1089 1090 case EVENT_EMERGENCY_CALLBACK_MODE_ENTER:{ 1091 handleEnterEmergencyCallbackMode(msg); 1092 } 1093 break; 1094 1095 case EVENT_ICC_RECORD_EVENTS: 1096 ar = (AsyncResult)msg.obj; 1097 processIccRecordEvents((Integer)ar.result); 1098 break; 1099 1100 case EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE:{ 1101 handleExitEmergencyCallbackMode(msg); 1102 } 1103 break; 1104 1105 case EVENT_RUIM_RECORDS_LOADED:{ 1106 Rlog.d(LOG_TAG, "Event EVENT_RUIM_RECORDS_LOADED Received"); 1107 updateCurrentCarrierInProvider(); 1108 } 1109 break; 1110 1111 case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:{ 1112 Rlog.d(LOG_TAG, "Event EVENT_RADIO_OFF_OR_NOT_AVAILABLE Received"); 1113 } 1114 break; 1115 1116 case EVENT_RADIO_ON:{ 1117 Rlog.d(LOG_TAG, "Event EVENT_RADIO_ON Received"); 1118 handleCdmaSubscriptionSource(mCdmaSSM.getCdmaSubscriptionSource()); 1119 } 1120 break; 1121 1122 case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED:{ 1123 Rlog.d(LOG_TAG, "EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED"); 1124 handleCdmaSubscriptionSource(mCdmaSSM.getCdmaSubscriptionSource()); 1125 } 1126 break; 1127 1128 case EVENT_SSN:{ 1129 Rlog.d(LOG_TAG, "Event EVENT_SSN Received"); 1130 } 1131 break; 1132 1133 case EVENT_REGISTERED_TO_NETWORK:{ 1134 Rlog.d(LOG_TAG, "Event EVENT_REGISTERED_TO_NETWORK Received"); 1135 } 1136 break; 1137 1138 case EVENT_NV_READY:{ 1139 Rlog.d(LOG_TAG, "Event EVENT_NV_READY Received"); 1140 prepareEri(); 1141 } 1142 break; 1143 1144 case EVENT_SET_VM_NUMBER_DONE:{ 1145 ar = (AsyncResult)msg.obj; 1146 if (IccException.class.isInstance(ar.exception)) { 1147 storeVoiceMailNumber(mVmNumber); 1148 ar.exception = null; 1149 } 1150 onComplete = (Message) ar.userObj; 1151 if (onComplete != null) { 1152 AsyncResult.forMessage(onComplete, ar.result, ar.exception); 1153 onComplete.sendToTarget(); 1154 } 1155 } 1156 break; 1157 1158 default:{ 1159 super.handleMessage(msg); 1160 } 1161 } 1162 } 1163 1164 @Override 1165 protected void onUpdateIccAvailability() { 1166 if (mUiccController == null ) { 1167 return; 1168 } 1169 1170 UiccCardApplication newUiccApplication = 1171 mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP2); 1172 1173 if (newUiccApplication == null) { 1174 log("can't find 3GPP2 application; trying APP_FAM_3GPP"); 1175 newUiccApplication = mUiccController 1176 .getUiccCardApplication(UiccController.APP_FAM_3GPP); 1177 } 1178 1179 UiccCardApplication app = mUiccApplication.get(); 1180 if (app != newUiccApplication) { 1181 if (app != null) { 1182 log("Removing stale icc objects."); 1183 if (mIccRecords.get() != null) { 1184 unregisterForRuimRecordEvents(); 1185 mRuimPhoneBookInterfaceManager.updateIccRecords(null); 1186 } 1187 mIccRecords.set(null); 1188 mUiccApplication.set(null); 1189 } 1190 if (newUiccApplication != null) { 1191 log("New Uicc application found"); 1192 mUiccApplication.set(newUiccApplication); 1193 mIccRecords.set(newUiccApplication.getIccRecords()); 1194 registerForRuimRecordEvents(); 1195 mRuimPhoneBookInterfaceManager.updateIccRecords(mIccRecords.get()); 1196 } 1197 } 1198 } 1199 1200 private void processIccRecordEvents(int eventCode) { 1201 switch (eventCode) { 1202 case RuimRecords.EVENT_MWI: 1203 notifyMessageWaitingIndicator(); 1204 break; 1205 1206 default: 1207 Rlog.e(LOG_TAG,"Unknown icc records event code " + eventCode); 1208 break; 1209 } 1210 } 1211 1212 /** 1213 * Handles the call to get the subscription source 1214 * 1215 * @param newSubscriptionSource holds the new CDMA subscription source value 1216 */ 1217 private void handleCdmaSubscriptionSource(int newSubscriptionSource) { 1218 if (newSubscriptionSource != mCdmaSubscriptionSource) { 1219 mCdmaSubscriptionSource = newSubscriptionSource; 1220 if (newSubscriptionSource == CDMA_SUBSCRIPTION_NV) { 1221 // NV is ready when subscription source is NV 1222 sendMessage(obtainMessage(EVENT_NV_READY)); 1223 } 1224 } 1225 } 1226 1227 /** 1228 * Retrieves the PhoneSubInfo of the CDMAPhone 1229 */ 1230 @Override 1231 public PhoneSubInfo getPhoneSubInfo() { 1232 return mSubInfo; 1233 } 1234 1235 /** 1236 * Retrieves the IccPhoneBookInterfaceManager of the CDMAPhone 1237 */ 1238 @Override 1239 public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager() { 1240 return mRuimPhoneBookInterfaceManager; 1241 } 1242 1243 public void registerForEriFileLoaded(Handler h, int what, Object obj) { 1244 Registrant r = new Registrant (h, what, obj); 1245 mEriFileLoadedRegistrants.add(r); 1246 } 1247 1248 public void unregisterForEriFileLoaded(Handler h) { 1249 mEriFileLoadedRegistrants.remove(h); 1250 } 1251 1252 // override for allowing access from other classes of this package 1253 /** 1254 * {@inheritDoc} 1255 */ 1256 @Override 1257 public final void setSystemProperty(String property, String value) { 1258 super.setSystemProperty(property, value); 1259 } 1260 1261 /** 1262 * Activate or deactivate cell broadcast SMS. 1263 * 1264 * @param activate 0 = activate, 1 = deactivate 1265 * @param response Callback message is empty on completion 1266 */ 1267 @Override 1268 public void activateCellBroadcastSms(int activate, Message response) { 1269 Rlog.e(LOG_TAG, "[CDMAPhone] activateCellBroadcastSms() is obsolete; use SmsManager"); 1270 response.sendToTarget(); 1271 } 1272 1273 /** 1274 * Query the current configuration of cdma cell broadcast SMS. 1275 * 1276 * @param response Callback message is empty on completion 1277 */ 1278 @Override 1279 public void getCellBroadcastSmsConfig(Message response) { 1280 Rlog.e(LOG_TAG, "[CDMAPhone] getCellBroadcastSmsConfig() is obsolete; use SmsManager"); 1281 response.sendToTarget(); 1282 } 1283 1284 /** 1285 * Configure cdma cell broadcast SMS. 1286 * 1287 * @param response Callback message is empty on completion 1288 */ 1289 @Override 1290 public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response) { 1291 Rlog.e(LOG_TAG, "[CDMAPhone] setCellBroadcastSmsConfig() is obsolete; use SmsManager"); 1292 response.sendToTarget(); 1293 } 1294 1295 /** 1296 * Returns true if OTA Service Provisioning needs to be performed. 1297 */ 1298 @Override 1299 public boolean needsOtaServiceProvisioning() { 1300 return mSST.getOtasp() != ServiceStateTracker.OTASP_NOT_NEEDED; 1301 } 1302 1303 private static final String IS683A_FEATURE_CODE = "*228"; 1304 private static final int IS683A_FEATURE_CODE_NUM_DIGITS = 4; 1305 private static final int IS683A_SYS_SEL_CODE_NUM_DIGITS = 2; 1306 private static final int IS683A_SYS_SEL_CODE_OFFSET = 4; 1307 1308 private static final int IS683_CONST_800MHZ_A_BAND = 0; 1309 private static final int IS683_CONST_800MHZ_B_BAND = 1; 1310 private static final int IS683_CONST_1900MHZ_A_BLOCK = 2; 1311 private static final int IS683_CONST_1900MHZ_B_BLOCK = 3; 1312 private static final int IS683_CONST_1900MHZ_C_BLOCK = 4; 1313 private static final int IS683_CONST_1900MHZ_D_BLOCK = 5; 1314 private static final int IS683_CONST_1900MHZ_E_BLOCK = 6; 1315 private static final int IS683_CONST_1900MHZ_F_BLOCK = 7; 1316 private static final int INVALID_SYSTEM_SELECTION_CODE = -1; 1317 1318 private static boolean isIs683OtaSpDialStr(String dialStr) { 1319 int sysSelCodeInt; 1320 boolean isOtaspDialString = false; 1321 int dialStrLen = dialStr.length(); 1322 1323 if (dialStrLen == IS683A_FEATURE_CODE_NUM_DIGITS) { 1324 if (dialStr.equals(IS683A_FEATURE_CODE)) { 1325 isOtaspDialString = true; 1326 } 1327 } else { 1328 sysSelCodeInt = extractSelCodeFromOtaSpNum(dialStr); 1329 switch (sysSelCodeInt) { 1330 case IS683_CONST_800MHZ_A_BAND: 1331 case IS683_CONST_800MHZ_B_BAND: 1332 case IS683_CONST_1900MHZ_A_BLOCK: 1333 case IS683_CONST_1900MHZ_B_BLOCK: 1334 case IS683_CONST_1900MHZ_C_BLOCK: 1335 case IS683_CONST_1900MHZ_D_BLOCK: 1336 case IS683_CONST_1900MHZ_E_BLOCK: 1337 case IS683_CONST_1900MHZ_F_BLOCK: 1338 isOtaspDialString = true; 1339 break; 1340 default: 1341 break; 1342 } 1343 } 1344 return isOtaspDialString; 1345 } 1346 /** 1347 * This function extracts the system selection code from the dial string. 1348 */ 1349 private static int extractSelCodeFromOtaSpNum(String dialStr) { 1350 int dialStrLen = dialStr.length(); 1351 int sysSelCodeInt = INVALID_SYSTEM_SELECTION_CODE; 1352 1353 if ((dialStr.regionMatches(0, IS683A_FEATURE_CODE, 1354 0, IS683A_FEATURE_CODE_NUM_DIGITS)) && 1355 (dialStrLen >= (IS683A_FEATURE_CODE_NUM_DIGITS + 1356 IS683A_SYS_SEL_CODE_NUM_DIGITS))) { 1357 // Since we checked the condition above, the system selection code 1358 // extracted from dialStr will not cause any exception 1359 sysSelCodeInt = Integer.parseInt ( 1360 dialStr.substring (IS683A_FEATURE_CODE_NUM_DIGITS, 1361 IS683A_FEATURE_CODE_NUM_DIGITS + IS683A_SYS_SEL_CODE_NUM_DIGITS)); 1362 } 1363 if (DBG) Rlog.d(LOG_TAG, "extractSelCodeFromOtaSpNum " + sysSelCodeInt); 1364 return sysSelCodeInt; 1365 } 1366 1367 /** 1368 * This function checks if the system selection code extracted from 1369 * the dial string "sysSelCodeInt' is the system selection code specified 1370 * in the carrier ota sp number schema "sch". 1371 */ 1372 private static boolean 1373 checkOtaSpNumBasedOnSysSelCode (int sysSelCodeInt, String sch[]) { 1374 boolean isOtaSpNum = false; 1375 try { 1376 // Get how many number of system selection code ranges 1377 int selRc = Integer.parseInt(sch[1]); 1378 for (int i = 0; i < selRc; i++) { 1379 if (!TextUtils.isEmpty(sch[i+2]) && !TextUtils.isEmpty(sch[i+3])) { 1380 int selMin = Integer.parseInt(sch[i+2]); 1381 int selMax = Integer.parseInt(sch[i+3]); 1382 // Check if the selection code extracted from the dial string falls 1383 // within any of the range pairs specified in the schema. 1384 if ((sysSelCodeInt >= selMin) && (sysSelCodeInt <= selMax)) { 1385 isOtaSpNum = true; 1386 break; 1387 } 1388 } 1389 } 1390 } catch (NumberFormatException ex) { 1391 // If the carrier ota sp number schema is not correct, we still allow dial 1392 // and only log the error: 1393 Rlog.e(LOG_TAG, "checkOtaSpNumBasedOnSysSelCode, error", ex); 1394 } 1395 return isOtaSpNum; 1396 } 1397 1398 // Define the pattern/format for carrier specified OTASP number schema. 1399 // It separates by comma and/or whitespace. 1400 private static Pattern pOtaSpNumSchema = Pattern.compile("[,\\s]+"); 1401 1402 /** 1403 * The following function checks if a dial string is a carrier specified 1404 * OTASP number or not by checking against the OTASP number schema stored 1405 * in PROPERTY_OTASP_NUM_SCHEMA. 1406 * 1407 * Currently, there are 2 schemas for carriers to specify the OTASP number: 1408 * 1) Use system selection code: 1409 * The schema is: 1410 * SELC,the # of code pairs,min1,max1,min2,max2,... 1411 * e.g "SELC,3,10,20,30,40,60,70" indicates that there are 3 pairs of 1412 * selection codes, and they are {10,20}, {30,40} and {60,70} respectively. 1413 * 1414 * 2) Use feature code: 1415 * The schema is: 1416 * "FC,length of feature code,feature code". 1417 * e.g "FC,2,*2" indicates that the length of the feature code is 2, 1418 * and the code itself is "*2". 1419 */ 1420 private boolean isCarrierOtaSpNum(String dialStr) { 1421 boolean isOtaSpNum = false; 1422 int sysSelCodeInt = extractSelCodeFromOtaSpNum(dialStr); 1423 if (sysSelCodeInt == INVALID_SYSTEM_SELECTION_CODE) { 1424 return isOtaSpNum; 1425 } 1426 // mCarrierOtaSpNumSchema is retrieved from PROPERTY_OTASP_NUM_SCHEMA: 1427 if (!TextUtils.isEmpty(mCarrierOtaSpNumSchema)) { 1428 Matcher m = pOtaSpNumSchema.matcher(mCarrierOtaSpNumSchema); 1429 if (DBG) { 1430 Rlog.d(LOG_TAG, "isCarrierOtaSpNum,schema" + mCarrierOtaSpNumSchema); 1431 } 1432 1433 if (m.find()) { 1434 String sch[] = pOtaSpNumSchema.split(mCarrierOtaSpNumSchema); 1435 // If carrier uses system selection code mechanism 1436 if (!TextUtils.isEmpty(sch[0]) && sch[0].equals("SELC")) { 1437 if (sysSelCodeInt!=INVALID_SYSTEM_SELECTION_CODE) { 1438 isOtaSpNum=checkOtaSpNumBasedOnSysSelCode(sysSelCodeInt,sch); 1439 } else { 1440 if (DBG) { 1441 Rlog.d(LOG_TAG, "isCarrierOtaSpNum,sysSelCodeInt is invalid"); 1442 } 1443 } 1444 } else if (!TextUtils.isEmpty(sch[0]) && sch[0].equals("FC")) { 1445 int fcLen = Integer.parseInt(sch[1]); 1446 String fc = sch[2]; 1447 if (dialStr.regionMatches(0,fc,0,fcLen)) { 1448 isOtaSpNum = true; 1449 } else { 1450 if (DBG) Rlog.d(LOG_TAG, "isCarrierOtaSpNum,not otasp number"); 1451 } 1452 } else { 1453 if (DBG) { 1454 Rlog.d(LOG_TAG, "isCarrierOtaSpNum,ota schema not supported" + sch[0]); 1455 } 1456 } 1457 } else { 1458 if (DBG) { 1459 Rlog.d(LOG_TAG, "isCarrierOtaSpNum,ota schema pattern not right" + 1460 mCarrierOtaSpNumSchema); 1461 } 1462 } 1463 } else { 1464 if (DBG) Rlog.d(LOG_TAG, "isCarrierOtaSpNum,ota schema pattern empty"); 1465 } 1466 return isOtaSpNum; 1467 } 1468 1469 /** 1470 * isOTASPNumber: checks a given number against the IS-683A OTASP dial string and carrier 1471 * OTASP dial string. 1472 * 1473 * @param dialStr the number to look up. 1474 * @return true if the number is in IS-683A OTASP dial string or carrier OTASP dial string 1475 */ 1476 @Override 1477 public boolean isOtaSpNumber(String dialStr){ 1478 boolean isOtaSpNum = false; 1479 String dialableStr = PhoneNumberUtils.extractNetworkPortionAlt(dialStr); 1480 if (dialableStr != null) { 1481 isOtaSpNum = isIs683OtaSpDialStr(dialableStr); 1482 if (isOtaSpNum == false) { 1483 isOtaSpNum = isCarrierOtaSpNum(dialableStr); 1484 } 1485 } 1486 if (DBG) Rlog.d(LOG_TAG, "isOtaSpNumber " + isOtaSpNum); 1487 return isOtaSpNum; 1488 } 1489 1490 @Override 1491 public int getCdmaEriIconIndex() { 1492 return getServiceState().getCdmaEriIconIndex(); 1493 } 1494 1495 /** 1496 * Returns the CDMA ERI icon mode, 1497 * 0 - ON 1498 * 1 - FLASHING 1499 */ 1500 @Override 1501 public int getCdmaEriIconMode() { 1502 return getServiceState().getCdmaEriIconMode(); 1503 } 1504 1505 /** 1506 * Returns the CDMA ERI text, 1507 */ 1508 @Override 1509 public String getCdmaEriText() { 1510 int roamInd = getServiceState().getCdmaRoamingIndicator(); 1511 int defRoamInd = getServiceState().getCdmaDefaultRoamingIndicator(); 1512 return mEriManager.getCdmaEriText(roamInd, defRoamInd); 1513 } 1514 1515 /** 1516 * Store the voicemail number in preferences 1517 */ 1518 private void storeVoiceMailNumber(String number) { 1519 // Update the preference value of voicemail number 1520 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 1521 SharedPreferences.Editor editor = sp.edit(); 1522 editor.putString(VM_NUMBER_CDMA, number); 1523 editor.apply(); 1524 } 1525 1526 /** 1527 * Sets PROPERTY_ICC_OPERATOR_ISO_COUNTRY property 1528 * 1529 */ 1530 private void setIsoCountryProperty(String operatorNumeric) { 1531 if (TextUtils.isEmpty(operatorNumeric)) { 1532 setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, ""); 1533 } else { 1534 String iso = ""; 1535 try { 1536 iso = MccTable.countryCodeForMcc(Integer.parseInt( 1537 operatorNumeric.substring(0,3))); 1538 } catch (NumberFormatException ex) { 1539 Rlog.w(LOG_TAG, "countryCodeForMcc error" + ex); 1540 } catch (StringIndexOutOfBoundsException ex) { 1541 Rlog.w(LOG_TAG, "countryCodeForMcc error" + ex); 1542 } 1543 1544 setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, iso); 1545 } 1546 } 1547 1548 /** 1549 * Sets the "current" field in the telephony provider according to the 1550 * build-time operator numeric property 1551 * 1552 * @return true for success; false otherwise. 1553 */ 1554 boolean updateCurrentCarrierInProvider(String operatorNumeric) { 1555 if (!TextUtils.isEmpty(operatorNumeric)) { 1556 try { 1557 Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current"); 1558 ContentValues map = new ContentValues(); 1559 map.put(Telephony.Carriers.NUMERIC, operatorNumeric); 1560 log("updateCurrentCarrierInProvider from system: numeric=" + operatorNumeric); 1561 getContext().getContentResolver().insert(uri, map); 1562 1563 // Updates MCC MNC device configuration information 1564 MccTable.updateMccMncConfiguration(mContext, operatorNumeric); 1565 1566 return true; 1567 } catch (SQLException e) { 1568 Rlog.e(LOG_TAG, "Can't store current operator", e); 1569 } 1570 } 1571 return false; 1572 } 1573 1574 /** 1575 * Sets the "current" field in the telephony provider according to the SIM's operator. 1576 * Implemented in {@link CDMALTEPhone} for CDMA/LTE devices. 1577 * 1578 * @return true for success; false otherwise. 1579 */ 1580 boolean updateCurrentCarrierInProvider() { 1581 return true; 1582 } 1583 1584 public void prepareEri() { 1585 mEriManager.loadEriFile(); 1586 if(mEriManager.isEriFileLoaded()) { 1587 // when the ERI file is loaded 1588 log("ERI read, notify registrants"); 1589 mEriFileLoadedRegistrants.notifyRegistrants(); 1590 } 1591 } 1592 1593 public boolean isEriFileLoaded() { 1594 return mEriManager.isEriFileLoaded(); 1595 } 1596 1597 protected void registerForRuimRecordEvents() { 1598 IccRecords r = mIccRecords.get(); 1599 if (r == null) { 1600 return; 1601 } 1602 r.registerForRecordsEvents(this, EVENT_ICC_RECORD_EVENTS, null); 1603 r.registerForRecordsLoaded(this, EVENT_RUIM_RECORDS_LOADED, null); 1604 } 1605 1606 protected void unregisterForRuimRecordEvents() { 1607 IccRecords r = mIccRecords.get(); 1608 if (r == null) { 1609 return; 1610 } 1611 r.unregisterForRecordsEvents(this); 1612 r.unregisterForRecordsLoaded(this); 1613 } 1614 1615 protected void log(String s) { 1616 if (DBG) 1617 Rlog.d(LOG_TAG, s); 1618 } 1619 1620 @Override 1621 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1622 pw.println("CDMAPhone extends:"); 1623 super.dump(fd, pw, args); 1624 pw.println(" mVmNumber=" + mVmNumber); 1625 pw.println(" mCT=" + mCT); 1626 pw.println(" mSST=" + mSST); 1627 pw.println(" mCdmaSSM=" + mCdmaSSM); 1628 pw.println(" mPendingMmis=" + mPendingMmis); 1629 pw.println(" mRuimPhoneBookInterfaceManager=" + mRuimPhoneBookInterfaceManager); 1630 pw.println(" mCdmaSubscriptionSource=" + mCdmaSubscriptionSource); 1631 pw.println(" mSubInfo=" + mSubInfo); 1632 pw.println(" mEriManager=" + mEriManager); 1633 pw.println(" mWakeLock=" + mWakeLock); 1634 pw.println(" mIsPhoneInEcmState=" + mIsPhoneInEcmState); 1635 if (VDBG) pw.println(" mImei=" + mImei); 1636 if (VDBG) pw.println(" mImeiSv=" + mImeiSv); 1637 if (VDBG) pw.println(" mEsn=" + mEsn); 1638 if (VDBG) pw.println(" mMeid=" + mMeid); 1639 pw.println(" mCarrierOtaSpNumSchema=" + mCarrierOtaSpNumSchema); 1640 pw.println(" getCdmaEriIconIndex()=" + getCdmaEriIconIndex()); 1641 pw.println(" getCdmaEriIconMode()=" + getCdmaEriIconMode()); 1642 pw.println(" getCdmaEriText()=" + getCdmaEriText()); 1643 pw.println(" isMinInfoReady()=" + isMinInfoReady()); 1644 pw.println(" isCspPlmnEnabled()=" + isCspPlmnEnabled()); 1645 } 1646} 1647