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