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