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