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