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