1 /* 2 * Copyright (C) 2007 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 17 package com.android.internal.telephony; 18 19 import android.app.ActivityManagerNative; 20 import android.app.IActivityManager; 21 import android.content.Context; 22 import android.content.res.Configuration; 23 import android.content.SharedPreferences; 24 import android.net.LinkCapabilities; 25 import android.net.LinkProperties; 26 import android.net.wifi.WifiManager; 27 import android.os.AsyncResult; 28 import android.os.Handler; 29 import android.os.Looper; 30 import android.os.Message; 31 import android.os.RegistrantList; 32 import android.os.SystemProperties; 33 import android.preference.PreferenceManager; 34 import android.provider.Settings; 35 import android.telephony.ServiceState; 36 import android.text.TextUtils; 37 import android.util.Log; 38 39 import com.android.internal.R; 40 import com.android.internal.telephony.ims.IsimRecords; 41 import com.android.internal.telephony.test.SimulatedRadioControl; 42 import com.android.internal.telephony.gsm.SIMRecords; 43 import com.android.internal.telephony.gsm.SimCard; 44 45 import java.util.Locale; 46 47 48 /** 49 * (<em>Not for SDK use</em>) 50 * A base implementation for the com.android.internal.telephony.Phone interface. 51 * 52 * Note that implementations of Phone.java are expected to be used 53 * from a single application thread. This should be the same thread that 54 * originally called PhoneFactory to obtain the interface. 55 * 56 * {@hide} 57 * 58 */ 59 60 public abstract class PhoneBase extends Handler implements Phone { 61 private static final String LOG_TAG = "PHONE"; 62 private static final boolean LOCAL_DEBUG = true; 63 64 // Key used to read and write the saved network selection numeric value 65 public static final String NETWORK_SELECTION_KEY = "network_selection_key"; 66 // Key used to read and write the saved network selection operator name 67 public static final String NETWORK_SELECTION_NAME_KEY = "network_selection_name_key"; 68 69 70 // Key used to read/write "disable data connection on boot" pref (used for testing) 71 public static final String DATA_DISABLED_ON_BOOT_KEY = "disabled_on_boot_key"; 72 73 /* Event Constants */ 74 protected static final int EVENT_RADIO_AVAILABLE = 1; 75 /** Supplementary Service Notification received. */ 76 protected static final int EVENT_SSN = 2; 77 protected static final int EVENT_SIM_RECORDS_LOADED = 3; 78 protected static final int EVENT_MMI_DONE = 4; 79 protected static final int EVENT_RADIO_ON = 5; 80 protected static final int EVENT_GET_BASEBAND_VERSION_DONE = 6; 81 protected static final int EVENT_USSD = 7; 82 protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 8; 83 protected static final int EVENT_GET_IMEI_DONE = 9; 84 protected static final int EVENT_GET_IMEISV_DONE = 10; 85 protected static final int EVENT_GET_SIM_STATUS_DONE = 11; 86 protected static final int EVENT_SET_CALL_FORWARD_DONE = 12; 87 protected static final int EVENT_GET_CALL_FORWARD_DONE = 13; 88 protected static final int EVENT_CALL_RING = 14; 89 protected static final int EVENT_CALL_RING_CONTINUE = 15; 90 91 // Used to intercept the carrier selection calls so that 92 // we can save the values. 93 protected static final int EVENT_SET_NETWORK_MANUAL_COMPLETE = 16; 94 protected static final int EVENT_SET_NETWORK_AUTOMATIC_COMPLETE = 17; 95 protected static final int EVENT_SET_CLIR_COMPLETE = 18; 96 protected static final int EVENT_REGISTERED_TO_NETWORK = 19; 97 protected static final int EVENT_SET_VM_NUMBER_DONE = 20; 98 // Events for CDMA support 99 protected static final int EVENT_GET_DEVICE_IDENTITY_DONE = 21; 100 protected static final int EVENT_RUIM_RECORDS_LOADED = 22; 101 protected static final int EVENT_NV_READY = 23; 102 protected static final int EVENT_SET_ENHANCED_VP = 24; 103 protected static final int EVENT_EMERGENCY_CALLBACK_MODE_ENTER = 25; 104 protected static final int EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE = 26; 105 106 // Key used to read/write current CLIR setting 107 public static final String CLIR_KEY = "clir_key"; 108 109 // Key used to read/write "disable DNS server check" pref (used for testing) 110 public static final String DNS_SERVER_CHECK_DISABLED_KEY = "dns_server_check_disabled_key"; 111 112 /* Instance Variables */ 113 public CommandsInterface mCM; 114 protected IccFileHandler mIccFileHandler; 115 boolean mDnsCheckDisabled; 116 public DataConnectionTracker mDataConnectionTracker; 117 boolean mDoesRilSendMultipleCallRing; 118 int mCallRingContinueToken; 119 int mCallRingDelay; 120 public boolean mIsTheCurrentActivePhone = true; 121 boolean mIsVoiceCapable = true; 122 public IccRecords mIccRecords; 123 public IccCard mIccCard; 124 public SmsStorageMonitor mSmsStorageMonitor; 125 public SmsUsageMonitor mSmsUsageMonitor; 126 public SMSDispatcher mSMS; 127 128 /** 129 * Set a system property, unless we're in unit test mode 130 */ 131 public void 132 setSystemProperty(String property, String value) { 133 if(getUnitTestMode()) { 134 return; 135 } 136 SystemProperties.set(property, value); 137 } 138 139 140 protected final RegistrantList mPreciseCallStateRegistrants 141 = new RegistrantList(); 142 143 protected final RegistrantList mNewRingingConnectionRegistrants 144 = new RegistrantList(); 145 146 protected final RegistrantList mIncomingRingRegistrants 147 = new RegistrantList(); 148 149 protected final RegistrantList mDisconnectRegistrants 150 = new RegistrantList(); 151 152 protected final RegistrantList mServiceStateRegistrants 153 = new RegistrantList(); 154 155 protected final RegistrantList mMmiCompleteRegistrants 156 = new RegistrantList(); 157 158 protected final RegistrantList mMmiRegistrants 159 = new RegistrantList(); 160 161 protected final RegistrantList mUnknownConnectionRegistrants 162 = new RegistrantList(); 163 164 protected final RegistrantList mSuppServiceFailedRegistrants 165 = new RegistrantList(); 166 167 protected Looper mLooper; /* to insure registrants are in correct thread*/ 168 169 protected final Context mContext; 170 171 /** 172 * PhoneNotifier is an abstraction for all system-wide 173 * state change notification. DefaultPhoneNotifier is 174 * used here unless running we're inside a unit test. 175 */ 176 protected PhoneNotifier mNotifier; 177 178 protected SimulatedRadioControl mSimulatedRadioControl; 179 180 boolean mUnitTestMode; 181 182 /** 183 * Constructs a PhoneBase in normal (non-unit test) mode. 184 * 185 * @param context Context object from hosting application 186 * @param notifier An instance of DefaultPhoneNotifier, 187 * unless unit testing. 188 */ 189 protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci) { 190 this(notifier, context, ci, false); 191 } 192 193 /** 194 * Constructs a PhoneBase in normal (non-unit test) mode. 195 * 196 * @param context Context object from hosting application 197 * @param notifier An instance of DefaultPhoneNotifier, 198 * unless unit testing. 199 * @param unitTestMode when true, prevents notifications 200 * of state change events 201 */ 202 protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci, 203 boolean unitTestMode) { 204 this.mNotifier = notifier; 205 this.mContext = context; 206 mLooper = Looper.myLooper(); 207 mCM = ci; 208 209 setPropertiesByCarrier(); 210 211 setUnitTestMode(unitTestMode); 212 213 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); 214 mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false); 215 mCM.setOnCallRing(this, EVENT_CALL_RING, null); 216 217 /* "Voice capable" means that this device supports circuit-switched 218 * (i.e. voice) phone calls over the telephony network, and is allowed 219 * to display the in-call UI while a cellular voice call is active. 220 * This will be false on "data only" devices which can't make voice 221 * calls and don't support any in-call UI. 222 */ 223 mIsVoiceCapable = mContext.getResources().getBoolean( 224 com.android.internal.R.bool.config_voice_capable); 225 226 /** 227 * Some RIL's don't always send RIL_UNSOL_CALL_RING so it needs 228 * to be generated locally. Ideally all ring tones should be loops 229 * and this wouldn't be necessary. But to minimize changes to upper 230 * layers it is requested that it be generated by lower layers. 231 * 232 * By default old phones won't have the property set but do generate 233 * the RIL_UNSOL_CALL_RING so the default if there is no property is 234 * true. 235 */ 236 mDoesRilSendMultipleCallRing = SystemProperties.getBoolean( 237 TelephonyProperties.PROPERTY_RIL_SENDS_MULTIPLE_CALL_RING, true); 238 Log.d(LOG_TAG, "mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing); 239 240 mCallRingDelay = SystemProperties.getInt( 241 TelephonyProperties.PROPERTY_CALL_RING_DELAY, 3000); 242 Log.d(LOG_TAG, "mCallRingDelay=" + mCallRingDelay); 243 244 // Initialize device storage and outgoing SMS usage monitors for SMSDispatchers. 245 mSmsStorageMonitor = new SmsStorageMonitor(this); 246 mSmsUsageMonitor = new SmsUsageMonitor(context.getContentResolver()); 247 } 248 249 public void dispose() { 250 synchronized(PhoneProxy.lockForRadioTechnologyChange) { 251 mCM.unSetOnCallRing(this); 252 // Must cleanup all connectionS and needs to use sendMessage! 253 mDataConnectionTracker.cleanUpAllConnections(null); 254 mIsTheCurrentActivePhone = false; 255 // Dispose the SMS usage and storage monitors 256 mSmsStorageMonitor.dispose(); 257 mSmsUsageMonitor.dispose(); 258 } 259 } 260 261 public void removeReferences() { 262 mSmsStorageMonitor = null; 263 mSmsUsageMonitor = null; 264 } 265 266 /** 267 * When overridden the derived class needs to call 268 * super.handleMessage(msg) so this method has a 269 * a chance to process the message. 270 * 271 * @param msg 272 */ 273 @Override 274 public void handleMessage(Message msg) { 275 AsyncResult ar; 276 277 switch(msg.what) { 278 case EVENT_CALL_RING: 279 Log.d(LOG_TAG, "Event EVENT_CALL_RING Received state=" + getState()); 280 ar = (AsyncResult)msg.obj; 281 if (ar.exception == null) { 282 Phone.State state = getState(); 283 if ((!mDoesRilSendMultipleCallRing) 284 && ((state == Phone.State.RINGING) || (state == Phone.State.IDLE))) { 285 mCallRingContinueToken += 1; 286 sendIncomingCallRingNotification(mCallRingContinueToken); 287 } else { 288 notifyIncomingRing(); 289 } 290 } 291 break; 292 293 case EVENT_CALL_RING_CONTINUE: 294 Log.d(LOG_TAG, "Event EVENT_CALL_RING_CONTINUE Received stat=" + getState()); 295 if (getState() == Phone.State.RINGING) { 296 sendIncomingCallRingNotification(msg.arg1); 297 } 298 break; 299 300 default: 301 throw new RuntimeException("unexpected event not handled"); 302 } 303 } 304 305 // Inherited documentation suffices. 306 public Context getContext() { 307 return mContext; 308 } 309 310 /** 311 * Disables the DNS check (i.e., allows "0.0.0.0"). 312 * Useful for lab testing environment. 313 * @param b true disables the check, false enables. 314 */ 315 public void disableDnsCheck(boolean b) { 316 mDnsCheckDisabled = b; 317 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 318 SharedPreferences.Editor editor = sp.edit(); 319 editor.putBoolean(DNS_SERVER_CHECK_DISABLED_KEY, b); 320 editor.apply(); 321 } 322 323 /** 324 * Returns true if the DNS check is currently disabled. 325 */ 326 public boolean isDnsCheckDisabled() { 327 return mDnsCheckDisabled; 328 } 329 330 // Inherited documentation suffices. 331 public void registerForPreciseCallStateChanged(Handler h, int what, Object obj) { 332 checkCorrectThread(h); 333 334 mPreciseCallStateRegistrants.addUnique(h, what, obj); 335 } 336 337 // Inherited documentation suffices. 338 public void unregisterForPreciseCallStateChanged(Handler h) { 339 mPreciseCallStateRegistrants.remove(h); 340 } 341 342 /** 343 * Subclasses of Phone probably want to replace this with a 344 * version scoped to their packages 345 */ 346 protected void notifyPreciseCallStateChangedP() { 347 AsyncResult ar = new AsyncResult(null, this, null); 348 mPreciseCallStateRegistrants.notifyRegistrants(ar); 349 } 350 351 // Inherited documentation suffices. 352 public void registerForUnknownConnection(Handler h, int what, Object obj) { 353 checkCorrectThread(h); 354 355 mUnknownConnectionRegistrants.addUnique(h, what, obj); 356 } 357 358 // Inherited documentation suffices. 359 public void unregisterForUnknownConnection(Handler h) { 360 mUnknownConnectionRegistrants.remove(h); 361 } 362 363 // Inherited documentation suffices. 364 public void registerForNewRingingConnection( 365 Handler h, int what, Object obj) { 366 checkCorrectThread(h); 367 368 mNewRingingConnectionRegistrants.addUnique(h, what, obj); 369 } 370 371 // Inherited documentation suffices. 372 public void unregisterForNewRingingConnection(Handler h) { 373 mNewRingingConnectionRegistrants.remove(h); 374 } 375 376 // Inherited documentation suffices. 377 public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){ 378 mCM.registerForInCallVoicePrivacyOn(h,what,obj); 379 } 380 381 // Inherited documentation suffices. 382 public void unregisterForInCallVoicePrivacyOn(Handler h){ 383 mCM.unregisterForInCallVoicePrivacyOn(h); 384 } 385 386 // Inherited documentation suffices. 387 public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){ 388 mCM.registerForInCallVoicePrivacyOff(h,what,obj); 389 } 390 391 // Inherited documentation suffices. 392 public void unregisterForInCallVoicePrivacyOff(Handler h){ 393 mCM.unregisterForInCallVoicePrivacyOff(h); 394 } 395 396 // Inherited documentation suffices. 397 public void registerForIncomingRing( 398 Handler h, int what, Object obj) { 399 checkCorrectThread(h); 400 401 mIncomingRingRegistrants.addUnique(h, what, obj); 402 } 403 404 // Inherited documentation suffices. 405 public void unregisterForIncomingRing(Handler h) { 406 mIncomingRingRegistrants.remove(h); 407 } 408 409 // Inherited documentation suffices. 410 public void registerForDisconnect(Handler h, int what, Object obj) { 411 checkCorrectThread(h); 412 413 mDisconnectRegistrants.addUnique(h, what, obj); 414 } 415 416 // Inherited documentation suffices. 417 public void unregisterForDisconnect(Handler h) { 418 mDisconnectRegistrants.remove(h); 419 } 420 421 // Inherited documentation suffices. 422 public void registerForSuppServiceFailed(Handler h, int what, Object obj) { 423 checkCorrectThread(h); 424 425 mSuppServiceFailedRegistrants.addUnique(h, what, obj); 426 } 427 428 // Inherited documentation suffices. 429 public void unregisterForSuppServiceFailed(Handler h) { 430 mSuppServiceFailedRegistrants.remove(h); 431 } 432 433 // Inherited documentation suffices. 434 public void registerForMmiInitiate(Handler h, int what, Object obj) { 435 checkCorrectThread(h); 436 437 mMmiRegistrants.addUnique(h, what, obj); 438 } 439 440 // Inherited documentation suffices. 441 public void unregisterForMmiInitiate(Handler h) { 442 mMmiRegistrants.remove(h); 443 } 444 445 // Inherited documentation suffices. 446 public void registerForMmiComplete(Handler h, int what, Object obj) { 447 checkCorrectThread(h); 448 449 mMmiCompleteRegistrants.addUnique(h, what, obj); 450 } 451 452 // Inherited documentation suffices. 453 public void unregisterForMmiComplete(Handler h) { 454 checkCorrectThread(h); 455 456 mMmiCompleteRegistrants.remove(h); 457 } 458 459 /** 460 * Method to retrieve the saved operator id from the Shared Preferences 461 */ 462 private String getSavedNetworkSelection() { 463 // open the shared preferences and search with our key. 464 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 465 return sp.getString(NETWORK_SELECTION_KEY, ""); 466 } 467 468 /** 469 * Method to restore the previously saved operator id, or reset to 470 * automatic selection, all depending upon the value in the shared 471 * preferences. 472 */ 473 public void restoreSavedNetworkSelection(Message response) { 474 // retrieve the operator id 475 String networkSelection = getSavedNetworkSelection(); 476 477 // set to auto if the id is empty, otherwise select the network. 478 if (TextUtils.isEmpty(networkSelection)) { 479 mCM.setNetworkSelectionModeAutomatic(response); 480 } else { 481 mCM.setNetworkSelectionModeManual(networkSelection, response); 482 } 483 } 484 485 // Inherited documentation suffices. 486 public void setUnitTestMode(boolean f) { 487 mUnitTestMode = f; 488 } 489 490 // Inherited documentation suffices. 491 public boolean getUnitTestMode() { 492 return mUnitTestMode; 493 } 494 495 /** 496 * To be invoked when a voice call Connection disconnects. 497 * 498 * Subclasses of Phone probably want to replace this with a 499 * version scoped to their packages 500 */ 501 protected void notifyDisconnectP(Connection cn) { 502 AsyncResult ar = new AsyncResult(null, cn, null); 503 mDisconnectRegistrants.notifyRegistrants(ar); 504 } 505 506 // Inherited documentation suffices. 507 public void registerForServiceStateChanged( 508 Handler h, int what, Object obj) { 509 checkCorrectThread(h); 510 511 mServiceStateRegistrants.add(h, what, obj); 512 } 513 514 // Inherited documentation suffices. 515 public void unregisterForServiceStateChanged(Handler h) { 516 mServiceStateRegistrants.remove(h); 517 } 518 519 // Inherited documentation suffices. 520 public void registerForRingbackTone(Handler h, int what, Object obj) { 521 mCM.registerForRingbackTone(h,what,obj); 522 } 523 524 // Inherited documentation suffices. 525 public void unregisterForRingbackTone(Handler h) { 526 mCM.unregisterForRingbackTone(h); 527 } 528 529 // Inherited documentation suffices. 530 public void registerForResendIncallMute(Handler h, int what, Object obj) { 531 mCM.registerForResendIncallMute(h,what,obj); 532 } 533 534 // Inherited documentation suffices. 535 public void unregisterForResendIncallMute(Handler h) { 536 mCM.unregisterForResendIncallMute(h); 537 } 538 539 public void setEchoSuppressionEnabled(boolean enabled) { 540 // no need for regular phone 541 } 542 543 /** 544 * Subclasses of Phone probably want to replace this with a 545 * version scoped to their packages 546 */ 547 protected void notifyServiceStateChangedP(ServiceState ss) { 548 AsyncResult ar = new AsyncResult(null, ss, null); 549 mServiceStateRegistrants.notifyRegistrants(ar); 550 551 mNotifier.notifyServiceState(this); 552 } 553 554 // Inherited documentation suffices. 555 public SimulatedRadioControl getSimulatedRadioControl() { 556 return mSimulatedRadioControl; 557 } 558 559 /** 560 * Verifies the current thread is the same as the thread originally 561 * used in the initialization of this instance. Throws RuntimeException 562 * if not. 563 * 564 * @exception RuntimeException if the current thread is not 565 * the thread that originally obtained this PhoneBase instance. 566 */ 567 private void checkCorrectThread(Handler h) { 568 if (h.getLooper() != mLooper) { 569 throw new RuntimeException( 570 "com.android.internal.telephony.Phone must be used from within one thread"); 571 } 572 } 573 574 /** 575 * Set the properties by matching the carrier string in 576 * a string-array resource 577 */ 578 private void setPropertiesByCarrier() { 579 String carrier = SystemProperties.get("ro.carrier"); 580 581 if (null == carrier || 0 == carrier.length() || "unknown".equals(carrier)) { 582 return; 583 } 584 585 CharSequence[] carrierLocales = mContext. 586 getResources().getTextArray(R.array.carrier_properties); 587 588 for (int i = 0; i < carrierLocales.length; i+=3) { 589 String c = carrierLocales[i].toString(); 590 if (carrier.equals(c)) { 591 String l = carrierLocales[i+1].toString(); 592 593 String language = l.substring(0, 2); 594 String country = ""; 595 if (l.length() >=5) { 596 country = l.substring(3, 5); 597 } 598 setSystemLocale(language, country, false); 599 600 if (!country.isEmpty()) { 601 try { 602 Settings.Secure.getInt(mContext.getContentResolver(), 603 Settings.Secure.WIFI_COUNTRY_CODE); 604 } catch (Settings.SettingNotFoundException e) { 605 // note this is not persisting 606 WifiManager wM = (WifiManager) 607 mContext.getSystemService(Context.WIFI_SERVICE); 608 wM.setCountryCode(country, false); 609 } 610 } 611 return; 612 } 613 } 614 } 615 616 /** 617 * Utility code to set the system locale if it's not set already 618 * @param language Two character language code desired 619 * @param country Two character country code desired 620 * @param fromMcc Indicating whether the locale is set according to MCC table. 621 * This flag wil be ignored by default implementation. 622 * TODO: Use a source enumeration so that source of the locale 623 * can be prioritized. 624 * 625 * {@hide} 626 */ 627 public void setSystemLocale(String language, String country, boolean fromMcc) { 628 String l = SystemProperties.get("persist.sys.language"); 629 String c = SystemProperties.get("persist.sys.country"); 630 631 if (null == language) { 632 return; // no match possible 633 } 634 language = language.toLowerCase(); 635 if (null == country) { 636 country = ""; 637 } 638 country = country.toUpperCase(); 639 640 if((null == l || 0 == l.length()) && (null == c || 0 == c.length())) { 641 try { 642 // try to find a good match 643 String[] locales = mContext.getAssets().getLocales(); 644 final int N = locales.length; 645 String bestMatch = null; 646 for(int i = 0; i < N; i++) { 647 // only match full (lang + country) locales 648 if (locales[i]!=null && locales[i].length() >= 5 && 649 locales[i].substring(0,2).equals(language)) { 650 if (locales[i].substring(3,5).equals(country)) { 651 bestMatch = locales[i]; 652 break; 653 } else if (null == bestMatch) { 654 bestMatch = locales[i]; 655 } 656 } 657 } 658 if (null != bestMatch) { 659 IActivityManager am = ActivityManagerNative.getDefault(); 660 Configuration config = am.getConfiguration(); 661 config.locale = new Locale(bestMatch.substring(0,2), 662 bestMatch.substring(3,5)); 663 config.userSetLocale = true; 664 am.updateConfiguration(config); 665 } 666 } catch (Exception e) { 667 // Intentionally left blank 668 } 669 } 670 } 671 672 /** 673 * Get state 674 */ 675 public abstract Phone.State getState(); 676 677 /** 678 * Retrieves the IccFileHandler of the Phone instance 679 */ 680 public abstract IccFileHandler getIccFileHandler(); 681 682 /* 683 * Retrieves the Handler of the Phone instance 684 */ 685 public Handler getHandler() { 686 return this; 687 } 688 689 /** 690 * Retrieves the ServiceStateTracker of the phone instance. 691 */ 692 public ServiceStateTracker getServiceStateTracker() { 693 return null; 694 } 695 696 /** 697 * Get call tracker 698 */ 699 public CallTracker getCallTracker() { 700 return null; 701 } 702 703 @Override 704 public IccCard getIccCard() { 705 return mIccCard; 706 } 707 708 @Override 709 public String getIccSerialNumber() { 710 return mIccRecords.iccid; 711 } 712 713 @Override 714 public boolean getIccRecordsLoaded() { 715 return mIccRecords.getRecordsLoaded(); 716 } 717 718 @Override 719 public boolean getMessageWaitingIndicator() { 720 return mIccRecords.getVoiceMessageWaiting(); 721 } 722 723 @Override 724 public boolean getCallForwardingIndicator() { 725 return mIccRecords.getVoiceCallForwardingFlag(); 726 } 727 728 /** 729 * Query the status of the CDMA roaming preference 730 */ 731 public void queryCdmaRoamingPreference(Message response) { 732 mCM.queryCdmaRoamingPreference(response); 733 } 734 735 /** 736 * Set the status of the CDMA roaming preference 737 */ 738 public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) { 739 mCM.setCdmaRoamingPreference(cdmaRoamingType, response); 740 } 741 742 /** 743 * Set the status of the CDMA subscription mode 744 */ 745 public void setCdmaSubscription(int cdmaSubscriptionType, Message response) { 746 mCM.setCdmaSubscriptionSource(cdmaSubscriptionType, response); 747 } 748 749 /** 750 * Set the preferred Network Type: Global, CDMA only or GSM/UMTS only 751 */ 752 public void setPreferredNetworkType(int networkType, Message response) { 753 mCM.setPreferredNetworkType(networkType, response); 754 } 755 756 public void getPreferredNetworkType(Message response) { 757 mCM.getPreferredNetworkType(response); 758 } 759 760 public void getSmscAddress(Message result) { 761 mCM.getSmscAddress(result); 762 } 763 764 public void setSmscAddress(String address, Message result) { 765 mCM.setSmscAddress(address, result); 766 } 767 768 public void setTTYMode(int ttyMode, Message onComplete) { 769 mCM.setTTYMode(ttyMode, onComplete); 770 } 771 772 public void queryTTYMode(Message onComplete) { 773 mCM.queryTTYMode(onComplete); 774 } 775 776 public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) { 777 // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. 778 logUnexpectedCdmaMethodCall("enableEnhancedVoicePrivacy"); 779 } 780 781 public void getEnhancedVoicePrivacy(Message onComplete) { 782 // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. 783 logUnexpectedCdmaMethodCall("getEnhancedVoicePrivacy"); 784 } 785 786 public void setBandMode(int bandMode, Message response) { 787 mCM.setBandMode(bandMode, response); 788 } 789 790 public void queryAvailableBandMode(Message response) { 791 mCM.queryAvailableBandMode(response); 792 } 793 794 public void invokeOemRilRequestRaw(byte[] data, Message response) { 795 mCM.invokeOemRilRequestRaw(data, response); 796 } 797 798 public void invokeOemRilRequestStrings(String[] strings, Message response) { 799 mCM.invokeOemRilRequestStrings(strings, response); 800 } 801 802 public void notifyDataActivity() { 803 mNotifier.notifyDataActivity(this); 804 } 805 806 public void notifyMessageWaitingIndicator() { 807 // Do not notify voice mail waiting if device doesn't support voice 808 if (!mIsVoiceCapable) 809 return; 810 811 // This function is added to send the notification to DefaultPhoneNotifier. 812 mNotifier.notifyMessageWaitingChanged(this); 813 } 814 815 public void notifyDataConnection(String reason, String apnType, 816 Phone.DataState state) { 817 mNotifier.notifyDataConnection(this, reason, apnType, state); 818 } 819 820 public void notifyDataConnection(String reason, String apnType) { 821 mNotifier.notifyDataConnection(this, reason, apnType, getDataConnectionState(apnType)); 822 } 823 824 public void notifyDataConnection(String reason) { 825 String types[] = getActiveApnTypes(); 826 for (String apnType : types) { 827 mNotifier.notifyDataConnection(this, reason, apnType, getDataConnectionState(apnType)); 828 } 829 } 830 831 public void notifyOtaspChanged(int otaspMode) { 832 mNotifier.notifyOtaspChanged(this, otaspMode); 833 } 834 835 /** 836 * @return true if a mobile originating emergency call is active 837 */ 838 public boolean isInEmergencyCall() { 839 return false; 840 } 841 842 /** 843 * @return true if we are in the emergency call back mode. This is a period where 844 * the phone should be using as little power as possible and be ready to receive an 845 * incoming call from the emergency operator. 846 */ 847 public boolean isInEcm() { 848 return false; 849 } 850 851 public abstract String getPhoneName(); 852 853 public abstract int getPhoneType(); 854 855 /** @hide */ 856 public int getVoiceMessageCount(){ 857 return 0; 858 } 859 860 /** 861 * Returns the CDMA ERI icon index to display 862 */ 863 public int getCdmaEriIconIndex() { 864 logUnexpectedCdmaMethodCall("getCdmaEriIconIndex"); 865 return -1; 866 } 867 868 /** 869 * Returns the CDMA ERI icon mode, 870 * 0 - ON 871 * 1 - FLASHING 872 */ 873 public int getCdmaEriIconMode() { 874 logUnexpectedCdmaMethodCall("getCdmaEriIconMode"); 875 return -1; 876 } 877 878 /** 879 * Returns the CDMA ERI text, 880 */ 881 public String getCdmaEriText() { 882 logUnexpectedCdmaMethodCall("getCdmaEriText"); 883 return "GSM nw, no ERI"; 884 } 885 886 public String getCdmaMin() { 887 // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. 888 logUnexpectedCdmaMethodCall("getCdmaMin"); 889 return null; 890 } 891 892 public boolean isMinInfoReady() { 893 // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. 894 logUnexpectedCdmaMethodCall("isMinInfoReady"); 895 return false; 896 } 897 898 public String getCdmaPrlVersion(){ 899 // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. 900 logUnexpectedCdmaMethodCall("getCdmaPrlVersion"); 901 return null; 902 } 903 904 public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) { 905 // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. 906 logUnexpectedCdmaMethodCall("sendBurstDtmf"); 907 } 908 909 public void exitEmergencyCallbackMode() { 910 // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. 911 logUnexpectedCdmaMethodCall("exitEmergencyCallbackMode"); 912 } 913 914 public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) { 915 // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. 916 logUnexpectedCdmaMethodCall("registerForCdmaOtaStatusChange"); 917 } 918 919 public void unregisterForCdmaOtaStatusChange(Handler h) { 920 // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. 921 logUnexpectedCdmaMethodCall("unregisterForCdmaOtaStatusChange"); 922 } 923 924 public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) { 925 // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. 926 logUnexpectedCdmaMethodCall("registerForSubscriptionInfoReady"); 927 } 928 929 public void unregisterForSubscriptionInfoReady(Handler h) { 930 // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. 931 logUnexpectedCdmaMethodCall("unregisterForSubscriptionInfoReady"); 932 } 933 934 /** 935 * Returns true if OTA Service Provisioning needs to be performed. 936 * If not overridden return false. 937 */ 938 public boolean needsOtaServiceProvisioning() { 939 return false; 940 } 941 942 /** 943 * Return true if number is an OTASP number. 944 * If not overridden return false. 945 */ 946 public boolean isOtaSpNumber(String dialStr) { 947 return false; 948 } 949 950 public void registerForCallWaiting(Handler h, int what, Object obj){ 951 // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. 952 logUnexpectedCdmaMethodCall("registerForCallWaiting"); 953 } 954 955 public void unregisterForCallWaiting(Handler h){ 956 // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. 957 logUnexpectedCdmaMethodCall("unregisterForCallWaiting"); 958 } 959 960 public void registerForEcmTimerReset(Handler h, int what, Object obj) { 961 // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. 962 logUnexpectedCdmaMethodCall("registerForEcmTimerReset"); 963 } 964 965 public void unregisterForEcmTimerReset(Handler h) { 966 // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. 967 logUnexpectedCdmaMethodCall("unregisterForEcmTimerReset"); 968 } 969 970 public void registerForSignalInfo(Handler h, int what, Object obj) { 971 mCM.registerForSignalInfo(h, what, obj); 972 } 973 974 public void unregisterForSignalInfo(Handler h) { 975 mCM.unregisterForSignalInfo(h); 976 } 977 978 public void registerForDisplayInfo(Handler h, int what, Object obj) { 979 mCM.registerForDisplayInfo(h, what, obj); 980 } 981 982 public void unregisterForDisplayInfo(Handler h) { 983 mCM.unregisterForDisplayInfo(h); 984 } 985 986 public void registerForNumberInfo(Handler h, int what, Object obj) { 987 mCM.registerForNumberInfo(h, what, obj); 988 } 989 990 public void unregisterForNumberInfo(Handler h) { 991 mCM.unregisterForNumberInfo(h); 992 } 993 994 public void registerForRedirectedNumberInfo(Handler h, int what, Object obj) { 995 mCM.registerForRedirectedNumberInfo(h, what, obj); 996 } 997 998 public void unregisterForRedirectedNumberInfo(Handler h) { 999 mCM.unregisterForRedirectedNumberInfo(h); 1000 } 1001 1002 public void registerForLineControlInfo(Handler h, int what, Object obj) { 1003 mCM.registerForLineControlInfo( h, what, obj); 1004 } 1005 1006 public void unregisterForLineControlInfo(Handler h) { 1007 mCM.unregisterForLineControlInfo(h); 1008 } 1009 1010 public void registerFoT53ClirlInfo(Handler h, int what, Object obj) { 1011 mCM.registerFoT53ClirlInfo(h, what, obj); 1012 } 1013 1014 public void unregisterForT53ClirInfo(Handler h) { 1015 mCM.unregisterForT53ClirInfo(h); 1016 } 1017 1018 public void registerForT53AudioControlInfo(Handler h, int what, Object obj) { 1019 mCM.registerForT53AudioControlInfo( h, what, obj); 1020 } 1021 1022 public void unregisterForT53AudioControlInfo(Handler h) { 1023 mCM.unregisterForT53AudioControlInfo(h); 1024 } 1025 1026 public void setOnEcbModeExitResponse(Handler h, int what, Object obj){ 1027 // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. 1028 logUnexpectedCdmaMethodCall("setOnEcbModeExitResponse"); 1029 } 1030 1031 public void unsetOnEcbModeExitResponse(Handler h){ 1032 // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. 1033 logUnexpectedCdmaMethodCall("unsetOnEcbModeExitResponse"); 1034 } 1035 1036 public String[] getActiveApnTypes() { 1037 return mDataConnectionTracker.getActiveApnTypes(); 1038 } 1039 1040 public String getActiveApnHost(String apnType) { 1041 return mDataConnectionTracker.getActiveApnString(apnType); 1042 } 1043 1044 public LinkProperties getLinkProperties(String apnType) { 1045 return mDataConnectionTracker.getLinkProperties(apnType); 1046 } 1047 1048 public LinkCapabilities getLinkCapabilities(String apnType) { 1049 return mDataConnectionTracker.getLinkCapabilities(apnType); 1050 } 1051 1052 public int enableApnType(String type) { 1053 return mDataConnectionTracker.enableApnType(type); 1054 } 1055 1056 public int disableApnType(String type) { 1057 return mDataConnectionTracker.disableApnType(type); 1058 } 1059 1060 public boolean isDataConnectivityPossible() { 1061 return isDataConnectivityPossible(Phone.APN_TYPE_DEFAULT); 1062 } 1063 1064 public boolean isDataConnectivityPossible(String apnType) { 1065 return ((mDataConnectionTracker != null) && 1066 (mDataConnectionTracker.isDataPossible(apnType))); 1067 } 1068 1069 /** 1070 * Notify registrants of a new ringing Connection. 1071 * Subclasses of Phone probably want to replace this with a 1072 * version scoped to their packages 1073 */ 1074 protected void notifyNewRingingConnectionP(Connection cn) { 1075 if (!mIsVoiceCapable) 1076 return; 1077 AsyncResult ar = new AsyncResult(null, cn, null); 1078 mNewRingingConnectionRegistrants.notifyRegistrants(ar); 1079 } 1080 1081 /** 1082 * Notify registrants of a RING event. 1083 */ 1084 private void notifyIncomingRing() { 1085 if (!mIsVoiceCapable) 1086 return; 1087 AsyncResult ar = new AsyncResult(null, this, null); 1088 mIncomingRingRegistrants.notifyRegistrants(ar); 1089 } 1090 1091 /** 1092 * Send the incoming call Ring notification if conditions are right. 1093 */ 1094 private void sendIncomingCallRingNotification(int token) { 1095 if (mIsVoiceCapable && !mDoesRilSendMultipleCallRing && 1096 (token == mCallRingContinueToken)) { 1097 Log.d(LOG_TAG, "Sending notifyIncomingRing"); 1098 notifyIncomingRing(); 1099 sendMessageDelayed( 1100 obtainMessage(EVENT_CALL_RING_CONTINUE, token, 0), mCallRingDelay); 1101 } else { 1102 Log.d(LOG_TAG, "Ignoring ring notification request," 1103 + " mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing 1104 + " token=" + token 1105 + " mCallRingContinueToken=" + mCallRingContinueToken 1106 + " mIsVoiceCapable=" + mIsVoiceCapable); 1107 } 1108 } 1109 1110 public boolean isCspPlmnEnabled() { 1111 // This function should be overridden by the class GSMPhone. 1112 // Not implemented in CDMAPhone. 1113 logUnexpectedGsmMethodCall("isCspPlmnEnabled"); 1114 return false; 1115 } 1116 1117 public IsimRecords getIsimRecords() { 1118 Log.e(LOG_TAG, "getIsimRecords() is only supported on LTE devices"); 1119 return null; 1120 } 1121 1122 public void requestIsimAuthentication(String nonce, Message result) { 1123 Log.e(LOG_TAG, "requestIsimAuthentication() is only supported on LTE devices"); 1124 } 1125 1126 public String getMsisdn() { 1127 logUnexpectedGsmMethodCall("getMsisdn"); 1128 return null; 1129 } 1130 1131 /** 1132 * Common error logger method for unexpected calls to CDMA-only methods. 1133 */ 1134 private static void logUnexpectedCdmaMethodCall(String name) 1135 { 1136 Log.e(LOG_TAG, "Error! " + name + "() in PhoneBase should not be " + 1137 "called, CDMAPhone inactive."); 1138 } 1139 1140 public DataState getDataConnectionState() { 1141 return getDataConnectionState(APN_TYPE_DEFAULT); 1142 } 1143 1144 /** 1145 * Common error logger method for unexpected calls to GSM/WCDMA-only methods. 1146 */ 1147 private static void logUnexpectedGsmMethodCall(String name) { 1148 Log.e(LOG_TAG, "Error! " + name + "() in PhoneBase should not be " + 1149 "called, GSMPhone inactive."); 1150 } 1151 1152 // Called by SimRecords which is constructed with a PhoneBase instead of a GSMPhone. 1153 public void notifyCallForwardingIndicator() { 1154 // This function should be overridden by the class GSMPhone. Not implemented in CDMAPhone. 1155 Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone."); 1156 } 1157 1158 public void notifyDataConnectionFailed(String reason, String apnType) { 1159 mNotifier.notifyDataConnectionFailed(this, reason, apnType); 1160 } 1161 1162 /** 1163 * {@inheritDoc} 1164 */ 1165 @Override 1166 public int getLteOnCdmaMode() { 1167 return mCM.getLteOnCdmaMode(); 1168 } 1169 1170 /** 1171 * Sets the SIM voice message waiting indicator records. 1172 * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported 1173 * @param countWaiting The number of messages waiting, if known. Use 1174 * -1 to indicate that an unknown number of 1175 * messages are waiting 1176 */ 1177 @Override 1178 public void setVoiceMessageWaiting(int line, int countWaiting) { 1179 mIccRecords.setVoiceMessageWaiting(line, countWaiting); 1180 } 1181 } 1182