GSMPhone.java revision 5b81adc82a53b3064f4baa3acfeabef31586588a
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 public void 398 notifyCallForwardingIndicator() { 399 mNotifier.notifyCallForwardingChanged(this); 400 } 401 402 // override for allowing access from other classes of this package 403 /** 404 * {@inheritDoc} 405 */ 406 public final void 407 setSystemProperty(String property, String value) { 408 super.setSystemProperty(property, value); 409 } 410 411 public void registerForSuppServiceNotification( 412 Handler h, int what, Object obj) { 413 mSsnRegistrants.addUnique(h, what, obj); 414 if (mSsnRegistrants.size() == 1) mCM.setSuppServiceNotifications(true, null); 415 } 416 417 public void unregisterForSuppServiceNotification(Handler h) { 418 mSsnRegistrants.remove(h); 419 if (mSsnRegistrants.size() == 0) mCM.setSuppServiceNotifications(false, null); 420 } 421 422 public void 423 acceptCall() throws CallStateException { 424 mCT.acceptCall(); 425 } 426 427 public void 428 rejectCall() throws CallStateException { 429 mCT.rejectCall(); 430 } 431 432 public void 433 switchHoldingAndActive() throws CallStateException { 434 mCT.switchWaitingOrHoldingAndActive(); 435 } 436 437 public boolean canConference() { 438 return mCT.canConference(); 439 } 440 441 public boolean canDial() { 442 return mCT.canDial(); 443 } 444 445 public void conference() throws CallStateException { 446 mCT.conference(); 447 } 448 449 public void clearDisconnected() { 450 mCT.clearDisconnected(); 451 } 452 453 public boolean canTransfer() { 454 return mCT.canTransfer(); 455 } 456 457 public void explicitCallTransfer() throws CallStateException { 458 mCT.explicitCallTransfer(); 459 } 460 461 public GsmCall 462 getForegroundCall() { 463 return mCT.foregroundCall; 464 } 465 466 public GsmCall 467 getBackgroundCall() { 468 return mCT.backgroundCall; 469 } 470 471 public GsmCall 472 getRingingCall() { 473 return mCT.ringingCall; 474 } 475 476 private boolean handleCallDeflectionIncallSupplementaryService( 477 String dialString) throws CallStateException { 478 if (dialString.length() > 1) { 479 return false; 480 } 481 482 if (getRingingCall().getState() != GsmCall.State.IDLE) { 483 if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 0: rejectCall"); 484 try { 485 mCT.rejectCall(); 486 } catch (CallStateException e) { 487 if (LOCAL_DEBUG) Log.d(LOG_TAG, 488 "reject failed", e); 489 notifySuppServiceFailed(Phone.SuppService.REJECT); 490 } 491 } else if (getBackgroundCall().getState() != GsmCall.State.IDLE) { 492 if (LOCAL_DEBUG) Log.d(LOG_TAG, 493 "MmiCode 0: hangupWaitingOrBackground"); 494 mCT.hangupWaitingOrBackground(); 495 } 496 497 return true; 498 } 499 500 private boolean handleCallWaitingIncallSupplementaryService( 501 String dialString) throws CallStateException { 502 int len = dialString.length(); 503 504 if (len > 2) { 505 return false; 506 } 507 508 GsmCall call = (GsmCall) getForegroundCall(); 509 510 try { 511 if (len > 1) { 512 char ch = dialString.charAt(1); 513 int callIndex = ch - '0'; 514 515 if (callIndex >= 1 && callIndex <= GsmCallTracker.MAX_CONNECTIONS) { 516 if (LOCAL_DEBUG) Log.d(LOG_TAG, 517 "MmiCode 1: hangupConnectionByIndex " + 518 callIndex); 519 mCT.hangupConnectionByIndex(call, callIndex); 520 } 521 } else { 522 if (call.getState() != GsmCall.State.IDLE) { 523 if (LOCAL_DEBUG) Log.d(LOG_TAG, 524 "MmiCode 1: hangup foreground"); 525 //mCT.hangupForegroundResumeBackground(); 526 mCT.hangup(call); 527 } else { 528 if (LOCAL_DEBUG) Log.d(LOG_TAG, 529 "MmiCode 1: switchWaitingOrHoldingAndActive"); 530 mCT.switchWaitingOrHoldingAndActive(); 531 } 532 } 533 } catch (CallStateException e) { 534 if (LOCAL_DEBUG) Log.d(LOG_TAG, 535 "hangup failed", e); 536 notifySuppServiceFailed(Phone.SuppService.HANGUP); 537 } 538 539 return true; 540 } 541 542 private boolean handleCallHoldIncallSupplementaryService(String dialString) 543 throws CallStateException { 544 int len = dialString.length(); 545 546 if (len > 2) { 547 return false; 548 } 549 550 GsmCall call = (GsmCall) getForegroundCall(); 551 552 if (len > 1) { 553 try { 554 char ch = dialString.charAt(1); 555 int callIndex = ch - '0'; 556 GsmConnection conn = mCT.getConnectionByIndex(call, callIndex); 557 558 // gsm index starts at 1, up to 5 connections in a call, 559 if (conn != null && callIndex >= 1 && callIndex <= GsmCallTracker.MAX_CONNECTIONS) { 560 if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 2: separate call "+ 561 callIndex); 562 mCT.separate(conn); 563 } else { 564 if (LOCAL_DEBUG) Log.d(LOG_TAG, "separate: invalid call index "+ 565 callIndex); 566 notifySuppServiceFailed(Phone.SuppService.SEPARATE); 567 } 568 } catch (CallStateException e) { 569 if (LOCAL_DEBUG) Log.d(LOG_TAG, 570 "separate failed", e); 571 notifySuppServiceFailed(Phone.SuppService.SEPARATE); 572 } 573 } else { 574 try { 575 if (getRingingCall().getState() != GsmCall.State.IDLE) { 576 if (LOCAL_DEBUG) Log.d(LOG_TAG, 577 "MmiCode 2: accept ringing call"); 578 mCT.acceptCall(); 579 } else { 580 if (LOCAL_DEBUG) Log.d(LOG_TAG, 581 "MmiCode 2: switchWaitingOrHoldingAndActive"); 582 mCT.switchWaitingOrHoldingAndActive(); 583 } 584 } catch (CallStateException e) { 585 if (LOCAL_DEBUG) Log.d(LOG_TAG, 586 "switch failed", e); 587 notifySuppServiceFailed(Phone.SuppService.SWITCH); 588 } 589 } 590 591 return true; 592 } 593 594 private boolean handleMultipartyIncallSupplementaryService( 595 String dialString) throws CallStateException { 596 if (dialString.length() > 1) { 597 return false; 598 } 599 600 if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 3: merge calls"); 601 try { 602 conference(); 603 } catch (CallStateException e) { 604 if (LOCAL_DEBUG) Log.d(LOG_TAG, 605 "conference failed", e); 606 notifySuppServiceFailed(Phone.SuppService.CONFERENCE); 607 } 608 return true; 609 } 610 611 private boolean handleEctIncallSupplementaryService(String dialString) 612 throws CallStateException { 613 614 int len = dialString.length(); 615 616 if (len != 1) { 617 return false; 618 } 619 620 if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 4: explicit call transfer"); 621 try { 622 explicitCallTransfer(); 623 } catch (CallStateException e) { 624 if (LOCAL_DEBUG) Log.d(LOG_TAG, 625 "transfer failed", e); 626 notifySuppServiceFailed(Phone.SuppService.TRANSFER); 627 } 628 return true; 629 } 630 631 private boolean handleCcbsIncallSupplementaryService(String dialString) 632 throws CallStateException { 633 if (dialString.length() > 1) { 634 return false; 635 } 636 637 Log.i(LOG_TAG, "MmiCode 5: CCBS not supported!"); 638 // Treat it as an "unknown" service. 639 notifySuppServiceFailed(Phone.SuppService.UNKNOWN); 640 return true; 641 } 642 643 public boolean handleInCallMmiCommands(String dialString) 644 throws CallStateException { 645 if (!isInCall()) { 646 return false; 647 } 648 649 if (TextUtils.isEmpty(dialString)) { 650 return false; 651 } 652 653 boolean result = false; 654 char ch = dialString.charAt(0); 655 switch (ch) { 656 case '0': 657 result = handleCallDeflectionIncallSupplementaryService( 658 dialString); 659 break; 660 case '1': 661 result = handleCallWaitingIncallSupplementaryService( 662 dialString); 663 break; 664 case '2': 665 result = handleCallHoldIncallSupplementaryService(dialString); 666 break; 667 case '3': 668 result = handleMultipartyIncallSupplementaryService(dialString); 669 break; 670 case '4': 671 result = handleEctIncallSupplementaryService(dialString); 672 break; 673 case '5': 674 result = handleCcbsIncallSupplementaryService(dialString); 675 break; 676 default: 677 break; 678 } 679 680 return result; 681 } 682 683 boolean isInCall() { 684 GsmCall.State foregroundCallState = getForegroundCall().getState(); 685 GsmCall.State backgroundCallState = getBackgroundCall().getState(); 686 GsmCall.State ringingCallState = getRingingCall().getState(); 687 688 return (foregroundCallState.isAlive() || 689 backgroundCallState.isAlive() || 690 ringingCallState.isAlive()); 691 } 692 693 public Connection 694 dial(String dialString) throws CallStateException { 695 return dial(dialString, null); 696 } 697 698 public Connection 699 dial (String dialString, UUSInfo uusInfo) throws CallStateException { 700 // Need to make sure dialString gets parsed properly 701 String newDialString = PhoneNumberUtils.stripSeparators(dialString); 702 703 // handle in-call MMI first if applicable 704 if (handleInCallMmiCommands(newDialString)) { 705 return null; 706 } 707 708 // Only look at the Network portion for mmi 709 String networkPortion = PhoneNumberUtils.extractNetworkPortionAlt(newDialString); 710 GsmMmiCode mmi = GsmMmiCode.newFromDialString(networkPortion, this); 711 if (LOCAL_DEBUG) Log.d(LOG_TAG, 712 "dialing w/ mmi '" + mmi + "'..."); 713 714 if (mmi == null) { 715 return mCT.dial(newDialString, uusInfo); 716 } else if (mmi.isTemporaryModeCLIR()) { 717 return mCT.dial(mmi.dialingNumber, mmi.getCLIRMode(), uusInfo); 718 } else { 719 mPendingMMIs.add(mmi); 720 mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null)); 721 mmi.processCode(); 722 723 // FIXME should this return null or something else? 724 return null; 725 } 726 } 727 728 public boolean handlePinMmi(String dialString) { 729 GsmMmiCode mmi = GsmMmiCode.newFromDialString(dialString, this); 730 731 if (mmi != null && mmi.isPinCommand()) { 732 mPendingMMIs.add(mmi); 733 mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null)); 734 mmi.processCode(); 735 return true; 736 } 737 738 return false; 739 } 740 741 public void sendUssdResponse(String ussdMessge) { 742 GsmMmiCode mmi = GsmMmiCode.newFromUssdUserInput(ussdMessge, this); 743 mPendingMMIs.add(mmi); 744 mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null)); 745 mmi.sendUssd(ussdMessge); 746 } 747 748 public void 749 sendDtmf(char c) { 750 if (!PhoneNumberUtils.is12Key(c)) { 751 Log.e(LOG_TAG, 752 "sendDtmf called with invalid character '" + c + "'"); 753 } else { 754 if (mCT.state == PhoneConstants.State.OFFHOOK) { 755 mCM.sendDtmf(c, null); 756 } 757 } 758 } 759 760 public void 761 startDtmf(char c) { 762 if (!PhoneNumberUtils.is12Key(c)) { 763 Log.e(LOG_TAG, 764 "startDtmf called with invalid character '" + c + "'"); 765 } else { 766 mCM.startDtmf(c, null); 767 } 768 } 769 770 public void 771 stopDtmf() { 772 mCM.stopDtmf(null); 773 } 774 775 public void 776 sendBurstDtmf(String dtmfString) { 777 Log.e(LOG_TAG, "[GSMPhone] sendBurstDtmf() is a CDMA method"); 778 } 779 780 public void 781 setRadioPower(boolean power) { 782 mSST.setRadioPower(power); 783 } 784 785 private void storeVoiceMailNumber(String number) { 786 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 787 SharedPreferences.Editor editor = sp.edit(); 788 editor.putString(VM_NUMBER, number); 789 editor.apply(); 790 setVmSimImsi(getSubscriberId()); 791 } 792 793 public String getVoiceMailNumber() { 794 // Read from the SIM. If its null, try reading from the shared preference area. 795 String number = mIccRecords.getVoiceMailNumber(); 796 if (TextUtils.isEmpty(number)) { 797 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 798 number = sp.getString(VM_NUMBER, null); 799 } 800 return number; 801 } 802 803 private String getVmSimImsi() { 804 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 805 return sp.getString(VM_SIM_IMSI, null); 806 } 807 808 private void setVmSimImsi(String imsi) { 809 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 810 SharedPreferences.Editor editor = sp.edit(); 811 editor.putString(VM_SIM_IMSI, imsi); 812 editor.apply(); 813 } 814 815 public String getVoiceMailAlphaTag() { 816 String ret; 817 818 ret = mIccRecords.getVoiceMailAlphaTag(); 819 820 if (ret == null || ret.length() == 0) { 821 return mContext.getText( 822 com.android.internal.R.string.defaultVoiceMailAlphaTag).toString(); 823 } 824 825 return ret; 826 } 827 828 public String getDeviceId() { 829 return mImei; 830 } 831 832 public String getDeviceSvn() { 833 return mImeiSv; 834 } 835 836 public String getImei() { 837 return mImei; 838 } 839 840 public String getEsn() { 841 Log.e(LOG_TAG, "[GSMPhone] getEsn() is a CDMA method"); 842 return "0"; 843 } 844 845 public String getMeid() { 846 Log.e(LOG_TAG, "[GSMPhone] getMeid() is a CDMA method"); 847 return "0"; 848 } 849 850 public String getSubscriberId() { 851 return mIccRecords.getIMSI(); 852 } 853 854 public String getLine1Number() { 855 return mIccRecords.getMsisdnNumber(); 856 } 857 858 @Override 859 public String getMsisdn() { 860 return mIccRecords.getMsisdnNumber(); 861 } 862 863 public String getLine1AlphaTag() { 864 return mIccRecords.getMsisdnAlphaTag(); 865 } 866 867 public void setLine1Number(String alphaTag, String number, Message onComplete) { 868 mIccRecords.setMsisdnNumber(alphaTag, number, onComplete); 869 } 870 871 public void setVoiceMailNumber(String alphaTag, 872 String voiceMailNumber, 873 Message onComplete) { 874 875 Message resp; 876 mVmNumber = voiceMailNumber; 877 resp = obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete); 878 mIccRecords.setVoiceMailNumber(alphaTag, mVmNumber, resp); 879 } 880 881 private boolean isValidCommandInterfaceCFReason (int commandInterfaceCFReason) { 882 switch (commandInterfaceCFReason) { 883 case CF_REASON_UNCONDITIONAL: 884 case CF_REASON_BUSY: 885 case CF_REASON_NO_REPLY: 886 case CF_REASON_NOT_REACHABLE: 887 case CF_REASON_ALL: 888 case CF_REASON_ALL_CONDITIONAL: 889 return true; 890 default: 891 return false; 892 } 893 } 894 895 private boolean isValidCommandInterfaceCFAction (int commandInterfaceCFAction) { 896 switch (commandInterfaceCFAction) { 897 case CF_ACTION_DISABLE: 898 case CF_ACTION_ENABLE: 899 case CF_ACTION_REGISTRATION: 900 case CF_ACTION_ERASURE: 901 return true; 902 default: 903 return false; 904 } 905 } 906 907 protected boolean isCfEnable(int action) { 908 return (action == CF_ACTION_ENABLE) || (action == CF_ACTION_REGISTRATION); 909 } 910 911 public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) { 912 if (isValidCommandInterfaceCFReason(commandInterfaceCFReason)) { 913 if (LOCAL_DEBUG) Log.d(LOG_TAG, "requesting call forwarding query."); 914 Message resp; 915 if (commandInterfaceCFReason == CF_REASON_UNCONDITIONAL) { 916 resp = obtainMessage(EVENT_GET_CALL_FORWARD_DONE, onComplete); 917 } else { 918 resp = onComplete; 919 } 920 mCM.queryCallForwardStatus(commandInterfaceCFReason,0,null,resp); 921 } 922 } 923 924 public void setCallForwardingOption(int commandInterfaceCFAction, 925 int commandInterfaceCFReason, 926 String dialingNumber, 927 int timerSeconds, 928 Message onComplete) { 929 if ( (isValidCommandInterfaceCFAction(commandInterfaceCFAction)) && 930 (isValidCommandInterfaceCFReason(commandInterfaceCFReason))) { 931 932 Message resp; 933 if (commandInterfaceCFReason == CF_REASON_UNCONDITIONAL) { 934 resp = obtainMessage(EVENT_SET_CALL_FORWARD_DONE, 935 isCfEnable(commandInterfaceCFAction) ? 1 : 0, 0, onComplete); 936 } else { 937 resp = onComplete; 938 } 939 mCM.setCallForward(commandInterfaceCFAction, 940 commandInterfaceCFReason, 941 CommandsInterface.SERVICE_CLASS_VOICE, 942 dialingNumber, 943 timerSeconds, 944 resp); 945 } 946 } 947 948 public void getOutgoingCallerIdDisplay(Message onComplete) { 949 mCM.getCLIR(onComplete); 950 } 951 952 public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, 953 Message onComplete) { 954 mCM.setCLIR(commandInterfaceCLIRMode, 955 obtainMessage(EVENT_SET_CLIR_COMPLETE, commandInterfaceCLIRMode, 0, onComplete)); 956 } 957 958 public void getCallWaiting(Message onComplete) { 959 //As per 3GPP TS 24.083, section 1.6 UE doesn't need to send service 960 //class parameter in call waiting interrogation to network 961 mCM.queryCallWaiting(CommandsInterface.SERVICE_CLASS_NONE, onComplete); 962 } 963 964 public void setCallWaiting(boolean enable, Message onComplete) { 965 mCM.setCallWaiting(enable, CommandsInterface.SERVICE_CLASS_VOICE, onComplete); 966 } 967 968 public void 969 getAvailableNetworks(Message response) { 970 mCM.getAvailableNetworks(response); 971 } 972 973 /** 974 * Small container class used to hold information relevant to 975 * the carrier selection process. operatorNumeric can be "" 976 * if we are looking for automatic selection. operatorAlphaLong is the 977 * corresponding operator name. 978 */ 979 private static class NetworkSelectMessage { 980 public Message message; 981 public String operatorNumeric; 982 public String operatorAlphaLong; 983 } 984 985 public void 986 setNetworkSelectionModeAutomatic(Message response) { 987 // wrap the response message in our own message along with 988 // an empty string (to indicate automatic selection) for the 989 // operator's id. 990 NetworkSelectMessage nsm = new NetworkSelectMessage(); 991 nsm.message = response; 992 nsm.operatorNumeric = ""; 993 nsm.operatorAlphaLong = ""; 994 995 // get the message 996 Message msg = obtainMessage(EVENT_SET_NETWORK_AUTOMATIC_COMPLETE, nsm); 997 if (LOCAL_DEBUG) 998 Log.d(LOG_TAG, "wrapping and sending message to connect automatically"); 999 1000 mCM.setNetworkSelectionModeAutomatic(msg); 1001 } 1002 1003 public void 1004 selectNetworkManually(OperatorInfo network, 1005 Message response) { 1006 // wrap the response message in our own message along with 1007 // the operator's id. 1008 NetworkSelectMessage nsm = new NetworkSelectMessage(); 1009 nsm.message = response; 1010 nsm.operatorNumeric = network.getOperatorNumeric(); 1011 nsm.operatorAlphaLong = network.getOperatorAlphaLong(); 1012 1013 // get the message 1014 Message msg = obtainMessage(EVENT_SET_NETWORK_MANUAL_COMPLETE, nsm); 1015 1016 mCM.setNetworkSelectionModeManual(network.getOperatorNumeric(), msg); 1017 } 1018 1019 public void 1020 getNeighboringCids(Message response) { 1021 mCM.getNeighboringCids(response); 1022 } 1023 1024 public void setOnPostDialCharacter(Handler h, int what, Object obj) { 1025 mPostDialHandler = new Registrant(h, what, obj); 1026 } 1027 1028 public void setMute(boolean muted) { 1029 mCT.setMute(muted); 1030 } 1031 1032 public boolean getMute() { 1033 return mCT.getMute(); 1034 } 1035 1036 public void getDataCallList(Message response) { 1037 mCM.getDataCallList(response); 1038 } 1039 1040 public void updateServiceLocation() { 1041 mSST.enableSingleLocationUpdate(); 1042 } 1043 1044 public void enableLocationUpdates() { 1045 mSST.enableLocationUpdates(); 1046 } 1047 1048 public void disableLocationUpdates() { 1049 mSST.disableLocationUpdates(); 1050 } 1051 1052 public boolean getDataRoamingEnabled() { 1053 return mDataConnectionTracker.getDataOnRoamingEnabled(); 1054 } 1055 1056 public void setDataRoamingEnabled(boolean enable) { 1057 mDataConnectionTracker.setDataOnRoamingEnabled(enable); 1058 } 1059 1060 /** 1061 * Removes the given MMI from the pending list and notifies 1062 * registrants that it is complete. 1063 * @param mmi MMI that is done 1064 */ 1065 /*package*/ void 1066 onMMIDone(GsmMmiCode mmi) { 1067 /* Only notify complete if it's on the pending list. 1068 * Otherwise, it's already been handled (eg, previously canceled). 1069 * The exception is cancellation of an incoming USSD-REQUEST, which is 1070 * not on the list. 1071 */ 1072 if (mPendingMMIs.remove(mmi) || mmi.isUssdRequest()) { 1073 mMmiCompleteRegistrants.notifyRegistrants( 1074 new AsyncResult(null, mmi, null)); 1075 } 1076 } 1077 1078 1079 private void 1080 onNetworkInitiatedUssd(GsmMmiCode mmi) { 1081 mMmiCompleteRegistrants.notifyRegistrants( 1082 new AsyncResult(null, mmi, null)); 1083 } 1084 1085 1086 /** ussdMode is one of CommandsInterface.USSD_MODE_* */ 1087 private void 1088 onIncomingUSSD (int ussdMode, String ussdMessage) { 1089 boolean isUssdError; 1090 boolean isUssdRequest; 1091 1092 isUssdRequest 1093 = (ussdMode == CommandsInterface.USSD_MODE_REQUEST); 1094 1095 isUssdError 1096 = (ussdMode != CommandsInterface.USSD_MODE_NOTIFY 1097 && ussdMode != CommandsInterface.USSD_MODE_REQUEST); 1098 1099 // See comments in GsmMmiCode.java 1100 // USSD requests aren't finished until one 1101 // of these two events happen 1102 GsmMmiCode found = null; 1103 for (int i = 0, s = mPendingMMIs.size() ; i < s; i++) { 1104 if(mPendingMMIs.get(i).isPendingUSSD()) { 1105 found = mPendingMMIs.get(i); 1106 break; 1107 } 1108 } 1109 1110 if (found != null) { 1111 // Complete pending USSD 1112 1113 if (isUssdError) { 1114 found.onUssdFinishedError(); 1115 } else { 1116 found.onUssdFinished(ussdMessage, isUssdRequest); 1117 } 1118 } else { // pending USSD not found 1119 // The network may initiate its own USSD request 1120 1121 // ignore everything that isnt a Notify or a Request 1122 // also, discard if there is no message to present 1123 if (!isUssdError && ussdMessage != null) { 1124 GsmMmiCode mmi; 1125 mmi = GsmMmiCode.newNetworkInitiatedUssd(ussdMessage, 1126 isUssdRequest, 1127 GSMPhone.this); 1128 onNetworkInitiatedUssd(mmi); 1129 } 1130 } 1131 } 1132 1133 /** 1134 * Make sure the network knows our preferred setting. 1135 */ 1136 protected void syncClirSetting() { 1137 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 1138 int clirSetting = sp.getInt(CLIR_KEY, -1); 1139 if (clirSetting >= 0) { 1140 mCM.setCLIR(clirSetting, null); 1141 } 1142 } 1143 1144 @Override 1145 public void handleMessage (Message msg) { 1146 AsyncResult ar; 1147 Message onComplete; 1148 1149 switch (msg.what) { 1150 case EVENT_RADIO_AVAILABLE: { 1151 mCM.getBasebandVersion( 1152 obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE)); 1153 1154 mCM.getIMEI(obtainMessage(EVENT_GET_IMEI_DONE)); 1155 mCM.getIMEISV(obtainMessage(EVENT_GET_IMEISV_DONE)); 1156 } 1157 break; 1158 1159 case EVENT_RADIO_ON: 1160 break; 1161 1162 case EVENT_REGISTERED_TO_NETWORK: 1163 syncClirSetting(); 1164 break; 1165 1166 case EVENT_SIM_RECORDS_LOADED: 1167 updateCurrentCarrierInProvider(); 1168 1169 // Check if this is a different SIM than the previous one. If so unset the 1170 // voice mail number. 1171 String imsi = getVmSimImsi(); 1172 String imsiFromSIM = getSubscriberId(); 1173 if (imsi != null && imsiFromSIM != null && !imsiFromSIM.equals(imsi)) { 1174 storeVoiceMailNumber(null); 1175 setVmSimImsi(null); 1176 } 1177 1178 break; 1179 1180 case EVENT_GET_BASEBAND_VERSION_DONE: 1181 ar = (AsyncResult)msg.obj; 1182 1183 if (ar.exception != null) { 1184 break; 1185 } 1186 1187 if (LOCAL_DEBUG) Log.d(LOG_TAG, "Baseband version: " + ar.result); 1188 setSystemProperty(PROPERTY_BASEBAND_VERSION, (String)ar.result); 1189 break; 1190 1191 case EVENT_GET_IMEI_DONE: 1192 ar = (AsyncResult)msg.obj; 1193 1194 if (ar.exception != null) { 1195 break; 1196 } 1197 1198 mImei = (String)ar.result; 1199 break; 1200 1201 case EVENT_GET_IMEISV_DONE: 1202 ar = (AsyncResult)msg.obj; 1203 1204 if (ar.exception != null) { 1205 break; 1206 } 1207 1208 mImeiSv = (String)ar.result; 1209 break; 1210 1211 case EVENT_USSD: 1212 ar = (AsyncResult)msg.obj; 1213 1214 String[] ussdResult = (String[]) ar.result; 1215 1216 if (ussdResult.length > 1) { 1217 try { 1218 onIncomingUSSD(Integer.parseInt(ussdResult[0]), ussdResult[1]); 1219 } catch (NumberFormatException e) { 1220 Log.w(LOG_TAG, "error parsing USSD"); 1221 } 1222 } 1223 break; 1224 1225 case EVENT_RADIO_OFF_OR_NOT_AVAILABLE: 1226 // Some MMI requests (eg USSD) are not completed 1227 // within the course of a CommandsInterface request 1228 // If the radio shuts off or resets while one of these 1229 // is pending, we need to clean up. 1230 1231 for (int i = mPendingMMIs.size() - 1; i >= 0; i--) { 1232 if (mPendingMMIs.get(i).isPendingUSSD()) { 1233 mPendingMMIs.get(i).onUssdFinishedError(); 1234 } 1235 } 1236 break; 1237 1238 case EVENT_SSN: 1239 ar = (AsyncResult)msg.obj; 1240 SuppServiceNotification not = (SuppServiceNotification) ar.result; 1241 mSsnRegistrants.notifyRegistrants(ar); 1242 break; 1243 1244 case EVENT_SET_CALL_FORWARD_DONE: 1245 ar = (AsyncResult)msg.obj; 1246 if (ar.exception == null) { 1247 mIccRecords.setVoiceCallForwardingFlag(1, msg.arg1 == 1); 1248 } 1249 onComplete = (Message) ar.userObj; 1250 if (onComplete != null) { 1251 AsyncResult.forMessage(onComplete, ar.result, ar.exception); 1252 onComplete.sendToTarget(); 1253 } 1254 break; 1255 1256 case EVENT_SET_VM_NUMBER_DONE: 1257 ar = (AsyncResult)msg.obj; 1258 if (IccVmNotSupportedException.class.isInstance(ar.exception)) { 1259 storeVoiceMailNumber(mVmNumber); 1260 ar.exception = null; 1261 } 1262 onComplete = (Message) ar.userObj; 1263 if (onComplete != null) { 1264 AsyncResult.forMessage(onComplete, ar.result, ar.exception); 1265 onComplete.sendToTarget(); 1266 } 1267 break; 1268 1269 1270 case EVENT_GET_CALL_FORWARD_DONE: 1271 ar = (AsyncResult)msg.obj; 1272 if (ar.exception == null) { 1273 handleCfuQueryResult((CallForwardInfo[])ar.result); 1274 } 1275 onComplete = (Message) ar.userObj; 1276 if (onComplete != null) { 1277 AsyncResult.forMessage(onComplete, ar.result, ar.exception); 1278 onComplete.sendToTarget(); 1279 } 1280 break; 1281 1282 case EVENT_NEW_ICC_SMS: 1283 ar = (AsyncResult)msg.obj; 1284 mSMS.dispatchMessage((SmsMessage)ar.result); 1285 break; 1286 1287 case EVENT_SET_NETWORK_AUTOMATIC: 1288 ar = (AsyncResult)msg.obj; 1289 setNetworkSelectionModeAutomatic((Message)ar.result); 1290 break; 1291 1292 case EVENT_ICC_RECORD_EVENTS: 1293 ar = (AsyncResult)msg.obj; 1294 processIccRecordEvents((Integer)ar.result); 1295 break; 1296 1297 // handle the select network completion callbacks. 1298 case EVENT_SET_NETWORK_MANUAL_COMPLETE: 1299 case EVENT_SET_NETWORK_AUTOMATIC_COMPLETE: 1300 handleSetSelectNetwork((AsyncResult) msg.obj); 1301 break; 1302 1303 case EVENT_SET_CLIR_COMPLETE: 1304 ar = (AsyncResult)msg.obj; 1305 if (ar.exception == null) { 1306 saveClirSetting(msg.arg1); 1307 } 1308 onComplete = (Message) ar.userObj; 1309 if (onComplete != null) { 1310 AsyncResult.forMessage(onComplete, ar.result, ar.exception); 1311 onComplete.sendToTarget(); 1312 } 1313 break; 1314 1315 default: 1316 super.handleMessage(msg); 1317 } 1318 } 1319 1320 private void processIccRecordEvents(int eventCode) { 1321 switch (eventCode) { 1322 case SIMRecords.EVENT_CFI: 1323 notifyCallForwardingIndicator(); 1324 break; 1325 case SIMRecords.EVENT_MWI: 1326 notifyMessageWaitingIndicator(); 1327 break; 1328 } 1329 } 1330 1331 /** 1332 * Sets the "current" field in the telephony provider according to the SIM's operator 1333 * 1334 * @return true for success; false otherwise. 1335 */ 1336 boolean updateCurrentCarrierInProvider() { 1337 if (mIccRecords != null) { 1338 try { 1339 Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current"); 1340 ContentValues map = new ContentValues(); 1341 map.put(Telephony.Carriers.NUMERIC, mIccRecords.getOperatorNumeric()); 1342 mContext.getContentResolver().insert(uri, map); 1343 return true; 1344 } catch (SQLException e) { 1345 Log.e(LOG_TAG, "Can't store current operator", e); 1346 } 1347 } 1348 return false; 1349 } 1350 1351 /** 1352 * Used to track the settings upon completion of the network change. 1353 */ 1354 private void handleSetSelectNetwork(AsyncResult ar) { 1355 // look for our wrapper within the asyncresult, skip the rest if it 1356 // is null. 1357 if (!(ar.userObj instanceof NetworkSelectMessage)) { 1358 if (LOCAL_DEBUG) Log.d(LOG_TAG, "unexpected result from user object."); 1359 return; 1360 } 1361 1362 NetworkSelectMessage nsm = (NetworkSelectMessage) ar.userObj; 1363 1364 // found the object, now we send off the message we had originally 1365 // attached to the request. 1366 if (nsm.message != null) { 1367 if (LOCAL_DEBUG) Log.d(LOG_TAG, "sending original message to recipient"); 1368 AsyncResult.forMessage(nsm.message, ar.result, ar.exception); 1369 nsm.message.sendToTarget(); 1370 } 1371 1372 // open the shared preferences editor, and write the value. 1373 // nsm.operatorNumeric is "" if we're in automatic.selection. 1374 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 1375 SharedPreferences.Editor editor = sp.edit(); 1376 editor.putString(NETWORK_SELECTION_KEY, nsm.operatorNumeric); 1377 editor.putString(NETWORK_SELECTION_NAME_KEY, nsm.operatorAlphaLong); 1378 1379 // commit and log the result. 1380 if (! editor.commit()) { 1381 Log.e(LOG_TAG, "failed to commit network selection preference"); 1382 } 1383 1384 } 1385 1386 /** 1387 * Saves CLIR setting so that we can re-apply it as necessary 1388 * (in case the RIL resets it across reboots). 1389 */ 1390 public void saveClirSetting(int commandInterfaceCLIRMode) { 1391 // open the shared preferences editor, and write the value. 1392 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 1393 SharedPreferences.Editor editor = sp.edit(); 1394 editor.putInt(CLIR_KEY, commandInterfaceCLIRMode); 1395 1396 // commit and log the result. 1397 if (! editor.commit()) { 1398 Log.e(LOG_TAG, "failed to commit CLIR preference"); 1399 } 1400 } 1401 1402 private void handleCfuQueryResult(CallForwardInfo[] infos) { 1403 if (infos == null || infos.length == 0) { 1404 // Assume the default is not active 1405 // Set unconditional CFF in SIM to false 1406 mIccRecords.setVoiceCallForwardingFlag(1, false); 1407 } else { 1408 for (int i = 0, s = infos.length; i < s; i++) { 1409 if ((infos[i].serviceClass & SERVICE_CLASS_VOICE) != 0) { 1410 mIccRecords.setVoiceCallForwardingFlag(1, (infos[i].status == 1)); 1411 // should only have the one 1412 break; 1413 } 1414 } 1415 } 1416 } 1417 1418 /** 1419 * Retrieves the PhoneSubInfo of the GSMPhone 1420 */ 1421 public PhoneSubInfo getPhoneSubInfo(){ 1422 return mSubInfo; 1423 } 1424 1425 /** 1426 * Retrieves the IccSmsInterfaceManager of the GSMPhone 1427 */ 1428 public IccSmsInterfaceManager getIccSmsInterfaceManager(){ 1429 return mSimSmsIntManager; 1430 } 1431 1432 /** 1433 * Retrieves the IccPhoneBookInterfaceManager of the GSMPhone 1434 */ 1435 public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){ 1436 return mSimPhoneBookIntManager; 1437 } 1438 1439 /** 1440 * Activate or deactivate cell broadcast SMS. 1441 * 1442 * @param activate 0 = activate, 1 = deactivate 1443 * @param response Callback message is empty on completion 1444 */ 1445 public void activateCellBroadcastSms(int activate, Message response) { 1446 Log.e(LOG_TAG, "[GSMPhone] activateCellBroadcastSms() is obsolete; use SmsManager"); 1447 response.sendToTarget(); 1448 } 1449 1450 /** 1451 * Query the current configuration of cdma cell broadcast SMS. 1452 * 1453 * @param response Callback message is empty on completion 1454 */ 1455 public void getCellBroadcastSmsConfig(Message response) { 1456 Log.e(LOG_TAG, "[GSMPhone] getCellBroadcastSmsConfig() is obsolete; use SmsManager"); 1457 response.sendToTarget(); 1458 } 1459 1460 /** 1461 * Configure cdma cell broadcast SMS. 1462 * 1463 * @param response Callback message is empty on completion 1464 */ 1465 public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response) { 1466 Log.e(LOG_TAG, "[GSMPhone] setCellBroadcastSmsConfig() is obsolete; use SmsManager"); 1467 response.sendToTarget(); 1468 } 1469 1470 public boolean isCspPlmnEnabled() { 1471 return mIccRecords.isCspPlmnEnabled(); 1472 } 1473 1474 private void registerForSimRecordEvents() { 1475 mIccRecords.registerForNetworkSelectionModeAutomatic( 1476 this, EVENT_SET_NETWORK_AUTOMATIC, null); 1477 mIccRecords.registerForNewSms(this, EVENT_NEW_ICC_SMS, null); 1478 mIccRecords.registerForRecordsEvents(this, EVENT_ICC_RECORD_EVENTS, null); 1479 mIccRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null); 1480 } 1481 1482 private void unregisterForSimRecordEvents() { 1483 mIccRecords.unregisterForNetworkSelectionModeAutomatic(this); 1484 mIccRecords.unregisterForNewSms(this); 1485 mIccRecords.unregisterForRecordsEvents(this); 1486 mIccRecords.unregisterForRecordsLoaded(this); 1487 } 1488 1489 @Override 1490 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1491 pw.println("GSMPhone extends:"); 1492 super.dump(fd, pw, args); 1493 pw.println(" mCT=" + mCT); 1494 pw.println(" mSST=" + mSST); 1495 pw.println(" mPendingMMIs=" + mPendingMMIs); 1496 pw.println(" mSimPhoneBookIntManager=" + mSimPhoneBookIntManager); 1497 pw.println(" mSimSmsIntManager=" + mSimSmsIntManager); 1498 pw.println(" mSubInfo=" + mSubInfo); 1499 if (VDBG) pw.println(" mImei=" + mImei); 1500 if (VDBG) pw.println(" mImeiSv=" + mImeiSv); 1501 pw.println(" mVmNumber=" + mVmNumber); 1502 } 1503} 1504