CDMAPhone.java revision 019581bf6055eb69ee7e4cb844dafe2b6c23597e
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.Intent; 22import android.content.SharedPreferences; 23import android.os.AsyncResult; 24import android.os.Handler; 25import android.os.Looper; 26import android.os.Message; 27import android.os.Registrant; 28import android.os.RegistrantList; 29import android.os.SystemProperties; 30import android.preference.PreferenceManager; 31import android.provider.Settings; 32import android.telephony.CellLocation; 33import android.telephony.PhoneNumberUtils; 34import android.telephony.ServiceState; 35import android.telephony.SignalStrength; 36import android.text.TextUtils; 37import android.util.Log; 38 39import com.android.internal.telephony.CallStateException; 40import com.android.internal.telephony.CommandException; 41import com.android.internal.telephony.CommandsInterface; 42import com.android.internal.telephony.Connection; 43import com.android.internal.telephony.DataConnection; 44import com.android.internal.telephony.IccCard; 45import com.android.internal.telephony.IccException; 46import com.android.internal.telephony.IccFileHandler; 47import com.android.internal.telephony.IccPhoneBookInterfaceManager; 48import com.android.internal.telephony.IccSmsInterfaceManager; 49import com.android.internal.telephony.MmiCode; 50import com.android.internal.telephony.Phone; 51import com.android.internal.telephony.PhoneBase; 52import com.android.internal.telephony.PhoneNotifier; 53import com.android.internal.telephony.PhoneProxy; 54import com.android.internal.telephony.PhoneSubInfo; 55import com.android.internal.telephony.RILConstants; 56import com.android.internal.telephony.TelephonyIntents; 57import com.android.internal.telephony.TelephonyProperties; 58 59import java.util.List; 60import java.util.Timer; 61import java.util.TimerTask; 62/** 63 * {@hide} 64 */ 65public class CDMAPhone extends PhoneBase { 66 static final String LOG_TAG = "CDMA"; 67 private static final boolean LOCAL_DEBUG = true; 68 69 // Default Emergency Callback Mode exit timer 70 private static final int DEFAULT_ECM_EXIT_TIMER_VALUE = 300000; 71 static final String VM_COUNT_CDMA = "vm_count_key_cdma"; 72 private static final String VM_NUMBER_CDMA = "vm_number_key_cdma"; 73 private String mVmNumber = null; 74 75 //***** Instance Variables 76 CdmaCallTracker mCT; 77 CdmaSMSDispatcher mSMS; 78 CdmaServiceStateTracker mSST; 79 CdmaDataConnectionTracker mDataConnection; 80 RuimFileHandler mRuimFileHandler; 81 RuimRecords mRuimRecords; 82 RuimCard mRuimCard; 83 MyHandler h; 84 RuimPhoneBookInterfaceManager mRuimPhoneBookInterfaceManager; 85 RuimSmsInterfaceManager mRuimSmsInterfaceManager; 86 PhoneSubInfo mSubInfo; 87 EriManager mEriManager; 88 89 // mNvLoadedRegistrants are informed after the EVENT_NV_READY 90 private RegistrantList mNvLoadedRegistrants = new RegistrantList(); 91 92 // mEriFileLoadedRegistrants are informed after the ERI text has been loaded 93 private RegistrantList mEriFileLoadedRegistrants = new RegistrantList(); 94 95 // mECMExitRespRegistrant is informed after the phone has been exited 96 //the emergency callback mode 97 //keep track of if phone is in emergency callback mode 98 private boolean mIsPhoneInECMState; 99 private Registrant mECMExitRespRegistrant; 100 private String mEsn; 101 private String mMeid; 102 103 // A runnable which is used to automatically exit from ECM after a period of time. 104 private Runnable mExitEcmRunnable = new Runnable() { 105 public void run() { 106 exitEmergencyCallbackMode(); 107 } 108 }; 109 110 Registrant mPostDialHandler; 111 112 113 //***** Constructors 114 public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) { 115 this(context,ci,notifier, false); 116 } 117 118 public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, 119 boolean unitTestMode) { 120 super(notifier, context, unitTestMode); 121 122 h = new MyHandler(); 123 mCM = ci; 124 125 mCM.setPhoneType(RILConstants.CDMA_PHONE); 126 mCT = new CdmaCallTracker(this); 127 mSST = new CdmaServiceStateTracker (this); 128 mSMS = new CdmaSMSDispatcher(this); 129 mIccFileHandler = new RuimFileHandler(this); 130 mRuimRecords = new RuimRecords(this); 131 mDataConnection = new CdmaDataConnectionTracker (this); 132 mRuimCard = new RuimCard(this); 133 mRuimPhoneBookInterfaceManager = new RuimPhoneBookInterfaceManager(this); 134 mRuimSmsInterfaceManager = new RuimSmsInterfaceManager(this); 135 mSubInfo = new PhoneSubInfo(this); 136 mEriManager = new EriManager(this, context, EriManager.ERI_FROM_XML); 137 138 mCM.registerForAvailable(h, EVENT_RADIO_AVAILABLE, null); 139 mRuimRecords.registerForRecordsLoaded(h, EVENT_RUIM_RECORDS_LOADED, null); 140 mCM.registerForOffOrNotAvailable(h, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null); 141 mCM.registerForOn(h, EVENT_RADIO_ON, null); 142 mCM.setOnSuppServiceNotification(h, EVENT_SSN, null); 143 mCM.setOnCallRing(h, EVENT_CALL_RING, null); 144 mSST.registerForNetworkAttach(h, EVENT_REGISTERED_TO_NETWORK, null); 145 mCM.registerForNVReady(h, EVENT_NV_READY, null); 146 mCM.setEmergencyCallbackMode(h, EVENT_EMERGENCY_CALLBACK_MODE_ENTER, null); 147 148 149 //Change the system setting 150 SystemProperties.set(TelephonyProperties.CURRENT_ACTIVE_PHONE, 151 new Integer(RILConstants.CDMA_PHONE).toString()); 152 153 // This is needed to handle phone process crashes 154 String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false"); 155 mIsPhoneInECMState = inEcm.equals("true"); 156 157 // Notify voicemails. 158 notifier.notifyMessageWaitingChanged(this); 159 } 160 161 public void dispose() { 162 synchronized(PhoneProxy.lockForRadioTechnologyChange) { 163 164 //Unregister from all former registered events 165 mRuimRecords.unregisterForRecordsLoaded(h); //EVENT_RUIM_RECORDS_LOADED 166 mCM.unregisterForAvailable(h); //EVENT_RADIO_AVAILABLE 167 mCM.unregisterForOffOrNotAvailable(h); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE 168 mCM.unregisterForOn(h); //EVENT_RADIO_ON 169 mCM.unregisterForNVReady(h); //EVENT_NV_READY 170 mSST.unregisterForNetworkAttach(h); //EVENT_REGISTERED_TO_NETWORK 171 mCM.unSetOnSuppServiceNotification(h); 172 mCM.unSetOnCallRing(h); 173 174 175 //Force all referenced classes to unregister their former registered events 176 mCT.dispose(); 177 mDataConnection.dispose(); 178 mSST.dispose(); 179 mSMS.dispose(); 180 mIccFileHandler.dispose(); // instance of RuimFileHandler 181 mRuimRecords.dispose(); 182 mRuimCard.dispose(); 183 mRuimPhoneBookInterfaceManager.dispose(); 184 mRuimSmsInterfaceManager.dispose(); 185 mSubInfo.dispose(); 186 mEriManager.dispose(); 187 } 188 } 189 190 public void removeReferences() { 191 this.mRuimPhoneBookInterfaceManager = null; 192 this.mRuimSmsInterfaceManager = null; 193 this.mSMS = null; 194 this.mSubInfo = null; 195 this.mRuimRecords = null; 196 this.mIccFileHandler = null; 197 this.mRuimCard = null; 198 this.mDataConnection = null; 199 this.mCT = null; 200 this.mSST = null; 201 this.mEriManager = null; 202 } 203 204 protected void finalize() { 205 if(LOCAL_DEBUG) Log.d(LOG_TAG, "CDMAPhone finalized"); 206 } 207 208 209 //***** Overridden from Phone 210 public ServiceState getServiceState() { 211 return mSST.ss; 212 } 213 214 public Phone.State 215 getState() { 216 return mCT.state; 217 } 218 219 public String 220 getPhoneName() { 221 return "CDMA"; 222 } 223 224 public boolean canTransfer() { 225 Log.e(LOG_TAG, "canTransfer: not possible in CDMA"); 226 return false; 227 } 228 229 public CdmaCall 230 getRingingCall() { 231 return mCT.ringingCall; 232 } 233 234 public void setMute(boolean muted) { 235 mCT.setMute(muted); 236 } 237 238 public boolean getMute() { 239 return mCT.getMute(); 240 } 241 242 public void conference() throws CallStateException { 243 // three way calls in CDMA will be handled by feature codes 244 Log.e(LOG_TAG, "conference: not possible in CDMA"); 245 } 246 247 public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) { 248 this.mCM.setPreferredVoicePrivacy(enable, onComplete); 249 } 250 251 public void getEnhancedVoicePrivacy(Message onComplete) { 252 this.mCM.getPreferredVoicePrivacy(onComplete); 253 } 254 255 public void clearDisconnected() { 256 mCT.clearDisconnected(); 257 } 258 259 public DataActivityState getDataActivityState() { 260 DataActivityState ret = DataActivityState.NONE; 261 262 if (mSST.getCurrentCdmaDataConnectionState() == ServiceState.STATE_IN_SERVICE) { 263 264 switch (mDataConnection.getActivity()) { 265 case DATAIN: 266 ret = DataActivityState.DATAIN; 267 break; 268 269 case DATAOUT: 270 ret = DataActivityState.DATAOUT; 271 break; 272 273 case DATAINANDOUT: 274 ret = DataActivityState.DATAINANDOUT; 275 break; 276 277 case DORMANT: 278 ret = DataActivityState.DORMANT; 279 break; 280 } 281 } 282 return ret; 283 } 284 285 /*package*/ void 286 notifySignalStrength() { 287 mNotifier.notifySignalStrength(this); 288 } 289 290 public Connection 291 dial (String dialString) throws CallStateException { 292 // Need to make sure dialString gets parsed properly 293 String newDialString = PhoneNumberUtils.stripSeparators(dialString); 294 295 if (!mCT.foregroundCall.isIdle()) { 296 FeatureCode fc = FeatureCode.newFromDialString(newDialString, this); 297 if (fc != null) { 298 //mMmiRegistrants.notifyRegistrants(new AsyncResult(null, fc, null)); 299 fc.processCode(); 300 return null; 301 } 302 } 303 return mCT.dial(newDialString); 304 } 305 306 public SignalStrength getSignalStrength() { 307 return mSST.mSignalStrength; 308 } 309 310 public boolean 311 getMessageWaitingIndicator() { 312 return (getVoiceMessageCount() > 0); 313 } 314 315 public List<? extends MmiCode> 316 getPendingMmiCodes() { 317 Log.e(LOG_TAG, "method getPendingMmiCodes is NOT supported in CDMA!"); 318 return null; 319 } 320 321 public void registerForSuppServiceNotification( 322 Handler h, int what, Object obj) { 323 Log.e(LOG_TAG, "method registerForSuppServiceNotification is NOT supported in CDMA!"); 324 } 325 326 public CdmaCall getBackgroundCall() { 327 return mCT.backgroundCall; 328 } 329 330 public String getGateway(String apnType) { 331 return mDataConnection.getGateway(); 332 } 333 334 public boolean handleInCallMmiCommands(String dialString) { 335 Log.e(LOG_TAG, "method handleInCallMmiCommands is NOT supported in CDMA!"); 336 return false; 337 } 338 339 public int enableApnType(String type) { 340 // This request is mainly used to enable MMS APN 341 // In CDMA there is no need to enable/disable a different APN for MMS 342 Log.d(LOG_TAG, "Request to enableApnType("+type+")"); 343 if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) { 344 return Phone.APN_ALREADY_ACTIVE; 345 } else { 346 return Phone.APN_REQUEST_FAILED; 347 } 348 } 349 350 public int disableApnType(String type) { 351 // This request is mainly used to disable MMS APN 352 // In CDMA there is no need to enable/disable a different APN for MMS 353 Log.d(LOG_TAG, "Request to disableApnType("+type+")"); 354 if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) { 355 return Phone.APN_REQUEST_STARTED; 356 } else { 357 return Phone.APN_REQUEST_FAILED; 358 } 359 } 360 361 public String getActiveApn() { 362 Log.d(LOG_TAG, "Request to getActiveApn()"); 363 return null; 364 } 365 366 public void 367 setNetworkSelectionModeAutomatic(Message response) { 368 Log.e(LOG_TAG, "method setNetworkSelectionModeAutomatic is NOT supported in CDMA!"); 369 } 370 371 public void unregisterForSuppServiceNotification(Handler h) { 372 Log.e(LOG_TAG, "method unregisterForSuppServiceNotification is NOT supported in CDMA!"); 373 } 374 375 public void 376 acceptCall() throws CallStateException { 377 mCT.acceptCall(); 378 } 379 380 public void 381 rejectCall() throws CallStateException { 382 mCT.rejectCall(); 383 } 384 385 public void 386 switchHoldingAndActive() throws CallStateException { 387 mCT.switchWaitingOrHoldingAndActive(); 388 } 389 390 public String getLine1Number() { 391 return mSST.getMdnNumber(); 392 } 393 394 public String getCdmaPrlVersion(){ 395 return mSST.getPrlVersion(); 396 } 397 398 public String getCdmaMin() { 399 return mSST.getCdmaMin(); 400 } 401 402 public void getCallWaiting(Message onComplete) { 403 mCM.queryCallWaiting(CommandsInterface.SERVICE_CLASS_VOICE, onComplete); 404 } 405 406 public void 407 setRadioPower(boolean power) { 408 mSST.setRadioPower(power); 409 } 410 411 public String getEsn() { 412 return mEsn; 413 } 414 415 public String getMeid() { 416 return mMeid; 417 } 418 419 //returns MEID in CDMA 420 public String getDeviceId() { 421 return getMeid(); 422 } 423 424 public String getDeviceSvn() { 425 Log.d(LOG_TAG, "getDeviceSvn(): return 0"); 426 return "0"; 427 } 428 429 public String getSubscriberId() { 430 // Subscriber ID is the combination of MCC+MNC+MIN as CDMA IMSI 431 // TODO(Moto): Replace with call to mRuimRecords.getIMSI_M() when implemented. 432 if ((getServiceState().getOperatorNumeric() != null) && (getCdmaMin() != null)) { 433 return (getServiceState().getOperatorNumeric() + getCdmaMin()); 434 } else { 435 return null; 436 } 437 } 438 439 public boolean canConference() { 440 Log.e(LOG_TAG, "canConference: not possible in CDMA"); 441 return false; 442 } 443 444 public String getInterfaceName(String apnType) { 445 return mDataConnection.getInterfaceName(); 446 } 447 448 public CellLocation getCellLocation() { 449 return mSST.cellLoc; 450 } 451 452 public boolean disableDataConnectivity() { 453 return mDataConnection.setDataEnabled(false); 454 } 455 456 public CdmaCall getForegroundCall() { 457 return mCT.foregroundCall; 458 } 459 460 public void 461 selectNetworkManually(com.android.internal.telephony.gsm.NetworkInfo network, 462 Message response) { 463 Log.e(LOG_TAG, "selectNetworkManually: not possible in CDMA"); 464 } 465 466 public void setOnPostDialCharacter(Handler h, int what, Object obj) { 467 mPostDialHandler = new Registrant(h, what, obj); 468 } 469 470 public boolean handlePinMmi(String dialString) { 471 Log.e(LOG_TAG, "method handlePinMmi is NOT supported in CDMA!"); 472 return false; 473 } 474 475 public boolean isDataConnectivityPossible() { 476 boolean noData = mDataConnection.getDataEnabled() && 477 getDataConnectionState() == DataState.DISCONNECTED; 478 return !noData && getIccCard().getState() == IccCard.State.READY && 479 getServiceState().getState() == ServiceState.STATE_IN_SERVICE && 480 (mDataConnection.getDataOnRoamingEnabled() || !getServiceState().getRoaming()); 481 } 482 483 public void setLine1Number(String alphaTag, String number, Message onComplete) { 484 Log.e(LOG_TAG, "setLine1Number: not possible in CDMA"); 485 } 486 487 public String[] getDnsServers(String apnType) { 488 return mDataConnection.getDnsServers(); 489 } 490 491 public IccCard getIccCard() { 492 return mRuimCard; 493 } 494 495 public String getIccSerialNumber() { 496 return mRuimRecords.iccid; 497 } 498 499 public void setCallWaiting(boolean enable, Message onComplete) { 500 Log.e(LOG_TAG, "method setCallWaiting is NOT supported in CDMA!"); 501 } 502 503 public void updateServiceLocation(Message response) { 504 mSST.getLacAndCid(response); 505 } 506 507 public void setDataRoamingEnabled(boolean enable) { 508 mDataConnection.setDataOnRoamingEnabled(enable); 509 } 510 511 public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) { 512 mCM.registerForCdmaOtaProvision(h, what, obj); 513 } 514 515 public void unregisterForCdmaOtaStatusChange(Handler h) { 516 mCM.unregisterForCdmaOtaProvision(h); 517 } 518 519 public void setOnEcbModeExitResponse(Handler h, int what, Object obj) { 520 mECMExitRespRegistrant = new Registrant (h, what, obj); 521 } 522 523 public void unsetOnEcbModeExitResponse(Handler h) { 524 mECMExitRespRegistrant.clear(); 525 } 526 527 public void registerForCallWaiting(Handler h, int what, Object obj) { 528 mCT.registerForCallWaiting(h, what, obj); 529 } 530 531 public void unregisterForCallWaiting(Handler h) { 532 mCT.unregisterForCallWaiting(h); 533 } 534 535 public String getIpAddress(String apnType) { 536 return mDataConnection.getIpAddress(); 537 } 538 539 public void 540 getNeighboringCids(Message response) { 541 /* 542 * This is currently not implemented. At least as of June 543 * 2009, there is no neighbor cell information available for 544 * CDMA because some party is resisting making this 545 * information readily available. Consequently, calling this 546 * function can have no useful effect. This situation may 547 * (and hopefully will) change in the future. 548 */ 549 if (response != null) { 550 CommandException ce = new CommandException( 551 CommandException.Error.REQUEST_NOT_SUPPORTED); 552 AsyncResult.forMessage(response).exception = ce; 553 response.sendToTarget(); 554 } 555 } 556 557 public DataState getDataConnectionState() { 558 DataState ret = DataState.DISCONNECTED; 559 560 if ((SystemProperties.get("adb.connected", "").length() > 0) 561 && (SystemProperties.get("android.net.use-adb-networking", "") 562 .length() > 0)) { 563 // We're connected to an ADB host and we have USB networking 564 // turned on. No matter what the radio state is, 565 // we report data connected 566 567 ret = DataState.CONNECTED; 568 } else if (mSST == null) { 569 // Radio Technology Change is ongoning, dispose() and removeReferences() have 570 // already been called 571 572 ret = DataState.DISCONNECTED; 573 } else if (mSST.getCurrentCdmaDataConnectionState() != ServiceState.STATE_IN_SERVICE) { 574 // If we're out of service, open TCP sockets may still work 575 // but no data will flow 576 ret = DataState.DISCONNECTED; 577 } else { 578 switch (mDataConnection.getState()) { 579 case FAILED: 580 case IDLE: 581 ret = DataState.DISCONNECTED; 582 break; 583 584 case CONNECTED: 585 case DISCONNECTING: 586 if ( mCT.state != Phone.State.IDLE 587 && !mSST.isConcurrentVoiceAndData()) { 588 ret = DataState.SUSPENDED; 589 } else { 590 ret = DataState.CONNECTED; 591 } 592 break; 593 594 case INITING: 595 case CONNECTING: 596 case SCANNING: 597 ret = DataState.CONNECTING; 598 break; 599 } 600 } 601 602 return ret; 603 } 604 605 public void sendUssdResponse(String ussdMessge) { 606 Log.e(LOG_TAG, "sendUssdResponse: not possible in CDMA"); 607 } 608 609 public void sendDtmf(char c) { 610 if (!PhoneNumberUtils.is12Key(c)) { 611 Log.e(LOG_TAG, 612 "sendDtmf called with invalid character '" + c + "'"); 613 } else { 614 if (mCT.state == Phone.State.OFFHOOK) { 615 mCM.sendDtmf(c, null); 616 } 617 } 618 } 619 620 public void startDtmf(char c) { 621 if (!PhoneNumberUtils.is12Key(c)) { 622 Log.e(LOG_TAG, 623 "startDtmf called with invalid character '" + c + "'"); 624 } else { 625 mCM.startDtmf(c, null); 626 } 627 } 628 629 public void stopDtmf() { 630 mCM.stopDtmf(null); 631 } 632 633 public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) { 634 boolean check = true; 635 for (int itr = 0;itr < dtmfString.length(); itr++) { 636 if (!PhoneNumberUtils.is12Key(dtmfString.charAt(itr))) { 637 Log.e(LOG_TAG, 638 "sendDtmf called with invalid character '" + dtmfString.charAt(itr)+ "'"); 639 check = false; 640 break; 641 } 642 } 643 if ((mCT.state == Phone.State.OFFHOOK)&&(check)) { 644 mCM.sendBurstDtmf(dtmfString, on, off, onComplete); 645 } 646 } 647 648 public void getAvailableNetworks(Message response) { 649 Log.e(LOG_TAG, "getAvailableNetworks: not possible in CDMA"); 650 } 651 652 public String[] getActiveApnTypes() { 653 String[] result; 654 Log.d(LOG_TAG, "Request to getActiveApn()"); 655 result = new String[1]; 656 result[0] = Phone.APN_TYPE_DEFAULT; 657 return result; 658 } 659 660 public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete) { 661 Log.e(LOG_TAG, "setOutgoingCallerIdDisplay: not possible in CDMA"); 662 } 663 664 public void enableLocationUpdates() { 665 mSST.enableLocationUpdates(); 666 } 667 668 /** 669 * @deprecated 670 */ 671 public void getPdpContextList(Message response) { 672 getDataCallList(response); 673 } 674 675 public void getDataCallList(Message response) { 676 mCM.getDataCallList(response); 677 } 678 679 public boolean getDataRoamingEnabled() { 680 return mDataConnection.getDataOnRoamingEnabled(); 681 } 682 683 public List<DataConnection> getCurrentDataConnectionList () { 684 return mDataConnection.getAllDataConnections(); 685 } 686 687 public void setVoiceMailNumber(String alphaTag, 688 String voiceMailNumber, 689 Message onComplete) { 690 Message resp; 691 mVmNumber = voiceMailNumber; 692 resp = h.obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete); 693 mRuimRecords.setVoiceMailNumber(alphaTag, mVmNumber, resp); 694 } 695 696 public String getVoiceMailNumber() { 697 String number = null; 698 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 699 // TODO(Moto): The default value of voicemail number should be read from a system property 700 number = sp.getString(VM_NUMBER_CDMA, "*86"); 701 return number; 702 } 703 704 /* Returns Number of Voicemails 705 * @hide 706 */ 707 public int getVoiceMessageCount() { 708 int voicemailCount = mRuimRecords.getVoiceMessageCount(); 709 // If mRuimRecords.getVoiceMessageCount returns zero, then there is possibility 710 // that phone was power cycled and would have lost the voicemail count. 711 // So get the count from preferences. 712 if (voicemailCount == 0) { 713 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 714 voicemailCount = sp.getInt(VM_COUNT_CDMA, 0); 715 } 716 return voicemailCount; 717 } 718 719 public String getVoiceMailAlphaTag() { 720 // TODO: Where can we get this value has to be clarified with QC. 721 String ret = "";//TODO: Remove = "", if we know where to get this value. 722 723 //ret = mSIMRecords.getVoiceMailAlphaTag(); 724 725 if (ret == null || ret.length() == 0) { 726 return mContext.getText( 727 com.android.internal.R.string.defaultVoiceMailAlphaTag).toString(); 728 } 729 730 return ret; 731 } 732 733 public boolean enableDataConnectivity() { 734 735 // block data activities when phone is in emergency callback mode 736 if (mIsPhoneInECMState) { 737 Intent intent = new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS); 738 ActivityManagerNative.broadcastStickyIntent(intent, null); 739 return false; 740 } else { 741 return mDataConnection.setDataEnabled(true); 742 } 743 } 744 745 public void disableLocationUpdates() { 746 mSST.disableLocationUpdates(); 747 } 748 749 public boolean getIccRecordsLoaded() { 750 return mRuimRecords.getRecordsLoaded(); 751 } 752 753 public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) { 754 Log.e(LOG_TAG, "getCallForwardingOption: not possible in CDMA"); 755 } 756 757 public void setCallForwardingOption(int commandInterfaceCFAction, 758 int commandInterfaceCFReason, 759 String dialingNumber, 760 int timerSeconds, 761 Message onComplete) { 762 Log.e(LOG_TAG, "setCallForwardingOption: not possible in CDMA"); 763 } 764 765 public void 766 getOutgoingCallerIdDisplay(Message onComplete) { 767 Log.e(LOG_TAG, "getOutgoingCallerIdDisplay: not possible in CDMA"); 768 } 769 770 public boolean 771 getCallForwardingIndicator() { 772 Log.e(LOG_TAG, "getCallForwardingIndicator: not possible in CDMA"); 773 return false; 774 } 775 776 public void explicitCallTransfer() { 777 Log.e(LOG_TAG, "explicitCallTransfer: not possible in CDMA"); 778 } 779 780 public String getLine1AlphaTag() { 781 Log.e(LOG_TAG, "getLine1AlphaTag: not possible in CDMA"); 782 return null; 783 } 784 785 /** 786 * Notify any interested party of a Phone state change. 787 */ 788 /*package*/ void notifyPhoneStateChanged() { 789 mNotifier.notifyPhoneState(this); 790 } 791 792 /** 793 * Notifies registrants (ie, activities in the Phone app) about 794 * changes to call state (including Phone and Connection changes). 795 */ 796 /*package*/ void notifyCallStateChanged() { 797 /* we'd love it if this was package-scoped*/ 798 super.notifyCallStateChangedP(); 799 } 800 801 void notifyServiceStateChanged(ServiceState ss) { 802 super.notifyServiceStateChangedP(ss); 803 } 804 805 void notifyLocationChanged() { 806 mNotifier.notifyCellLocation(this); 807 } 808 809 /*package*/ void notifyNewRingingConnection(Connection c) { 810 /* we'd love it if this was package-scoped*/ 811 super.notifyNewRingingConnectionP(c); 812 } 813 814 /** 815 * Notifiy registrants of a RING event. 816 */ 817 void notifyIncomingRing() { 818 AsyncResult ar = new AsyncResult(null, this, null); 819 mIncomingRingRegistrants.notifyRegistrants(ar); 820 } 821 822 /*package*/ void notifyDisconnect(Connection cn) { 823 mDisconnectRegistrants.notifyResult(cn); 824 } 825 826 void notifyUnknownConnection() { 827 mUnknownConnectionRegistrants.notifyResult(this); 828 } 829 830 void sendEmergencyCallbackModeChange(){ 831 //Send an Intent 832 Intent intent = new Intent(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); 833 intent.putExtra(PHONE_IN_ECM_STATE, mIsPhoneInECMState); 834 ActivityManagerNative.broadcastStickyIntent(intent,null); 835 } 836 837 /*package*/ void 838 updateMessageWaitingIndicator(boolean mwi) { 839 // this also calls notifyMessageWaitingIndicator() 840 mRuimRecords.setVoiceMessageWaiting(1, mwi ? -1 : 0); 841 } 842 843 /* This function is overloaded to send number of voicemails instead of sending true/false */ 844 /*package*/ void 845 updateMessageWaitingIndicator(int mwi) { 846 mRuimRecords.setVoiceMessageWaiting(1, mwi); 847 } 848 849 /** 850 * Removes the given FC from the pending list and notifies 851 * registrants that it is complete. 852 * @param fc FC that is done 853 */ 854 /*package*/ void onFeatureCodeDone(FeatureCode fc) { 855 /* Only notify complete if it's on the pending list. 856 * Otherwise, it's already been handled (eg, previously canceled). 857 * The exception is cancellation of an incoming USSD-REQUEST, which is 858 * not on the list. 859 */ 860 mMmiCompleteRegistrants.notifyRegistrants(new AsyncResult(null, fc, null)); 861 } 862 863 864 @Override 865 public void exitEmergencyCallbackMode() { 866 // Send a message which will invoke handleExitEmergencyCallbackMode 867 mCM.exitEmergencyCallbackMode(h.obtainMessage(EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE)); 868 } 869 870 private void handleEnterEmergencyCallbackMode(Message msg) { 871 Log.d(LOG_TAG, "Event EVENT_EMERGENCY_CALLBACK_MODE Received"); 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 h.postDelayed(mExitEcmRunnable, delayInMillis); 884 } 885 } 886 887 private void handleExitEmergencyCallbackMode(Message msg) { 888 Log.d(LOG_TAG, "Event EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE Received"); 889 AsyncResult ar = (AsyncResult)msg.obj; 890 891 // Remove pending exit ECM runnable, if any 892 h.removeCallbacks(mExitEcmRunnable); 893 894 if (mECMExitRespRegistrant != null) { 895 mECMExitRespRegistrant.notifyRegistrant(ar); 896 } 897 // if exiting ecm success 898 if (ar.exception == null) { 899 if (mIsPhoneInECMState) { 900 mIsPhoneInECMState = false; 901 setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE, "false"); 902 } 903 // send an Intent 904 sendEmergencyCallbackModeChange(); 905 } 906 } 907 908 //***** Inner Classes 909 class MyHandler extends Handler { 910 MyHandler() { 911 } 912 913 MyHandler(Looper l) { 914 super(l); 915 } 916 917 @Override 918 public void handleMessage(Message msg) { 919 AsyncResult ar; 920 Message onComplete; 921 922 switch(msg.what) { 923 case EVENT_RADIO_AVAILABLE: { 924 mCM.getBasebandVersion(obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE)); 925 926 mCM.getDeviceIdentity(obtainMessage(EVENT_GET_DEVICE_IDENTITY_DONE)); 927 } 928 break; 929 930 case EVENT_GET_BASEBAND_VERSION_DONE:{ 931 ar = (AsyncResult)msg.obj; 932 933 if (ar.exception != null) { 934 break; 935 } 936 937 if (LOCAL_DEBUG) Log.d(LOG_TAG, "Baseband version: " + ar.result); 938 setSystemProperty(TelephonyProperties.PROPERTY_BASEBAND_VERSION, (String)ar.result); 939 } 940 break; 941 942 case EVENT_GET_DEVICE_IDENTITY_DONE:{ 943 ar = (AsyncResult)msg.obj; 944 945 if (ar.exception != null) { 946 break; 947 } 948 String[] respId = (String[])ar.result; 949 mEsn = respId[2]; 950 mMeid = respId[3]; 951 } 952 break; 953 954 case EVENT_EMERGENCY_CALLBACK_MODE_ENTER:{ 955 handleEnterEmergencyCallbackMode(msg); 956 } 957 break; 958 959 case EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE:{ 960 handleExitEmergencyCallbackMode(msg); 961 } 962 break; 963 964 case EVENT_RUIM_RECORDS_LOADED:{ 965 Log.d(LOG_TAG, "Event EVENT_RUIM_RECORDS_LOADED Received"); 966 } 967 break; 968 969 case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:{ 970 Log.d(LOG_TAG, "Event EVENT_RADIO_OFF_OR_NOT_AVAILABLE Received"); 971 } 972 break; 973 974 case EVENT_RADIO_ON:{ 975 Log.d(LOG_TAG, "Event EVENT_RADIO_ON Received"); 976 } 977 break; 978 979 case EVENT_SSN:{ 980 Log.d(LOG_TAG, "Event EVENT_SSN Received"); 981 } 982 break; 983 984 case EVENT_CALL_RING:{ 985 Log.d(LOG_TAG, "Event EVENT_CALL_RING Received"); 986 } 987 break; 988 989 case EVENT_REGISTERED_TO_NETWORK:{ 990 Log.d(LOG_TAG, "Event EVENT_REGISTERED_TO_NETWORK Received"); 991 } 992 break; 993 994 case EVENT_NV_READY:{ 995 Log.d(LOG_TAG, "Event EVENT_NV_READY Received"); 996 //Inform the Service State Tracker 997 mEriManager.loadEriFile(); 998 mNvLoadedRegistrants.notifyRegistrants(); 999 if(mEriManager.isEriFileLoaded()) { 1000 // when the ERI file is loaded 1001 Log.d(LOG_TAG, "ERI read, notify registrants"); 1002 mEriFileLoadedRegistrants.notifyRegistrants(); 1003 } 1004 setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE,"false"); 1005 } 1006 break; 1007 1008 case EVENT_SET_VM_NUMBER_DONE:{ 1009 ar = (AsyncResult)msg.obj; 1010 if (IccException.class.isInstance(ar.exception)) { 1011 storeVoiceMailNumber(mVmNumber); 1012 ar.exception = null; 1013 } 1014 onComplete = (Message) ar.userObj; 1015 if (onComplete != null) { 1016 AsyncResult.forMessage(onComplete, ar.result, ar.exception); 1017 onComplete.sendToTarget(); 1018 } 1019 } 1020 1021 default:{ 1022 throw new RuntimeException("unexpected event not handled"); 1023 } 1024 } 1025 } 1026 } 1027 1028 /** 1029 * Retrieves the PhoneSubInfo of the CDMAPhone 1030 */ 1031 public PhoneSubInfo getPhoneSubInfo() { 1032 return mSubInfo; 1033 } 1034 1035 /** 1036 * Retrieves the IccSmsInterfaceManager of the CDMAPhone 1037 */ 1038 public IccSmsInterfaceManager getIccSmsInterfaceManager() { 1039 return mRuimSmsInterfaceManager; 1040 } 1041 1042 /** 1043 * Retrieves the IccPhoneBookInterfaceManager of the CDMAPhone 1044 */ 1045 public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager() { 1046 return mRuimPhoneBookInterfaceManager; 1047 } 1048 1049 public void registerForNvLoaded(Handler h, int what, Object obj) { 1050 Registrant r = new Registrant (h, what, obj); 1051 mNvLoadedRegistrants.add(r); 1052 } 1053 1054 public void unregisterForNvLoaded(Handler h) { 1055 mNvLoadedRegistrants.remove(h); 1056 } 1057 1058 public void registerForEriFileLoaded(Handler h, int what, Object obj) { 1059 Registrant r = new Registrant (h, what, obj); 1060 mEriFileLoadedRegistrants.add(r); 1061 } 1062 1063 public void unregisterForEriFileLoaded(Handler h) { 1064 mEriFileLoadedRegistrants.remove(h); 1065 } 1066 1067 // override for allowing access from other classes of this package 1068 /** 1069 * {@inheritDoc} 1070 */ 1071 public final void setSystemProperty(String property, String value) { 1072 super.setSystemProperty(property, value); 1073 } 1074 1075 /** 1076 * {@inheritDoc} 1077 */ 1078 public Handler getHandler() { 1079 return h; 1080 } 1081 1082 /** 1083 * {@inheritDoc} 1084 */ 1085 public IccFileHandler getIccFileHandler() { 1086 return this.mIccFileHandler; 1087 } 1088 1089 /** 1090 * Set the TTY mode of the CDMAPhone 1091 */ 1092 public void setTTYMode(int ttyMode, Message onComplete) { 1093 this.mCM.setTTYMode(ttyMode, onComplete); 1094 } 1095 1096 /** 1097 * Queries the TTY mode of the CDMAPhone 1098 */ 1099 public void queryTTYMode(Message onComplete) { 1100 this.mCM.queryTTYMode(onComplete); 1101 } 1102 1103 /** 1104 * Activate or deactivate cell broadcast SMS. 1105 * 1106 * @param activate 0 = activate, 1 = deactivate 1107 * @param response Callback message is empty on completion 1108 */ 1109 public void activateCellBroadcastSms(int activate, Message response) { 1110 mSMS.activateCellBroadcastSms(activate, response); 1111 } 1112 1113 /** 1114 * Query the current configuration of cdma cell broadcast SMS. 1115 * 1116 * @param response Callback message is empty on completion 1117 */ 1118 public void getCellBroadcastSmsConfig(Message response) { 1119 mSMS.getCellBroadcastSmsConfig(response); 1120 } 1121 1122 /** 1123 * Configure cdma cell broadcast SMS. 1124 * 1125 * @param response Callback message is empty on completion 1126 */ 1127 public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response) { 1128 mSMS.setCellBroadcastConfig(configValuesArray, response); 1129 } 1130 1131 public static final String IS683A_FEATURE_CODE = "*228" ; 1132 public static final int IS683A_FEATURE_CODE_NUM_DIGITS = 4 ; 1133 public static final int IS683A_SYS_SEL_CODE_NUM_DIGITS = 2 ; 1134 public static final int IS683A_SYS_SEL_CODE_OFFSET = 4; 1135 1136 private static final int IS683_CONST_800MHZ_A_BAND = 0; 1137 private static final int IS683_CONST_800MHZ_B_BAND = 1; 1138 private static final int IS683_CONST_1900MHZ_A_BLOCK = 2; 1139 private static final int IS683_CONST_1900MHZ_B_BLOCK = 3; 1140 private static final int IS683_CONST_1900MHZ_C_BLOCK = 4; 1141 private static final int IS683_CONST_1900MHZ_D_BLOCK = 5; 1142 private static final int IS683_CONST_1900MHZ_E_BLOCK = 6; 1143 private static final int IS683_CONST_1900MHZ_F_BLOCK = 7; 1144 1145 private boolean isIs683OtaSpDialStr(String dialStr) { 1146 int sysSelCodeInt; 1147 boolean isOtaspDialString = false; 1148 int dialStrLen = dialStr.length(); 1149 1150 if (dialStrLen == IS683A_FEATURE_CODE_NUM_DIGITS) { 1151 if (dialStr.equals(IS683A_FEATURE_CODE)) { 1152 isOtaspDialString = true; 1153 } 1154 } else if ((dialStr.regionMatches(0, IS683A_FEATURE_CODE, 0, 1155 IS683A_FEATURE_CODE_NUM_DIGITS) == true) 1156 && (dialStrLen >= 1157 (IS683A_FEATURE_CODE_NUM_DIGITS + IS683A_SYS_SEL_CODE_NUM_DIGITS))) { 1158 StringBuilder sb = new StringBuilder(dialStr); 1159 // Separate the System Selection Code into its own string 1160 char[] sysSel = new char[2]; 1161 sb.delete(0, IS683A_SYS_SEL_CODE_OFFSET); 1162 sb.getChars(0, IS683A_SYS_SEL_CODE_NUM_DIGITS, sysSel, 0); 1163 1164 if ((PhoneNumberUtils.isISODigit(sysSel[0])) 1165 && (PhoneNumberUtils.isISODigit(sysSel[1]))) { 1166 String sysSelCode = new String(sysSel); 1167 sysSelCodeInt = Integer.parseInt((String)sysSelCode); 1168 switch (sysSelCodeInt) { 1169 case IS683_CONST_800MHZ_A_BAND: 1170 case IS683_CONST_800MHZ_B_BAND: 1171 case IS683_CONST_1900MHZ_A_BLOCK: 1172 case IS683_CONST_1900MHZ_B_BLOCK: 1173 case IS683_CONST_1900MHZ_C_BLOCK: 1174 case IS683_CONST_1900MHZ_D_BLOCK: 1175 case IS683_CONST_1900MHZ_E_BLOCK: 1176 case IS683_CONST_1900MHZ_F_BLOCK: 1177 isOtaspDialString = true; 1178 break; 1179 1180 default: 1181 break; 1182 } 1183 } 1184 } 1185 return isOtaspDialString; 1186 } 1187 1188 /** 1189 * isOTASPNumber: checks a given number against the IS-683A OTASP dial string and carrier 1190 * OTASP dial string. 1191 * 1192 * @param dialStr the number to look up. 1193 * @return true if the number is in IS-683A OTASP dial string or carrier OTASP dial string 1194 */ 1195 @Override 1196 public boolean isOtaSpNumber(String dialStr){ 1197 boolean isOtaSpNum = false; 1198 if(dialStr != null){ 1199 isOtaSpNum=isIs683OtaSpDialStr(dialStr); 1200 if(isOtaSpNum == false){ 1201 //TO DO:Add carrier specific OTASP number detection here. 1202 } 1203 } 1204 return isOtaSpNum; 1205 } 1206 1207 @Override 1208 public int getCdmaEriIconIndex() { 1209 int roamInd = getServiceState().getCdmaRoamingIndicator(); 1210 int defRoamInd = getServiceState().getCdmaDefaultRoamingIndicator(); 1211 return mEriManager.getCdmaEriIconIndex(roamInd, defRoamInd); 1212 } 1213 1214 /** 1215 * Returns the CDMA ERI icon mode, 1216 * 0 - ON 1217 * 1 - FLASHING 1218 */ 1219 @Override 1220 public int getCdmaEriIconMode() { 1221 int roamInd = getServiceState().getCdmaRoamingIndicator(); 1222 int defRoamInd = getServiceState().getCdmaDefaultRoamingIndicator(); 1223 return mEriManager.getCdmaEriIconMode(roamInd, defRoamInd); 1224 } 1225 1226 /** 1227 * Returns the CDMA ERI text, 1228 */ 1229 @Override 1230 public String getCdmaEriText() { 1231 int roamInd = getServiceState().getCdmaRoamingIndicator(); 1232 int defRoamInd = getServiceState().getCdmaDefaultRoamingIndicator(); 1233 return mEriManager.getCdmaEriText(roamInd, defRoamInd); 1234 } 1235 1236 /** 1237 * Store the voicemail number in preferences 1238 */ 1239 private void storeVoiceMailNumber(String number) { 1240 // Update the preference value of voicemail number 1241 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 1242 SharedPreferences.Editor editor = sp.edit(); 1243 editor.putString(VM_NUMBER_CDMA, number); 1244 editor.commit(); 1245 } 1246 1247} 1248