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