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