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