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