GSMPhone.java revision 0825495a331bb44df395a0cdb79fab85e68db5d5
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.gsm; 18 19import android.content.ContentValues; 20import android.content.Context; 21import android.content.SharedPreferences; 22import android.database.SQLException; 23import android.net.Uri; 24import android.os.AsyncResult; 25import android.os.Handler; 26import android.os.Message; 27import android.os.Registrant; 28import android.os.RegistrantList; 29import android.os.SystemProperties; 30import android.preference.PreferenceManager; 31import android.provider.Telephony; 32import android.telephony.CellLocation; 33import android.telephony.PhoneNumberUtils; 34import android.telephony.ServiceState; 35import android.telephony.SignalStrength; 36import com.android.internal.telephony.CallTracker; 37import android.text.TextUtils; 38import android.util.Log; 39 40import static com.android.internal.telephony.CommandsInterface.CF_ACTION_DISABLE; 41import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ENABLE; 42import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ERASURE; 43import static com.android.internal.telephony.CommandsInterface.CF_ACTION_REGISTRATION; 44import static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL; 45import static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL_CONDITIONAL; 46import static com.android.internal.telephony.CommandsInterface.CF_REASON_NO_REPLY; 47import static com.android.internal.telephony.CommandsInterface.CF_REASON_NOT_REACHABLE; 48import static com.android.internal.telephony.CommandsInterface.CF_REASON_BUSY; 49import static com.android.internal.telephony.CommandsInterface.CF_REASON_UNCONDITIONAL; 50import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_VOICE; 51import static com.android.internal.telephony.TelephonyProperties.PROPERTY_BASEBAND_VERSION; 52 53import com.android.internal.telephony.cat.CatService; 54import com.android.internal.telephony.Call; 55import com.android.internal.telephony.CallForwardInfo; 56import com.android.internal.telephony.CallStateException; 57import com.android.internal.telephony.CommandsInterface; 58import com.android.internal.telephony.Connection; 59import com.android.internal.telephony.IccCard; 60import com.android.internal.telephony.IccFileHandler; 61import com.android.internal.telephony.IccPhoneBookInterfaceManager; 62import com.android.internal.telephony.IccSmsInterfaceManager; 63import com.android.internal.telephony.MmiCode; 64import com.android.internal.telephony.OperatorInfo; 65import com.android.internal.telephony.Phone; 66import com.android.internal.telephony.PhoneBase; 67import com.android.internal.telephony.PhoneConstants; 68import com.android.internal.telephony.PhoneNotifier; 69import com.android.internal.telephony.PhoneProxy; 70import com.android.internal.telephony.PhoneSubInfo; 71import com.android.internal.telephony.TelephonyProperties; 72import com.android.internal.telephony.UUSInfo; 73import com.android.internal.telephony.test.SimulatedRadioControl; 74import com.android.internal.telephony.uicc.UiccController; 75import com.android.internal.telephony.IccVmNotSupportedException; 76import com.android.internal.telephony.ServiceStateTracker; 77 78import java.io.FileDescriptor; 79import java.io.IOException; 80import java.io.PrintWriter; 81import java.net.InetSocketAddress; 82import java.net.ServerSocket; 83import java.net.Socket; 84import java.util.ArrayList; 85import java.util.List; 86 87/** 88 * {@hide} 89 */ 90public class GSMPhone extends PhoneBase { 91 // NOTE that LOG_TAG here is "GSM", which means that log messages 92 // from this file will go into the radio log rather than the main 93 // log. (Use "adb logcat -b radio" to see them.) 94 static final String LOG_TAG = "GSM"; 95 private static final boolean LOCAL_DEBUG = true; 96 private static final boolean VDBG = false; /* STOP SHIP if true */ 97 98 // Key used to read/write current ciphering state 99 public static final String CIPHERING_KEY = "ciphering_key"; 100 // Key used to read/write voice mail number 101 public static final String VM_NUMBER = "vm_number_key"; 102 // Key used to read/write the SIM IMSI used for storing the voice mail 103 public static final String VM_SIM_IMSI = "vm_sim_imsi_key"; 104 105 // Instance Variables 106 GsmCallTracker mCT; 107 GsmServiceStateTracker mSST; 108 ArrayList <GsmMmiCode> mPendingMMIs = new ArrayList<GsmMmiCode>(); 109 SimPhoneBookInterfaceManager mSimPhoneBookIntManager; 110 SimSmsInterfaceManager mSimSmsIntManager; 111 PhoneSubInfo mSubInfo; 112 113 114 Registrant mPostDialHandler; 115 116 /** List of Registrants to receive Supplementary Service Notifications. */ 117 RegistrantList mSsnRegistrants = new RegistrantList(); 118 119 Thread debugPortThread; 120 ServerSocket debugSocket; 121 122 private String mImei; 123 private String mImeiSv; 124 private String mVmNumber; 125 126 127 // Constructors 128 129 public 130 GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier) { 131 this(context,ci,notifier, false); 132 } 133 134 public 135 GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode) { 136 super(notifier, context, ci, unitTestMode); 137 138 if (ci instanceof SimulatedRadioControl) { 139 mSimulatedRadioControl = (SimulatedRadioControl) ci; 140 } 141 142 mCM.setPhoneType(PhoneConstants.PHONE_TYPE_GSM); 143 mIccCard.set(UiccController.getInstance(this).getIccCard()); 144 mIccRecords = mIccCard.get().getIccRecords(); 145 mCT = new GsmCallTracker(this); 146 mSST = new GsmServiceStateTracker (this); 147 mSMS = new GsmSMSDispatcher(this, mSmsStorageMonitor, mSmsUsageMonitor); 148 mDataConnectionTracker = new GsmDataConnectionTracker (this); 149 if (!unitTestMode) { 150 mSimPhoneBookIntManager = new SimPhoneBookInterfaceManager(this); 151 mSimSmsIntManager = new SimSmsInterfaceManager(this, mSMS); 152 mSubInfo = new PhoneSubInfo(this); 153 } 154 155 mCM.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null); 156 registerForSimRecordEvents(); 157 mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null); 158 mCM.registerForOn(this, EVENT_RADIO_ON, null); 159 mCM.setOnUSSD(this, EVENT_USSD, null); 160 mCM.setOnSuppServiceNotification(this, EVENT_SSN, null); 161 mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null); 162 163 if (false) { 164 try { 165 //debugSocket = new LocalServerSocket("com.android.internal.telephony.debug"); 166 debugSocket = new ServerSocket(); 167 debugSocket.setReuseAddress(true); 168 debugSocket.bind (new InetSocketAddress("127.0.0.1", 6666)); 169 170 debugPortThread 171 = new Thread( 172 new Runnable() { 173 public void run() { 174 for(;;) { 175 try { 176 Socket sock; 177 sock = debugSocket.accept(); 178 Log.i(LOG_TAG, "New connection; resetting radio"); 179 mCM.resetRadio(null); 180 sock.close(); 181 } catch (IOException ex) { 182 Log.w(LOG_TAG, 183 "Exception accepting socket", ex); 184 } 185 } 186 } 187 }, 188 "GSMPhone debug"); 189 190 debugPortThread.start(); 191 192 } catch (IOException ex) { 193 Log.w(LOG_TAG, "Failure to open com.android.internal.telephony.debug socket", ex); 194 } 195 } 196 197 //Change the system property 198 SystemProperties.set(TelephonyProperties.CURRENT_ACTIVE_PHONE, 199 new Integer(PhoneConstants.PHONE_TYPE_GSM).toString()); 200 } 201 202 @Override 203 public void dispose() { 204 synchronized(PhoneProxy.lockForRadioTechnologyChange) { 205 super.dispose(); 206 207 //Unregister from all former registered events 208 mCM.unregisterForAvailable(this); //EVENT_RADIO_AVAILABLE 209 unregisterForSimRecordEvents(); 210 mCM.unregisterForOffOrNotAvailable(this); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE 211 mCM.unregisterForOn(this); //EVENT_RADIO_ON 212 mSST.unregisterForNetworkAttached(this); //EVENT_REGISTERED_TO_NETWORK 213 mCM.unSetOnUSSD(this); 214 mCM.unSetOnSuppServiceNotification(this); 215 216 mPendingMMIs.clear(); 217 218 //Force all referenced classes to unregister their former registered events 219 mCT.dispose(); 220 mDataConnectionTracker.dispose(); 221 mSST.dispose(); 222 mSimPhoneBookIntManager.dispose(); 223 mSimSmsIntManager.dispose(); 224 mSubInfo.dispose(); 225 } 226 } 227 228 @Override 229 public void removeReferences() { 230 Log.d(LOG_TAG, "removeReferences"); 231 mSimulatedRadioControl = null; 232 mSimPhoneBookIntManager = null; 233 mSimSmsIntManager = null; 234 mSubInfo = null; 235 mCT = null; 236 mSST = null; 237 super.removeReferences(); 238 } 239 240 protected void finalize() { 241 if(LOCAL_DEBUG) Log.d(LOG_TAG, "GSMPhone finalized"); 242 } 243 244 245 public ServiceState 246 getServiceState() { 247 return mSST.ss; 248 } 249 250 public CellLocation getCellLocation() { 251 return mSST.cellLoc; 252 } 253 254 public PhoneConstants.State getState() { 255 return mCT.state; 256 } 257 258 public String getPhoneName() { 259 return "GSM"; 260 } 261 262 public int getPhoneType() { 263 return PhoneConstants.PHONE_TYPE_GSM; 264 } 265 266 public SignalStrength getSignalStrength() { 267 return mSST.mSignalStrength; 268 } 269 270 public CallTracker getCallTracker() { 271 return mCT; 272 } 273 274 public ServiceStateTracker getServiceStateTracker() { 275 return mSST; 276 } 277 278 public List<? extends MmiCode> 279 getPendingMmiCodes() { 280 return mPendingMMIs; 281 } 282 283 public PhoneConstants.DataState getDataConnectionState(String apnType) { 284 PhoneConstants.DataState ret = PhoneConstants.DataState.DISCONNECTED; 285 286 if (mSST == null) { 287 // Radio Technology Change is ongoning, dispose() and removeReferences() have 288 // already been called 289 290 ret = PhoneConstants.DataState.DISCONNECTED; 291 } else if (mSST.getCurrentGprsState() 292 != ServiceState.STATE_IN_SERVICE) { 293 // If we're out of service, open TCP sockets may still work 294 // but no data will flow 295 ret = PhoneConstants.DataState.DISCONNECTED; 296 } else if (mDataConnectionTracker.isApnTypeEnabled(apnType) == false || 297 mDataConnectionTracker.isApnTypeActive(apnType) == false) { 298 //TODO: isApnTypeActive() is just checking whether ApnContext holds 299 // Dataconnection or not. Checking each ApnState below should 300 // provide the same state. Calling isApnTypeActive() can be removed. 301 ret = PhoneConstants.DataState.DISCONNECTED; 302 } else { /* mSST.gprsState == ServiceState.STATE_IN_SERVICE */ 303 switch (mDataConnectionTracker.getState(apnType)) { 304 case FAILED: 305 case IDLE: 306 ret = PhoneConstants.DataState.DISCONNECTED; 307 break; 308 309 case CONNECTED: 310 case DISCONNECTING: 311 if ( mCT.state != PhoneConstants.State.IDLE 312 && !mSST.isConcurrentVoiceAndDataAllowed()) { 313 ret = PhoneConstants.DataState.SUSPENDED; 314 } else { 315 ret = PhoneConstants.DataState.CONNECTED; 316 } 317 break; 318 319 case INITING: 320 case CONNECTING: 321 case SCANNING: 322 ret = PhoneConstants.DataState.CONNECTING; 323 break; 324 } 325 } 326 327 return ret; 328 } 329 330 public DataActivityState getDataActivityState() { 331 DataActivityState ret = DataActivityState.NONE; 332 333 if (mSST.getCurrentGprsState() == ServiceState.STATE_IN_SERVICE) { 334 switch (mDataConnectionTracker.getActivity()) { 335 case DATAIN: 336 ret = DataActivityState.DATAIN; 337 break; 338 339 case DATAOUT: 340 ret = DataActivityState.DATAOUT; 341 break; 342 343 case DATAINANDOUT: 344 ret = DataActivityState.DATAINANDOUT; 345 break; 346 } 347 } 348 349 return ret; 350 } 351 352 /** 353 * Notify any interested party of a Phone state change {@link PhoneConstants.State} 354 */ 355 /*package*/ void notifyPhoneStateChanged() { 356 mNotifier.notifyPhoneState(this); 357 } 358 359 /** 360 * Notify registrants of a change in the call state. This notifies changes in {@link Call.State} 361 * Use this when changes in the precise call state are needed, else use notifyPhoneStateChanged. 362 */ 363 /*package*/ void notifyPreciseCallStateChanged() { 364 /* we'd love it if this was package-scoped*/ 365 super.notifyPreciseCallStateChangedP(); 366 } 367 368 /*package*/ void 369 notifyNewRingingConnection(Connection c) { 370 /* we'd love it if this was package-scoped*/ 371 super.notifyNewRingingConnectionP(c); 372 } 373 374 /*package*/ void 375 notifyDisconnect(Connection cn) { 376 mDisconnectRegistrants.notifyResult(cn); 377 } 378 379 void notifyUnknownConnection() { 380 mUnknownConnectionRegistrants.notifyResult(this); 381 } 382 383 void notifySuppServiceFailed(SuppService code) { 384 mSuppServiceFailedRegistrants.notifyResult(code); 385 } 386 387 /*package*/ void 388 notifyServiceStateChanged(ServiceState ss) { 389 super.notifyServiceStateChangedP(ss); 390 } 391 392 /*package*/ 393 void notifyLocationChanged() { 394 mNotifier.notifyCellLocation(this); 395 } 396 397 /*package*/ void 398 notifySignalStrength() { 399 mNotifier.notifySignalStrength(this); 400 } 401 402 public void 403 notifyCallForwardingIndicator() { 404 mNotifier.notifyCallForwardingChanged(this); 405 } 406 407 // override for allowing access from other classes of this package 408 /** 409 * {@inheritDoc} 410 */ 411 public final void 412 setSystemProperty(String property, String value) { 413 super.setSystemProperty(property, value); 414 } 415 416 public void registerForSuppServiceNotification( 417 Handler h, int what, Object obj) { 418 mSsnRegistrants.addUnique(h, what, obj); 419 if (mSsnRegistrants.size() == 1) mCM.setSuppServiceNotifications(true, null); 420 } 421 422 public void unregisterForSuppServiceNotification(Handler h) { 423 mSsnRegistrants.remove(h); 424 if (mSsnRegistrants.size() == 0) mCM.setSuppServiceNotifications(false, null); 425 } 426 427 public void 428 acceptCall() throws CallStateException { 429 mCT.acceptCall(); 430 } 431 432 public void 433 rejectCall() throws CallStateException { 434 mCT.rejectCall(); 435 } 436 437 public void 438 switchHoldingAndActive() throws CallStateException { 439 mCT.switchWaitingOrHoldingAndActive(); 440 } 441 442 public boolean canConference() { 443 return mCT.canConference(); 444 } 445 446 public boolean canDial() { 447 return mCT.canDial(); 448 } 449 450 public void conference() throws CallStateException { 451 mCT.conference(); 452 } 453 454 public void clearDisconnected() { 455 mCT.clearDisconnected(); 456 } 457 458 public boolean canTransfer() { 459 return mCT.canTransfer(); 460 } 461 462 public void explicitCallTransfer() throws CallStateException { 463 mCT.explicitCallTransfer(); 464 } 465 466 public GsmCall 467 getForegroundCall() { 468 return mCT.foregroundCall; 469 } 470 471 public GsmCall 472 getBackgroundCall() { 473 return mCT.backgroundCall; 474 } 475 476 public GsmCall 477 getRingingCall() { 478 return mCT.ringingCall; 479 } 480 481 private boolean handleCallDeflectionIncallSupplementaryService( 482 String dialString) throws CallStateException { 483 if (dialString.length() > 1) { 484 return false; 485 } 486 487 if (getRingingCall().getState() != GsmCall.State.IDLE) { 488 if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 0: rejectCall"); 489 try { 490 mCT.rejectCall(); 491 } catch (CallStateException e) { 492 if (LOCAL_DEBUG) Log.d(LOG_TAG, 493 "reject failed", e); 494 notifySuppServiceFailed(Phone.SuppService.REJECT); 495 } 496 } else if (getBackgroundCall().getState() != GsmCall.State.IDLE) { 497 if (LOCAL_DEBUG) Log.d(LOG_TAG, 498 "MmiCode 0: hangupWaitingOrBackground"); 499 mCT.hangupWaitingOrBackground(); 500 } 501 502 return true; 503 } 504 505 private boolean handleCallWaitingIncallSupplementaryService( 506 String dialString) throws CallStateException { 507 int len = dialString.length(); 508 509 if (len > 2) { 510 return false; 511 } 512 513 GsmCall call = (GsmCall) getForegroundCall(); 514 515 try { 516 if (len > 1) { 517 char ch = dialString.charAt(1); 518 int callIndex = ch - '0'; 519 520 if (callIndex >= 1 && callIndex <= GsmCallTracker.MAX_CONNECTIONS) { 521 if (LOCAL_DEBUG) Log.d(LOG_TAG, 522 "MmiCode 1: hangupConnectionByIndex " + 523 callIndex); 524 mCT.hangupConnectionByIndex(call, callIndex); 525 } 526 } else { 527 if (call.getState() != GsmCall.State.IDLE) { 528 if (LOCAL_DEBUG) Log.d(LOG_TAG, 529 "MmiCode 1: hangup foreground"); 530 //mCT.hangupForegroundResumeBackground(); 531 mCT.hangup(call); 532 } else { 533 if (LOCAL_DEBUG) Log.d(LOG_TAG, 534 "MmiCode 1: switchWaitingOrHoldingAndActive"); 535 mCT.switchWaitingOrHoldingAndActive(); 536 } 537 } 538 } catch (CallStateException e) { 539 if (LOCAL_DEBUG) Log.d(LOG_TAG, 540 "hangup failed", e); 541 notifySuppServiceFailed(Phone.SuppService.HANGUP); 542 } 543 544 return true; 545 } 546 547 private boolean handleCallHoldIncallSupplementaryService(String dialString) 548 throws CallStateException { 549 int len = dialString.length(); 550 551 if (len > 2) { 552 return false; 553 } 554 555 GsmCall call = (GsmCall) getForegroundCall(); 556 557 if (len > 1) { 558 try { 559 char ch = dialString.charAt(1); 560 int callIndex = ch - '0'; 561 GsmConnection conn = mCT.getConnectionByIndex(call, callIndex); 562 563 // gsm index starts at 1, up to 5 connections in a call, 564 if (conn != null && callIndex >= 1 && callIndex <= GsmCallTracker.MAX_CONNECTIONS) { 565 if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 2: separate call "+ 566 callIndex); 567 mCT.separate(conn); 568 } else { 569 if (LOCAL_DEBUG) Log.d(LOG_TAG, "separate: invalid call index "+ 570 callIndex); 571 notifySuppServiceFailed(Phone.SuppService.SEPARATE); 572 } 573 } catch (CallStateException e) { 574 if (LOCAL_DEBUG) Log.d(LOG_TAG, 575 "separate failed", e); 576 notifySuppServiceFailed(Phone.SuppService.SEPARATE); 577 } 578 } else { 579 try { 580 if (getRingingCall().getState() != GsmCall.State.IDLE) { 581 if (LOCAL_DEBUG) Log.d(LOG_TAG, 582 "MmiCode 2: accept ringing call"); 583 mCT.acceptCall(); 584 } else { 585 if (LOCAL_DEBUG) Log.d(LOG_TAG, 586 "MmiCode 2: switchWaitingOrHoldingAndActive"); 587 mCT.switchWaitingOrHoldingAndActive(); 588 } 589 } catch (CallStateException e) { 590 if (LOCAL_DEBUG) Log.d(LOG_TAG, 591 "switch failed", e); 592 notifySuppServiceFailed(Phone.SuppService.SWITCH); 593 } 594 } 595 596 return true; 597 } 598 599 private boolean handleMultipartyIncallSupplementaryService( 600 String dialString) throws CallStateException { 601 if (dialString.length() > 1) { 602 return false; 603 } 604 605 if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 3: merge calls"); 606 try { 607 conference(); 608 } catch (CallStateException e) { 609 if (LOCAL_DEBUG) Log.d(LOG_TAG, 610 "conference failed", e); 611 notifySuppServiceFailed(Phone.SuppService.CONFERENCE); 612 } 613 return true; 614 } 615 616 private boolean handleEctIncallSupplementaryService(String dialString) 617 throws CallStateException { 618 619 int len = dialString.length(); 620 621 if (len != 1) { 622 return false; 623 } 624 625 if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 4: explicit call transfer"); 626 try { 627 explicitCallTransfer(); 628 } catch (CallStateException e) { 629 if (LOCAL_DEBUG) Log.d(LOG_TAG, 630 "transfer failed", e); 631 notifySuppServiceFailed(Phone.SuppService.TRANSFER); 632 } 633 return true; 634 } 635 636 private boolean handleCcbsIncallSupplementaryService(String dialString) 637 throws CallStateException { 638 if (dialString.length() > 1) { 639 return false; 640 } 641 642 Log.i(LOG_TAG, "MmiCode 5: CCBS not supported!"); 643 // Treat it as an "unknown" service. 644 notifySuppServiceFailed(Phone.SuppService.UNKNOWN); 645 return true; 646 } 647 648 public boolean handleInCallMmiCommands(String dialString) 649 throws CallStateException { 650 if (!isInCall()) { 651 return false; 652 } 653 654 if (TextUtils.isEmpty(dialString)) { 655 return false; 656 } 657 658 boolean result = false; 659 char ch = dialString.charAt(0); 660 switch (ch) { 661 case '0': 662 result = handleCallDeflectionIncallSupplementaryService( 663 dialString); 664 break; 665 case '1': 666 result = handleCallWaitingIncallSupplementaryService( 667 dialString); 668 break; 669 case '2': 670 result = handleCallHoldIncallSupplementaryService(dialString); 671 break; 672 case '3': 673 result = handleMultipartyIncallSupplementaryService(dialString); 674 break; 675 case '4': 676 result = handleEctIncallSupplementaryService(dialString); 677 break; 678 case '5': 679 result = handleCcbsIncallSupplementaryService(dialString); 680 break; 681 default: 682 break; 683 } 684 685 return result; 686 } 687 688 boolean isInCall() { 689 GsmCall.State foregroundCallState = getForegroundCall().getState(); 690 GsmCall.State backgroundCallState = getBackgroundCall().getState(); 691 GsmCall.State ringingCallState = getRingingCall().getState(); 692 693 return (foregroundCallState.isAlive() || 694 backgroundCallState.isAlive() || 695 ringingCallState.isAlive()); 696 } 697 698 public Connection 699 dial(String dialString) throws CallStateException { 700 return dial(dialString, null); 701 } 702 703 public Connection 704 dial (String dialString, UUSInfo uusInfo) throws CallStateException { 705 // Need to make sure dialString gets parsed properly 706 String newDialString = PhoneNumberUtils.stripSeparators(dialString); 707 708 // handle in-call MMI first if applicable 709 if (handleInCallMmiCommands(newDialString)) { 710 return null; 711 } 712 713 // Only look at the Network portion for mmi 714 String networkPortion = PhoneNumberUtils.extractNetworkPortionAlt(newDialString); 715 GsmMmiCode mmi = GsmMmiCode.newFromDialString(networkPortion, this); 716 if (LOCAL_DEBUG) Log.d(LOG_TAG, 717 "dialing w/ mmi '" + mmi + "'..."); 718 719 if (mmi == null) { 720 return mCT.dial(newDialString, uusInfo); 721 } else if (mmi.isTemporaryModeCLIR()) { 722 return mCT.dial(mmi.dialingNumber, mmi.getCLIRMode(), uusInfo); 723 } else { 724 mPendingMMIs.add(mmi); 725 mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null)); 726 mmi.processCode(); 727 728 // FIXME should this return null or something else? 729 return null; 730 } 731 } 732 733 public boolean handlePinMmi(String dialString) { 734 GsmMmiCode mmi = GsmMmiCode.newFromDialString(dialString, this); 735 736 if (mmi != null && mmi.isPinCommand()) { 737 mPendingMMIs.add(mmi); 738 mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null)); 739 mmi.processCode(); 740 return true; 741 } 742 743 return false; 744 } 745 746 public void sendUssdResponse(String ussdMessge) { 747 GsmMmiCode mmi = GsmMmiCode.newFromUssdUserInput(ussdMessge, this); 748 mPendingMMIs.add(mmi); 749 mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null)); 750 mmi.sendUssd(ussdMessge); 751 } 752 753 public void 754 sendDtmf(char c) { 755 if (!PhoneNumberUtils.is12Key(c)) { 756 Log.e(LOG_TAG, 757 "sendDtmf called with invalid character '" + c + "'"); 758 } else { 759 if (mCT.state == PhoneConstants.State.OFFHOOK) { 760 mCM.sendDtmf(c, null); 761 } 762 } 763 } 764 765 public void 766 startDtmf(char c) { 767 if (!PhoneNumberUtils.is12Key(c)) { 768 Log.e(LOG_TAG, 769 "startDtmf called with invalid character '" + c + "'"); 770 } else { 771 mCM.startDtmf(c, null); 772 } 773 } 774 775 public void 776 stopDtmf() { 777 mCM.stopDtmf(null); 778 } 779 780 public void 781 sendBurstDtmf(String dtmfString) { 782 Log.e(LOG_TAG, "[GSMPhone] sendBurstDtmf() is a CDMA method"); 783 } 784 785 public void 786 setRadioPower(boolean power) { 787 mSST.setRadioPower(power); 788 } 789 790 private void storeVoiceMailNumber(String number) { 791 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 792 SharedPreferences.Editor editor = sp.edit(); 793 editor.putString(VM_NUMBER, number); 794 editor.apply(); 795 setVmSimImsi(getSubscriberId()); 796 } 797 798 public String getVoiceMailNumber() { 799 // Read from the SIM. If its null, try reading from the shared preference area. 800 String number = mIccRecords.getVoiceMailNumber(); 801 if (TextUtils.isEmpty(number)) { 802 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 803 number = sp.getString(VM_NUMBER, null); 804 } 805 return number; 806 } 807 808 private String getVmSimImsi() { 809 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 810 return sp.getString(VM_SIM_IMSI, null); 811 } 812 813 private void setVmSimImsi(String imsi) { 814 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 815 SharedPreferences.Editor editor = sp.edit(); 816 editor.putString(VM_SIM_IMSI, imsi); 817 editor.apply(); 818 } 819 820 public String getVoiceMailAlphaTag() { 821 String ret; 822 823 ret = mIccRecords.getVoiceMailAlphaTag(); 824 825 if (ret == null || ret.length() == 0) { 826 return mContext.getText( 827 com.android.internal.R.string.defaultVoiceMailAlphaTag).toString(); 828 } 829 830 return ret; 831 } 832 833 public String getDeviceId() { 834 return mImei; 835 } 836 837 public String getDeviceSvn() { 838 return mImeiSv; 839 } 840 841 public String getImei() { 842 return mImei; 843 } 844 845 public String getEsn() { 846 Log.e(LOG_TAG, "[GSMPhone] getEsn() is a CDMA method"); 847 return "0"; 848 } 849 850 public String getMeid() { 851 Log.e(LOG_TAG, "[GSMPhone] getMeid() is a CDMA method"); 852 return "0"; 853 } 854 855 public String getSubscriberId() { 856 return mIccRecords.getIMSI(); 857 } 858 859 public String getLine1Number() { 860 return mIccRecords.getMsisdnNumber(); 861 } 862 863 @Override 864 public String getMsisdn() { 865 return mIccRecords.getMsisdnNumber(); 866 } 867 868 public String getLine1AlphaTag() { 869 return mIccRecords.getMsisdnAlphaTag(); 870 } 871 872 public void setLine1Number(String alphaTag, String number, Message onComplete) { 873 mIccRecords.setMsisdnNumber(alphaTag, number, onComplete); 874 } 875 876 public void setVoiceMailNumber(String alphaTag, 877 String voiceMailNumber, 878 Message onComplete) { 879 880 Message resp; 881 mVmNumber = voiceMailNumber; 882 resp = obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete); 883 mIccRecords.setVoiceMailNumber(alphaTag, mVmNumber, resp); 884 } 885 886 private boolean isValidCommandInterfaceCFReason (int commandInterfaceCFReason) { 887 switch (commandInterfaceCFReason) { 888 case CF_REASON_UNCONDITIONAL: 889 case CF_REASON_BUSY: 890 case CF_REASON_NO_REPLY: 891 case CF_REASON_NOT_REACHABLE: 892 case CF_REASON_ALL: 893 case CF_REASON_ALL_CONDITIONAL: 894 return true; 895 default: 896 return false; 897 } 898 } 899 900 private boolean isValidCommandInterfaceCFAction (int commandInterfaceCFAction) { 901 switch (commandInterfaceCFAction) { 902 case CF_ACTION_DISABLE: 903 case CF_ACTION_ENABLE: 904 case CF_ACTION_REGISTRATION: 905 case CF_ACTION_ERASURE: 906 return true; 907 default: 908 return false; 909 } 910 } 911 912 protected boolean isCfEnable(int action) { 913 return (action == CF_ACTION_ENABLE) || (action == CF_ACTION_REGISTRATION); 914 } 915 916 public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) { 917 if (isValidCommandInterfaceCFReason(commandInterfaceCFReason)) { 918 if (LOCAL_DEBUG) Log.d(LOG_TAG, "requesting call forwarding query."); 919 Message resp; 920 if (commandInterfaceCFReason == CF_REASON_UNCONDITIONAL) { 921 resp = obtainMessage(EVENT_GET_CALL_FORWARD_DONE, onComplete); 922 } else { 923 resp = onComplete; 924 } 925 mCM.queryCallForwardStatus(commandInterfaceCFReason,0,null,resp); 926 } 927 } 928 929 public void setCallForwardingOption(int commandInterfaceCFAction, 930 int commandInterfaceCFReason, 931 String dialingNumber, 932 int timerSeconds, 933 Message onComplete) { 934 if ( (isValidCommandInterfaceCFAction(commandInterfaceCFAction)) && 935 (isValidCommandInterfaceCFReason(commandInterfaceCFReason))) { 936 937 Message resp; 938 if (commandInterfaceCFReason == CF_REASON_UNCONDITIONAL) { 939 resp = obtainMessage(EVENT_SET_CALL_FORWARD_DONE, 940 isCfEnable(commandInterfaceCFAction) ? 1 : 0, 0, onComplete); 941 } else { 942 resp = onComplete; 943 } 944 mCM.setCallForward(commandInterfaceCFAction, 945 commandInterfaceCFReason, 946 CommandsInterface.SERVICE_CLASS_VOICE, 947 dialingNumber, 948 timerSeconds, 949 resp); 950 } 951 } 952 953 public void getOutgoingCallerIdDisplay(Message onComplete) { 954 mCM.getCLIR(onComplete); 955 } 956 957 public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, 958 Message onComplete) { 959 mCM.setCLIR(commandInterfaceCLIRMode, 960 obtainMessage(EVENT_SET_CLIR_COMPLETE, commandInterfaceCLIRMode, 0, onComplete)); 961 } 962 963 public void getCallWaiting(Message onComplete) { 964 //As per 3GPP TS 24.083, section 1.6 UE doesn't need to send service 965 //class parameter in call waiting interrogation to network 966 mCM.queryCallWaiting(CommandsInterface.SERVICE_CLASS_NONE, onComplete); 967 } 968 969 public void setCallWaiting(boolean enable, Message onComplete) { 970 mCM.setCallWaiting(enable, CommandsInterface.SERVICE_CLASS_VOICE, onComplete); 971 } 972 973 public void 974 getAvailableNetworks(Message response) { 975 mCM.getAvailableNetworks(response); 976 } 977 978 /** 979 * Small container class used to hold information relevant to 980 * the carrier selection process. operatorNumeric can be "" 981 * if we are looking for automatic selection. operatorAlphaLong is the 982 * corresponding operator name. 983 */ 984 private static class NetworkSelectMessage { 985 public Message message; 986 public String operatorNumeric; 987 public String operatorAlphaLong; 988 } 989 990 public void 991 setNetworkSelectionModeAutomatic(Message response) { 992 // wrap the response message in our own message along with 993 // an empty string (to indicate automatic selection) for the 994 // operator's id. 995 NetworkSelectMessage nsm = new NetworkSelectMessage(); 996 nsm.message = response; 997 nsm.operatorNumeric = ""; 998 nsm.operatorAlphaLong = ""; 999 1000 // get the message 1001 Message msg = obtainMessage(EVENT_SET_NETWORK_AUTOMATIC_COMPLETE, nsm); 1002 if (LOCAL_DEBUG) 1003 Log.d(LOG_TAG, "wrapping and sending message to connect automatically"); 1004 1005 mCM.setNetworkSelectionModeAutomatic(msg); 1006 } 1007 1008 public void 1009 selectNetworkManually(OperatorInfo network, 1010 Message response) { 1011 // wrap the response message in our own message along with 1012 // the operator's id. 1013 NetworkSelectMessage nsm = new NetworkSelectMessage(); 1014 nsm.message = response; 1015 nsm.operatorNumeric = network.getOperatorNumeric(); 1016 nsm.operatorAlphaLong = network.getOperatorAlphaLong(); 1017 1018 // get the message 1019 Message msg = obtainMessage(EVENT_SET_NETWORK_MANUAL_COMPLETE, nsm); 1020 1021 mCM.setNetworkSelectionModeManual(network.getOperatorNumeric(), msg); 1022 } 1023 1024 public void 1025 getNeighboringCids(Message response) { 1026 mCM.getNeighboringCids(response); 1027 } 1028 1029 public void setOnPostDialCharacter(Handler h, int what, Object obj) { 1030 mPostDialHandler = new Registrant(h, what, obj); 1031 } 1032 1033 public void setMute(boolean muted) { 1034 mCT.setMute(muted); 1035 } 1036 1037 public boolean getMute() { 1038 return mCT.getMute(); 1039 } 1040 1041 public void getDataCallList(Message response) { 1042 mCM.getDataCallList(response); 1043 } 1044 1045 public void updateServiceLocation() { 1046 mSST.enableSingleLocationUpdate(); 1047 } 1048 1049 public void enableLocationUpdates() { 1050 mSST.enableLocationUpdates(); 1051 } 1052 1053 public void disableLocationUpdates() { 1054 mSST.disableLocationUpdates(); 1055 } 1056 1057 public boolean getDataRoamingEnabled() { 1058 return mDataConnectionTracker.getDataOnRoamingEnabled(); 1059 } 1060 1061 public void setDataRoamingEnabled(boolean enable) { 1062 mDataConnectionTracker.setDataOnRoamingEnabled(enable); 1063 } 1064 1065 /** 1066 * Removes the given MMI from the pending list and notifies 1067 * registrants that it is complete. 1068 * @param mmi MMI that is done 1069 */ 1070 /*package*/ void 1071 onMMIDone(GsmMmiCode mmi) { 1072 /* Only notify complete if it's on the pending list. 1073 * Otherwise, it's already been handled (eg, previously canceled). 1074 * The exception is cancellation of an incoming USSD-REQUEST, which is 1075 * not on the list. 1076 */ 1077 if (mPendingMMIs.remove(mmi) || mmi.isUssdRequest()) { 1078 mMmiCompleteRegistrants.notifyRegistrants( 1079 new AsyncResult(null, mmi, null)); 1080 } 1081 } 1082 1083 1084 private void 1085 onNetworkInitiatedUssd(GsmMmiCode mmi) { 1086 mMmiCompleteRegistrants.notifyRegistrants( 1087 new AsyncResult(null, mmi, null)); 1088 } 1089 1090 1091 /** ussdMode is one of CommandsInterface.USSD_MODE_* */ 1092 private void 1093 onIncomingUSSD (int ussdMode, String ussdMessage) { 1094 boolean isUssdError; 1095 boolean isUssdRequest; 1096 1097 isUssdRequest 1098 = (ussdMode == CommandsInterface.USSD_MODE_REQUEST); 1099 1100 isUssdError 1101 = (ussdMode != CommandsInterface.USSD_MODE_NOTIFY 1102 && ussdMode != CommandsInterface.USSD_MODE_REQUEST); 1103 1104 // See comments in GsmMmiCode.java 1105 // USSD requests aren't finished until one 1106 // of these two events happen 1107 GsmMmiCode found = null; 1108 for (int i = 0, s = mPendingMMIs.size() ; i < s; i++) { 1109 if(mPendingMMIs.get(i).isPendingUSSD()) { 1110 found = mPendingMMIs.get(i); 1111 break; 1112 } 1113 } 1114 1115 if (found != null) { 1116 // Complete pending USSD 1117 1118 if (isUssdError) { 1119 found.onUssdFinishedError(); 1120 } else { 1121 found.onUssdFinished(ussdMessage, isUssdRequest); 1122 } 1123 } else { // pending USSD not found 1124 // The network may initiate its own USSD request 1125 1126 // ignore everything that isnt a Notify or a Request 1127 // also, discard if there is no message to present 1128 if (!isUssdError && ussdMessage != null) { 1129 GsmMmiCode mmi; 1130 mmi = GsmMmiCode.newNetworkInitiatedUssd(ussdMessage, 1131 isUssdRequest, 1132 GSMPhone.this); 1133 onNetworkInitiatedUssd(mmi); 1134 } 1135 } 1136 } 1137 1138 /** 1139 * Make sure the network knows our preferred setting. 1140 */ 1141 protected void syncClirSetting() { 1142 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 1143 int clirSetting = sp.getInt(CLIR_KEY, -1); 1144 if (clirSetting >= 0) { 1145 mCM.setCLIR(clirSetting, null); 1146 } 1147 } 1148 1149 @Override 1150 public void handleMessage (Message msg) { 1151 AsyncResult ar; 1152 Message onComplete; 1153 1154 switch (msg.what) { 1155 case EVENT_RADIO_AVAILABLE: { 1156 mCM.getBasebandVersion( 1157 obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE)); 1158 1159 mCM.getIMEI(obtainMessage(EVENT_GET_IMEI_DONE)); 1160 mCM.getIMEISV(obtainMessage(EVENT_GET_IMEISV_DONE)); 1161 } 1162 break; 1163 1164 case EVENT_RADIO_ON: 1165 break; 1166 1167 case EVENT_REGISTERED_TO_NETWORK: 1168 syncClirSetting(); 1169 break; 1170 1171 case EVENT_SIM_RECORDS_LOADED: 1172 updateCurrentCarrierInProvider(); 1173 1174 // Check if this is a different SIM than the previous one. If so unset the 1175 // voice mail number. 1176 String imsi = getVmSimImsi(); 1177 String imsiFromSIM = getSubscriberId(); 1178 if (imsi != null && imsiFromSIM != null && !imsiFromSIM.equals(imsi)) { 1179 storeVoiceMailNumber(null); 1180 setVmSimImsi(null); 1181 } 1182 1183 break; 1184 1185 case EVENT_GET_BASEBAND_VERSION_DONE: 1186 ar = (AsyncResult)msg.obj; 1187 1188 if (ar.exception != null) { 1189 break; 1190 } 1191 1192 if (LOCAL_DEBUG) Log.d(LOG_TAG, "Baseband version: " + ar.result); 1193 setSystemProperty(PROPERTY_BASEBAND_VERSION, (String)ar.result); 1194 break; 1195 1196 case EVENT_GET_IMEI_DONE: 1197 ar = (AsyncResult)msg.obj; 1198 1199 if (ar.exception != null) { 1200 break; 1201 } 1202 1203 mImei = (String)ar.result; 1204 break; 1205 1206 case EVENT_GET_IMEISV_DONE: 1207 ar = (AsyncResult)msg.obj; 1208 1209 if (ar.exception != null) { 1210 break; 1211 } 1212 1213 mImeiSv = (String)ar.result; 1214 break; 1215 1216 case EVENT_USSD: 1217 ar = (AsyncResult)msg.obj; 1218 1219 String[] ussdResult = (String[]) ar.result; 1220 1221 if (ussdResult.length > 1) { 1222 try { 1223 onIncomingUSSD(Integer.parseInt(ussdResult[0]), ussdResult[1]); 1224 } catch (NumberFormatException e) { 1225 Log.w(LOG_TAG, "error parsing USSD"); 1226 } 1227 } 1228 break; 1229 1230 case EVENT_RADIO_OFF_OR_NOT_AVAILABLE: 1231 // Some MMI requests (eg USSD) are not completed 1232 // within the course of a CommandsInterface request 1233 // If the radio shuts off or resets while one of these 1234 // is pending, we need to clean up. 1235 1236 for (int i = mPendingMMIs.size() - 1; i >= 0; i--) { 1237 if (mPendingMMIs.get(i).isPendingUSSD()) { 1238 mPendingMMIs.get(i).onUssdFinishedError(); 1239 } 1240 } 1241 break; 1242 1243 case EVENT_SSN: 1244 ar = (AsyncResult)msg.obj; 1245 SuppServiceNotification not = (SuppServiceNotification) ar.result; 1246 mSsnRegistrants.notifyRegistrants(ar); 1247 break; 1248 1249 case EVENT_SET_CALL_FORWARD_DONE: 1250 ar = (AsyncResult)msg.obj; 1251 if (ar.exception == null) { 1252 mIccRecords.setVoiceCallForwardingFlag(1, msg.arg1 == 1); 1253 } 1254 onComplete = (Message) ar.userObj; 1255 if (onComplete != null) { 1256 AsyncResult.forMessage(onComplete, ar.result, ar.exception); 1257 onComplete.sendToTarget(); 1258 } 1259 break; 1260 1261 case EVENT_SET_VM_NUMBER_DONE: 1262 ar = (AsyncResult)msg.obj; 1263 if (IccVmNotSupportedException.class.isInstance(ar.exception)) { 1264 storeVoiceMailNumber(mVmNumber); 1265 ar.exception = null; 1266 } 1267 onComplete = (Message) ar.userObj; 1268 if (onComplete != null) { 1269 AsyncResult.forMessage(onComplete, ar.result, ar.exception); 1270 onComplete.sendToTarget(); 1271 } 1272 break; 1273 1274 1275 case EVENT_GET_CALL_FORWARD_DONE: 1276 ar = (AsyncResult)msg.obj; 1277 if (ar.exception == null) { 1278 handleCfuQueryResult((CallForwardInfo[])ar.result); 1279 } 1280 onComplete = (Message) ar.userObj; 1281 if (onComplete != null) { 1282 AsyncResult.forMessage(onComplete, ar.result, ar.exception); 1283 onComplete.sendToTarget(); 1284 } 1285 break; 1286 1287 case EVENT_NEW_ICC_SMS: 1288 ar = (AsyncResult)msg.obj; 1289 mSMS.dispatchMessage((SmsMessage)ar.result); 1290 break; 1291 1292 case EVENT_SET_NETWORK_AUTOMATIC: 1293 ar = (AsyncResult)msg.obj; 1294 setNetworkSelectionModeAutomatic((Message)ar.result); 1295 break; 1296 1297 case EVENT_ICC_RECORD_EVENTS: 1298 ar = (AsyncResult)msg.obj; 1299 processIccRecordEvents((Integer)ar.result); 1300 break; 1301 1302 // handle the select network completion callbacks. 1303 case EVENT_SET_NETWORK_MANUAL_COMPLETE: 1304 case EVENT_SET_NETWORK_AUTOMATIC_COMPLETE: 1305 handleSetSelectNetwork((AsyncResult) msg.obj); 1306 break; 1307 1308 case EVENT_SET_CLIR_COMPLETE: 1309 ar = (AsyncResult)msg.obj; 1310 if (ar.exception == null) { 1311 saveClirSetting(msg.arg1); 1312 } 1313 onComplete = (Message) ar.userObj; 1314 if (onComplete != null) { 1315 AsyncResult.forMessage(onComplete, ar.result, ar.exception); 1316 onComplete.sendToTarget(); 1317 } 1318 break; 1319 1320 default: 1321 super.handleMessage(msg); 1322 } 1323 } 1324 1325 private void processIccRecordEvents(int eventCode) { 1326 switch (eventCode) { 1327 case SIMRecords.EVENT_CFI: 1328 notifyCallForwardingIndicator(); 1329 break; 1330 case SIMRecords.EVENT_MWI: 1331 notifyMessageWaitingIndicator(); 1332 break; 1333 } 1334 } 1335 1336 /** 1337 * Sets the "current" field in the telephony provider according to the SIM's operator 1338 * 1339 * @return true for success; false otherwise. 1340 */ 1341 boolean updateCurrentCarrierInProvider() { 1342 if (mIccRecords != null) { 1343 try { 1344 Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current"); 1345 ContentValues map = new ContentValues(); 1346 map.put(Telephony.Carriers.NUMERIC, mIccRecords.getOperatorNumeric()); 1347 mContext.getContentResolver().insert(uri, map); 1348 return true; 1349 } catch (SQLException e) { 1350 Log.e(LOG_TAG, "Can't store current operator", e); 1351 } 1352 } 1353 return false; 1354 } 1355 1356 /** 1357 * Used to track the settings upon completion of the network change. 1358 */ 1359 private void handleSetSelectNetwork(AsyncResult ar) { 1360 // look for our wrapper within the asyncresult, skip the rest if it 1361 // is null. 1362 if (!(ar.userObj instanceof NetworkSelectMessage)) { 1363 if (LOCAL_DEBUG) Log.d(LOG_TAG, "unexpected result from user object."); 1364 return; 1365 } 1366 1367 NetworkSelectMessage nsm = (NetworkSelectMessage) ar.userObj; 1368 1369 // found the object, now we send off the message we had originally 1370 // attached to the request. 1371 if (nsm.message != null) { 1372 if (LOCAL_DEBUG) Log.d(LOG_TAG, "sending original message to recipient"); 1373 AsyncResult.forMessage(nsm.message, ar.result, ar.exception); 1374 nsm.message.sendToTarget(); 1375 } 1376 1377 // open the shared preferences editor, and write the value. 1378 // nsm.operatorNumeric is "" if we're in automatic.selection. 1379 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 1380 SharedPreferences.Editor editor = sp.edit(); 1381 editor.putString(NETWORK_SELECTION_KEY, nsm.operatorNumeric); 1382 editor.putString(NETWORK_SELECTION_NAME_KEY, nsm.operatorAlphaLong); 1383 1384 // commit and log the result. 1385 if (! editor.commit()) { 1386 Log.e(LOG_TAG, "failed to commit network selection preference"); 1387 } 1388 1389 } 1390 1391 /** 1392 * Saves CLIR setting so that we can re-apply it as necessary 1393 * (in case the RIL resets it across reboots). 1394 */ 1395 public void saveClirSetting(int commandInterfaceCLIRMode) { 1396 // open the shared preferences editor, and write the value. 1397 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 1398 SharedPreferences.Editor editor = sp.edit(); 1399 editor.putInt(CLIR_KEY, commandInterfaceCLIRMode); 1400 1401 // commit and log the result. 1402 if (! editor.commit()) { 1403 Log.e(LOG_TAG, "failed to commit CLIR preference"); 1404 } 1405 } 1406 1407 private void handleCfuQueryResult(CallForwardInfo[] infos) { 1408 if (infos == null || infos.length == 0) { 1409 // Assume the default is not active 1410 // Set unconditional CFF in SIM to false 1411 mIccRecords.setVoiceCallForwardingFlag(1, false); 1412 } else { 1413 for (int i = 0, s = infos.length; i < s; i++) { 1414 if ((infos[i].serviceClass & SERVICE_CLASS_VOICE) != 0) { 1415 mIccRecords.setVoiceCallForwardingFlag(1, (infos[i].status == 1)); 1416 // should only have the one 1417 break; 1418 } 1419 } 1420 } 1421 } 1422 1423 /** 1424 * Retrieves the PhoneSubInfo of the GSMPhone 1425 */ 1426 public PhoneSubInfo getPhoneSubInfo(){ 1427 return mSubInfo; 1428 } 1429 1430 /** 1431 * Retrieves the IccSmsInterfaceManager of the GSMPhone 1432 */ 1433 public IccSmsInterfaceManager getIccSmsInterfaceManager(){ 1434 return mSimSmsIntManager; 1435 } 1436 1437 /** 1438 * Retrieves the IccPhoneBookInterfaceManager of the GSMPhone 1439 */ 1440 public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){ 1441 return mSimPhoneBookIntManager; 1442 } 1443 1444 /** 1445 * Activate or deactivate cell broadcast SMS. 1446 * 1447 * @param activate 0 = activate, 1 = deactivate 1448 * @param response Callback message is empty on completion 1449 */ 1450 public void activateCellBroadcastSms(int activate, Message response) { 1451 Log.e(LOG_TAG, "[GSMPhone] activateCellBroadcastSms() is obsolete; use SmsManager"); 1452 response.sendToTarget(); 1453 } 1454 1455 /** 1456 * Query the current configuration of cdma cell broadcast SMS. 1457 * 1458 * @param response Callback message is empty on completion 1459 */ 1460 public void getCellBroadcastSmsConfig(Message response) { 1461 Log.e(LOG_TAG, "[GSMPhone] getCellBroadcastSmsConfig() is obsolete; use SmsManager"); 1462 response.sendToTarget(); 1463 } 1464 1465 /** 1466 * Configure cdma cell broadcast SMS. 1467 * 1468 * @param response Callback message is empty on completion 1469 */ 1470 public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response) { 1471 Log.e(LOG_TAG, "[GSMPhone] setCellBroadcastSmsConfig() is obsolete; use SmsManager"); 1472 response.sendToTarget(); 1473 } 1474 1475 public boolean isCspPlmnEnabled() { 1476 return mIccRecords.isCspPlmnEnabled(); 1477 } 1478 1479 private void registerForSimRecordEvents() { 1480 mIccRecords.registerForNetworkSelectionModeAutomatic( 1481 this, EVENT_SET_NETWORK_AUTOMATIC, null); 1482 mIccRecords.registerForNewSms(this, EVENT_NEW_ICC_SMS, null); 1483 mIccRecords.registerForRecordsEvents(this, EVENT_ICC_RECORD_EVENTS, null); 1484 mIccRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null); 1485 } 1486 1487 private void unregisterForSimRecordEvents() { 1488 mIccRecords.unregisterForNetworkSelectionModeAutomatic(this); 1489 mIccRecords.unregisterForNewSms(this); 1490 mIccRecords.unregisterForRecordsEvents(this); 1491 mIccRecords.unregisterForRecordsLoaded(this); 1492 } 1493 1494 @Override 1495 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1496 pw.println("GSMPhone extends:"); 1497 super.dump(fd, pw, args); 1498 pw.println(" mCT=" + mCT); 1499 pw.println(" mSST=" + mSST); 1500 pw.println(" mPendingMMIs=" + mPendingMMIs); 1501 pw.println(" mSimPhoneBookIntManager=" + mSimPhoneBookIntManager); 1502 pw.println(" mSimSmsIntManager=" + mSimSmsIntManager); 1503 pw.println(" mSubInfo=" + mSubInfo); 1504 if (VDBG) pw.println(" mImei=" + mImei); 1505 if (VDBG) pw.println(" mImeiSv=" + mImeiSv); 1506 pw.println(" mVmNumber=" + mVmNumber); 1507 } 1508} 1509