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