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