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