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