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