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