1 /* 2 * Copyright (C) 2010 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 com.android.internal.telephony.sip.SipPhone; 20 21 import android.content.Context; 22 import android.os.AsyncResult; 23 import android.os.Handler; 24 import android.os.Message; 25 import android.os.RegistrantList; 26 import android.os.Registrant; 27 import android.telecom.VideoProfile; 28 import android.telephony.PhoneNumberUtils; 29 import android.telephony.TelephonyManager; 30 import android.telephony.PhoneStateListener; 31 import android.telephony.ServiceState; 32 import android.telephony.Rlog; 33 34 import java.util.ArrayList; 35 import java.util.Collections; 36 import java.util.HashMap; 37 import java.util.List; 38 39 40 41 /** 42 * @hide 43 * 44 * CallManager class provides an abstract layer for PhoneApp to access 45 * and control calls. It implements Phone interface. 46 * 47 * CallManager provides call and connection control as well as 48 * channel capability. 49 * 50 * There are three categories of APIs CallManager provided 51 * 52 * 1. Call control and operation, such as dial() and hangup() 53 * 2. Channel capabilities, such as CanConference() 54 * 3. Register notification 55 * 56 * 57 */ 58 public class CallManager { 59 60 private static final String LOG_TAG ="CallManager"; 61 private static final boolean DBG = true; 62 private static final boolean VDBG = false; 63 64 private static final int EVENT_DISCONNECT = 100; 65 private static final int EVENT_PRECISE_CALL_STATE_CHANGED = 101; 66 private static final int EVENT_NEW_RINGING_CONNECTION = 102; 67 private static final int EVENT_UNKNOWN_CONNECTION = 103; 68 private static final int EVENT_INCOMING_RING = 104; 69 private static final int EVENT_RINGBACK_TONE = 105; 70 private static final int EVENT_IN_CALL_VOICE_PRIVACY_ON = 106; 71 private static final int EVENT_IN_CALL_VOICE_PRIVACY_OFF = 107; 72 private static final int EVENT_CALL_WAITING = 108; 73 private static final int EVENT_DISPLAY_INFO = 109; 74 private static final int EVENT_SIGNAL_INFO = 110; 75 private static final int EVENT_CDMA_OTA_STATUS_CHANGE = 111; 76 private static final int EVENT_RESEND_INCALL_MUTE = 112; 77 private static final int EVENT_MMI_INITIATE = 113; 78 private static final int EVENT_MMI_COMPLETE = 114; 79 private static final int EVENT_ECM_TIMER_RESET = 115; 80 private static final int EVENT_SUBSCRIPTION_INFO_READY = 116; 81 private static final int EVENT_SUPP_SERVICE_FAILED = 117; 82 private static final int EVENT_SERVICE_STATE_CHANGED = 118; 83 private static final int EVENT_POST_DIAL_CHARACTER = 119; 84 private static final int EVENT_ONHOLD_TONE = 120; 85 // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L. 86 //private static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 121; 87 private static final int EVENT_TTY_MODE_RECEIVED = 122; 88 89 // Singleton instance 90 private static final CallManager INSTANCE = new CallManager(); 91 92 // list of registered phones, which are Phone objs 93 private final ArrayList<Phone> mPhones; 94 95 // list of supported ringing calls 96 private final ArrayList<Call> mRingingCalls; 97 98 // list of supported background calls 99 private final ArrayList<Call> mBackgroundCalls; 100 101 // list of supported foreground calls 102 private final ArrayList<Call> mForegroundCalls; 103 104 // empty connection list 105 private final ArrayList<Connection> mEmptyConnections = new ArrayList<Connection>(); 106 107 // mapping of phones to registered handler instances used for callbacks from RIL 108 private final HashMap<Phone, CallManagerHandler> mHandlerMap = new HashMap<>(); 109 110 // default phone as the first phone registered, which is Phone obj 111 private Phone mDefaultPhone; 112 113 private boolean mSpeedUpAudioForMtCall = false; 114 // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L. 115 //private boolean mIsEccDialing = false; 116 117 private Object mRegistrantidentifier = new Object(); 118 119 // state registrants 120 protected final RegistrantList mPreciseCallStateRegistrants 121 = new RegistrantList(); 122 123 protected final RegistrantList mNewRingingConnectionRegistrants 124 = new RegistrantList(); 125 126 protected final RegistrantList mIncomingRingRegistrants 127 = new RegistrantList(); 128 129 protected final RegistrantList mDisconnectRegistrants 130 = new RegistrantList(); 131 132 protected final RegistrantList mMmiRegistrants 133 = new RegistrantList(); 134 135 protected final RegistrantList mUnknownConnectionRegistrants 136 = new RegistrantList(); 137 138 protected final RegistrantList mRingbackToneRegistrants 139 = new RegistrantList(); 140 141 protected final RegistrantList mOnHoldToneRegistrants 142 = new RegistrantList(); 143 144 protected final RegistrantList mInCallVoicePrivacyOnRegistrants 145 = new RegistrantList(); 146 147 protected final RegistrantList mInCallVoicePrivacyOffRegistrants 148 = new RegistrantList(); 149 150 protected final RegistrantList mCallWaitingRegistrants 151 = new RegistrantList(); 152 153 protected final RegistrantList mDisplayInfoRegistrants 154 = new RegistrantList(); 155 156 protected final RegistrantList mSignalInfoRegistrants 157 = new RegistrantList(); 158 159 protected final RegistrantList mCdmaOtaStatusChangeRegistrants 160 = new RegistrantList(); 161 162 protected final RegistrantList mResendIncallMuteRegistrants 163 = new RegistrantList(); 164 165 protected final RegistrantList mMmiInitiateRegistrants 166 = new RegistrantList(); 167 168 protected final RegistrantList mMmiCompleteRegistrants 169 = new RegistrantList(); 170 171 protected final RegistrantList mEcmTimerResetRegistrants 172 = new RegistrantList(); 173 174 protected final RegistrantList mSubscriptionInfoReadyRegistrants 175 = new RegistrantList(); 176 177 protected final RegistrantList mSuppServiceFailedRegistrants 178 = new RegistrantList(); 179 180 protected final RegistrantList mServiceStateChangedRegistrants 181 = new RegistrantList(); 182 183 protected final RegistrantList mPostDialCharacterRegistrants 184 = new RegistrantList(); 185 186 protected final RegistrantList mTtyModeReceivedRegistrants 187 = new RegistrantList(); 188 CallManager()189 private CallManager() { 190 mPhones = new ArrayList<Phone>(); 191 mRingingCalls = new ArrayList<Call>(); 192 mBackgroundCalls = new ArrayList<Call>(); 193 mForegroundCalls = new ArrayList<Call>(); 194 mDefaultPhone = null; 195 } 196 197 /** 198 * get singleton instance of CallManager 199 * @return CallManager 200 */ getInstance()201 public static CallManager getInstance() { 202 return INSTANCE; 203 } 204 205 /** 206 * Returns all the registered phone objects. 207 * @return all the registered phone objects. 208 */ getAllPhones()209 public List<Phone> getAllPhones() { 210 return Collections.unmodifiableList(mPhones); 211 } 212 213 /** 214 * get Phone object corresponds to subId 215 * @return Phone 216 */ getPhone(int subId)217 private Phone getPhone(int subId) { 218 Phone p = null; 219 for (Phone phone : mPhones) { 220 if (phone.getSubId() == subId && 221 phone.getPhoneType() != PhoneConstants.PHONE_TYPE_IMS) { 222 p = phone; 223 break; 224 } 225 } 226 return p; 227 } 228 229 /** 230 * Get current coarse-grained voice call state. 231 * If the Call Manager has an active call and call waiting occurs, 232 * then the phone state is RINGING not OFFHOOK 233 * 234 */ getState()235 public PhoneConstants.State getState() { 236 PhoneConstants.State s = PhoneConstants.State.IDLE; 237 238 for (Phone phone : mPhones) { 239 if (phone.getState() == PhoneConstants.State.RINGING) { 240 s = PhoneConstants.State.RINGING; 241 } else if (phone.getState() == PhoneConstants.State.OFFHOOK) { 242 if (s == PhoneConstants.State.IDLE) s = PhoneConstants.State.OFFHOOK; 243 } 244 } 245 return s; 246 } 247 248 /** 249 * Get current coarse-grained voice call state on a subId. 250 * If the Call Manager has an active call and call waiting occurs, 251 * then the phone state is RINGING not OFFHOOK 252 * 253 */ getState(int subId)254 public PhoneConstants.State getState(int subId) { 255 PhoneConstants.State s = PhoneConstants.State.IDLE; 256 257 for (Phone phone : mPhones) { 258 if (phone.getSubId() == subId) { 259 if (phone.getState() == PhoneConstants.State.RINGING) { 260 s = PhoneConstants.State.RINGING; 261 } else if (phone.getState() == PhoneConstants.State.OFFHOOK) { 262 if (s == PhoneConstants.State.IDLE) s = PhoneConstants.State.OFFHOOK; 263 } 264 } 265 } 266 return s; 267 } 268 269 /** 270 * @return the service state of CallManager, which represents the 271 * highest priority state of all the service states of phones 272 * 273 * The priority is defined as 274 * 275 * STATE_IN_SERIVCE > STATE_OUT_OF_SERIVCE > STATE_EMERGENCY > STATE_POWER_OFF 276 * 277 */ 278 getServiceState()279 public int getServiceState() { 280 int resultState = ServiceState.STATE_OUT_OF_SERVICE; 281 282 for (Phone phone : mPhones) { 283 int serviceState = phone.getServiceState().getState(); 284 if (serviceState == ServiceState.STATE_IN_SERVICE) { 285 // IN_SERVICE has the highest priority 286 resultState = serviceState; 287 break; 288 } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE) { 289 // OUT_OF_SERVICE replaces EMERGENCY_ONLY and POWER_OFF 290 // Note: EMERGENCY_ONLY is not in use at this moment 291 if ( resultState == ServiceState.STATE_EMERGENCY_ONLY || 292 resultState == ServiceState.STATE_POWER_OFF) { 293 resultState = serviceState; 294 } 295 } else if (serviceState == ServiceState.STATE_EMERGENCY_ONLY) { 296 if (resultState == ServiceState.STATE_POWER_OFF) { 297 resultState = serviceState; 298 } 299 } 300 } 301 return resultState; 302 } 303 304 /** 305 * @return the Phone service state corresponds to subId 306 */ getServiceState(int subId)307 public int getServiceState(int subId) { 308 int resultState = ServiceState.STATE_OUT_OF_SERVICE; 309 310 for (Phone phone : mPhones) { 311 if (phone.getSubId() == subId) { 312 int serviceState = phone.getServiceState().getState(); 313 if (serviceState == ServiceState.STATE_IN_SERVICE) { 314 // IN_SERVICE has the highest priority 315 resultState = serviceState; 316 break; 317 } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE) { 318 // OUT_OF_SERVICE replaces EMERGENCY_ONLY and POWER_OFF 319 // Note: EMERGENCY_ONLY is not in use at this moment 320 if ( resultState == ServiceState.STATE_EMERGENCY_ONLY || 321 resultState == ServiceState.STATE_POWER_OFF) { 322 resultState = serviceState; 323 } 324 } else if (serviceState == ServiceState.STATE_EMERGENCY_ONLY) { 325 if (resultState == ServiceState.STATE_POWER_OFF) { 326 resultState = serviceState; 327 } 328 } 329 } 330 } 331 return resultState; 332 } 333 334 /** 335 * @return the phone associated with any call 336 */ getPhoneInCall()337 public Phone getPhoneInCall() { 338 Phone phone = null; 339 if (!getFirstActiveRingingCall().isIdle()) { 340 phone = getFirstActiveRingingCall().getPhone(); 341 } else if (!getActiveFgCall().isIdle()) { 342 phone = getActiveFgCall().getPhone(); 343 } else { 344 // If BG call is idle, we return default phone 345 phone = getFirstActiveBgCall().getPhone(); 346 } 347 return phone; 348 } 349 getPhoneInCall(int subId)350 public Phone getPhoneInCall(int subId) { 351 Phone phone = null; 352 if (!getFirstActiveRingingCall(subId).isIdle()) { 353 phone = getFirstActiveRingingCall(subId).getPhone(); 354 } else if (!getActiveFgCall(subId).isIdle()) { 355 phone = getActiveFgCall(subId).getPhone(); 356 } else { 357 // If BG call is idle, we return default phone 358 phone = getFirstActiveBgCall(subId).getPhone(); 359 } 360 return phone; 361 } 362 363 /** 364 * Register phone to CallManager 365 * @param phone to be registered 366 * @return true if register successfully 367 */ registerPhone(Phone phone)368 public boolean registerPhone(Phone phone) { 369 if (phone != null && !mPhones.contains(phone)) { 370 371 if (DBG) { 372 Rlog.d(LOG_TAG, "registerPhone(" + 373 phone.getPhoneName() + " " + phone + ")"); 374 } 375 376 if (mPhones.isEmpty()) { 377 mDefaultPhone = phone; 378 } 379 mPhones.add(phone); 380 mRingingCalls.add(phone.getRingingCall()); 381 mBackgroundCalls.add(phone.getBackgroundCall()); 382 mForegroundCalls.add(phone.getForegroundCall()); 383 registerForPhoneStates(phone); 384 return true; 385 } 386 return false; 387 } 388 389 /** 390 * unregister phone from CallManager 391 * @param phone to be unregistered 392 */ unregisterPhone(Phone phone)393 public void unregisterPhone(Phone phone) { 394 if (phone != null && mPhones.contains(phone)) { 395 396 if (DBG) { 397 Rlog.d(LOG_TAG, "unregisterPhone(" + 398 phone.getPhoneName() + " " + phone + ")"); 399 } 400 401 Phone imsPhone = phone.getImsPhone(); 402 if (imsPhone != null) { 403 unregisterPhone(imsPhone); 404 } 405 406 mPhones.remove(phone); 407 mRingingCalls.remove(phone.getRingingCall()); 408 mBackgroundCalls.remove(phone.getBackgroundCall()); 409 mForegroundCalls.remove(phone.getForegroundCall()); 410 unregisterForPhoneStates(phone); 411 if (phone == mDefaultPhone) { 412 if (mPhones.isEmpty()) { 413 mDefaultPhone = null; 414 } else { 415 mDefaultPhone = mPhones.get(0); 416 } 417 } 418 } 419 } 420 421 /** 422 * return the default phone or null if no phone available 423 */ getDefaultPhone()424 public Phone getDefaultPhone() { 425 return mDefaultPhone; 426 } 427 428 /** 429 * @return the phone associated with the foreground call 430 */ getFgPhone()431 public Phone getFgPhone() { 432 return getActiveFgCall().getPhone(); 433 } 434 435 /** 436 * @return the phone associated with the foreground call 437 * of a particular subId 438 */ getFgPhone(int subId)439 public Phone getFgPhone(int subId) { 440 return getActiveFgCall(subId).getPhone(); 441 } 442 443 /** 444 * @return the phone associated with the background call 445 */ getBgPhone()446 public Phone getBgPhone() { 447 return getFirstActiveBgCall().getPhone(); 448 } 449 450 /** 451 * @return the phone associated with the background call 452 * of a particular subId 453 */ getBgPhone(int subId)454 public Phone getBgPhone(int subId) { 455 return getFirstActiveBgCall(subId).getPhone(); 456 } 457 458 /** 459 * @return the phone associated with the ringing call 460 */ getRingingPhone()461 public Phone getRingingPhone() { 462 return getFirstActiveRingingCall().getPhone(); 463 } 464 465 /** 466 * @return the phone associated with the ringing call 467 * of a particular subId 468 */ getRingingPhone(int subId)469 public Phone getRingingPhone(int subId) { 470 return getFirstActiveRingingCall(subId).getPhone(); 471 } 472 473 /* FIXME Taken from klp-sprout-dev but setAudioMode was removed in L. 474 public void setAudioMode() { 475 Context context = getContext(); 476 if (context == null) return; 477 AudioManager audioManager = (AudioManager) 478 context.getSystemService(Context.AUDIO_SERVICE); 479 480 if (!isServiceStateInService() && !mIsEccDialing) { 481 if (audioManager.getMode() != AudioManager.MODE_NORMAL) { 482 if (VDBG) Rlog.d(LOG_TAG, "abandonAudioFocus"); 483 // abandon audio focus after the mode has been set back to normal 484 audioManager.abandonAudioFocusForCall(); 485 audioManager.setMode(AudioManager.MODE_NORMAL); 486 } 487 return; 488 } 489 490 // change the audio mode and request/abandon audio focus according to phone state, 491 // but only on audio mode transitions 492 switch (getState()) { 493 case RINGING: 494 int curAudioMode = audioManager.getMode(); 495 if (curAudioMode != AudioManager.MODE_RINGTONE) { 496 if (VDBG) Rlog.d(LOG_TAG, "requestAudioFocus on STREAM_RING"); 497 audioManager.requestAudioFocusForCall(AudioManager.STREAM_RING, 498 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); 499 if(!mSpeedUpAudioForMtCall) { 500 audioManager.setMode(AudioManager.MODE_RINGTONE); 501 } 502 } 503 504 if (mSpeedUpAudioForMtCall && (curAudioMode != AudioManager.MODE_IN_CALL)) { 505 audioManager.setMode(AudioManager.MODE_IN_CALL); 506 } 507 break; 508 case OFFHOOK: 509 Phone offhookPhone = getFgPhone(); 510 if (getActiveFgCallState() == Call.State.IDLE) { 511 // There is no active Fg calls, the OFFHOOK state 512 // is set by the Bg call. So set the phone to bgPhone. 513 offhookPhone = getBgPhone(); 514 } 515 516 int newAudioMode = AudioManager.MODE_IN_CALL; 517 if (offhookPhone instanceof SipPhone) { 518 Rlog.d(LOG_TAG, "setAudioMode Set audio mode for SIP call!"); 519 // enable IN_COMMUNICATION audio mode instead for sipPhone 520 newAudioMode = AudioManager.MODE_IN_COMMUNICATION; 521 } 522 int currMode = audioManager.getMode(); 523 if (currMode != newAudioMode || mSpeedUpAudioForMtCall) { 524 // request audio focus before setting the new mode 525 if (VDBG) Rlog.d(LOG_TAG, "requestAudioFocus on STREAM_VOICE_CALL"); 526 audioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL, 527 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); 528 Rlog.d(LOG_TAG, "setAudioMode Setting audio mode from " 529 + currMode + " to " + newAudioMode); 530 audioManager.setMode(newAudioMode); 531 } 532 mSpeedUpAudioForMtCall = false; 533 break; 534 case IDLE: 535 if (audioManager.getMode() != AudioManager.MODE_NORMAL) { 536 audioManager.setMode(AudioManager.MODE_NORMAL); 537 if (VDBG) Rlog.d(LOG_TAG, "abandonAudioFocus"); 538 // abandon audio focus after the mode has been set back to normal 539 audioManager.abandonAudioFocusForCall(); 540 } 541 mSpeedUpAudioForMtCall = false; 542 break; 543 } 544 Rlog.d(LOG_TAG, "setAudioMode state = " + getState()); 545 } 546 */ 547 getContext()548 private Context getContext() { 549 Phone defaultPhone = getDefaultPhone(); 550 return ((defaultPhone == null) ? null : defaultPhone.getContext()); 551 } 552 getRegistrantIdentifier()553 public Object getRegistrantIdentifier() { 554 return mRegistrantidentifier; 555 } 556 registerForPhoneStates(Phone phone)557 private void registerForPhoneStates(Phone phone) { 558 // We need to keep a mapping of handler to Phone for proper unregistration. 559 // TODO: Clean up this solution as it is just a work around for each Phone instance 560 // using the same Handler to register with the RIL. When time permits, we should consider 561 // moving the handler (or the reference ot the handler) into the Phone object. 562 // See b/17414427. 563 CallManagerHandler handler = mHandlerMap.get(phone); 564 if (handler != null) { 565 Rlog.d(LOG_TAG, "This phone has already been registered."); 566 return; 567 } 568 569 // New registration, create a new handler instance and register the phone. 570 handler = new CallManagerHandler(); 571 mHandlerMap.put(phone, handler); 572 573 // for common events supported by all phones 574 // The mRegistrantIdentifier passed here, is to identify in the Phone 575 // that the registrants are coming from the CallManager. 576 phone.registerForPreciseCallStateChanged(handler, EVENT_PRECISE_CALL_STATE_CHANGED, 577 mRegistrantidentifier); 578 phone.registerForDisconnect(handler, EVENT_DISCONNECT, 579 mRegistrantidentifier); 580 phone.registerForNewRingingConnection(handler, EVENT_NEW_RINGING_CONNECTION, 581 mRegistrantidentifier); 582 phone.registerForUnknownConnection(handler, EVENT_UNKNOWN_CONNECTION, 583 mRegistrantidentifier); 584 phone.registerForIncomingRing(handler, EVENT_INCOMING_RING, 585 mRegistrantidentifier); 586 phone.registerForRingbackTone(handler, EVENT_RINGBACK_TONE, 587 mRegistrantidentifier); 588 phone.registerForInCallVoicePrivacyOn(handler, EVENT_IN_CALL_VOICE_PRIVACY_ON, 589 mRegistrantidentifier); 590 phone.registerForInCallVoicePrivacyOff(handler, EVENT_IN_CALL_VOICE_PRIVACY_OFF, 591 mRegistrantidentifier); 592 phone.registerForDisplayInfo(handler, EVENT_DISPLAY_INFO, 593 mRegistrantidentifier); 594 phone.registerForSignalInfo(handler, EVENT_SIGNAL_INFO, 595 mRegistrantidentifier); 596 phone.registerForResendIncallMute(handler, EVENT_RESEND_INCALL_MUTE, 597 mRegistrantidentifier); 598 phone.registerForMmiInitiate(handler, EVENT_MMI_INITIATE, 599 mRegistrantidentifier); 600 phone.registerForMmiComplete(handler, EVENT_MMI_COMPLETE, 601 mRegistrantidentifier); 602 phone.registerForSuppServiceFailed(handler, EVENT_SUPP_SERVICE_FAILED, 603 mRegistrantidentifier); 604 phone.registerForServiceStateChanged(handler, EVENT_SERVICE_STATE_CHANGED, 605 mRegistrantidentifier); 606 607 // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L. 608 //phone.registerForRadioOffOrNotAvailable(handler, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null); 609 610 // for events supported only by GSM, CDMA and IMS phone 611 phone.setOnPostDialCharacter(handler, EVENT_POST_DIAL_CHARACTER, null); 612 613 // for events supported only by CDMA phone 614 phone.registerForCdmaOtaStatusChange(handler, EVENT_CDMA_OTA_STATUS_CHANGE, null); 615 phone.registerForSubscriptionInfoReady(handler, EVENT_SUBSCRIPTION_INFO_READY, null); 616 phone.registerForCallWaiting(handler, EVENT_CALL_WAITING, null); 617 phone.registerForEcmTimerReset(handler, EVENT_ECM_TIMER_RESET, null); 618 619 // for events supported only by IMS phone 620 phone.registerForOnHoldTone(handler, EVENT_ONHOLD_TONE, null); 621 phone.registerForSuppServiceFailed(handler, EVENT_SUPP_SERVICE_FAILED, null); 622 phone.registerForTtyModeReceived(handler, EVENT_TTY_MODE_RECEIVED, null); 623 } 624 unregisterForPhoneStates(Phone phone)625 private void unregisterForPhoneStates(Phone phone) { 626 // Make sure that we clean up our map of handlers to Phones. 627 CallManagerHandler handler = mHandlerMap.get(phone); 628 if (handler == null) { 629 Rlog.e(LOG_TAG, "Could not find Phone handler for unregistration"); 630 return; 631 } 632 mHandlerMap.remove(phone); 633 634 // for common events supported by all phones 635 phone.unregisterForPreciseCallStateChanged(handler); 636 phone.unregisterForDisconnect(handler); 637 phone.unregisterForNewRingingConnection(handler); 638 phone.unregisterForUnknownConnection(handler); 639 phone.unregisterForIncomingRing(handler); 640 phone.unregisterForRingbackTone(handler); 641 phone.unregisterForInCallVoicePrivacyOn(handler); 642 phone.unregisterForInCallVoicePrivacyOff(handler); 643 phone.unregisterForDisplayInfo(handler); 644 phone.unregisterForSignalInfo(handler); 645 phone.unregisterForResendIncallMute(handler); 646 phone.unregisterForMmiInitiate(handler); 647 phone.unregisterForMmiComplete(handler); 648 phone.unregisterForSuppServiceFailed(handler); 649 phone.unregisterForServiceStateChanged(handler); 650 phone.unregisterForTtyModeReceived(handler); 651 // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L. 652 //phone.unregisterForRadioOffOrNotAvailable(handler); 653 654 // for events supported only by GSM, CDMA and IMS phone 655 phone.setOnPostDialCharacter(null, EVENT_POST_DIAL_CHARACTER, null); 656 657 // for events supported only by CDMA phone 658 phone.unregisterForCdmaOtaStatusChange(handler); 659 phone.unregisterForSubscriptionInfoReady(handler); 660 phone.unregisterForCallWaiting(handler); 661 phone.unregisterForEcmTimerReset(handler); 662 663 // for events supported only by IMS phone 664 phone.unregisterForOnHoldTone(handler); 665 phone.unregisterForSuppServiceFailed(handler); 666 } 667 668 /** 669 * Answers a ringing or waiting call. 670 * 671 * Active call, if any, go on hold. 672 * If active call can't be held, i.e., a background call of the same channel exists, 673 * the active call will be hang up. 674 * 675 * Answering occurs asynchronously, and final notification occurs via 676 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 677 * java.lang.Object) registerForPreciseCallStateChanged()}. 678 * 679 * @exception CallStateException when call is not ringing or waiting 680 */ acceptCall(Call ringingCall)681 public void acceptCall(Call ringingCall) throws CallStateException { 682 Phone ringingPhone = ringingCall.getPhone(); 683 684 if (VDBG) { 685 Rlog.d(LOG_TAG, "acceptCall(" +ringingCall + " from " + ringingCall.getPhone() + ")"); 686 Rlog.d(LOG_TAG, toString()); 687 } 688 689 if ( hasActiveFgCall() ) { 690 Phone activePhone = getActiveFgCall().getPhone(); 691 boolean hasBgCall = ! (activePhone.getBackgroundCall().isIdle()); 692 boolean sameChannel = (activePhone == ringingPhone); 693 694 if (VDBG) { 695 Rlog.d(LOG_TAG, "hasBgCall: "+ hasBgCall + "sameChannel:" + sameChannel); 696 } 697 698 if (sameChannel && hasBgCall) { 699 getActiveFgCall().hangup(); 700 } else if (!sameChannel && !hasBgCall) { 701 activePhone.switchHoldingAndActive(); 702 } else if (!sameChannel && hasBgCall) { 703 getActiveFgCall().hangup(); 704 } 705 } 706 707 // We only support the AUDIO_ONLY video state in this scenario. 708 ringingPhone.acceptCall(VideoProfile.STATE_AUDIO_ONLY); 709 710 if (VDBG) { 711 Rlog.d(LOG_TAG, "End acceptCall(" +ringingCall + ")"); 712 Rlog.d(LOG_TAG, toString()); 713 } 714 } 715 716 /** 717 * Reject (ignore) a ringing call. In GSM, this means UDUB 718 * (User Determined User Busy). Reject occurs asynchronously, 719 * and final notification occurs via 720 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 721 * java.lang.Object) registerForPreciseCallStateChanged()}. 722 * 723 * @exception CallStateException when no call is ringing or waiting 724 */ rejectCall(Call ringingCall)725 public void rejectCall(Call ringingCall) throws CallStateException { 726 if (VDBG) { 727 Rlog.d(LOG_TAG, "rejectCall(" +ringingCall + ")"); 728 Rlog.d(LOG_TAG, toString()); 729 } 730 731 Phone ringingPhone = ringingCall.getPhone(); 732 733 ringingPhone.rejectCall(); 734 735 if (VDBG) { 736 Rlog.d(LOG_TAG, "End rejectCall(" +ringingCall + ")"); 737 Rlog.d(LOG_TAG, toString()); 738 } 739 } 740 741 /** 742 * Places active call on hold, and makes held call active. 743 * Switch occurs asynchronously and may fail. 744 * 745 * There are 4 scenarios 746 * 1. only active call but no held call, aka, hold 747 * 2. no active call but only held call, aka, unhold 748 * 3. both active and held calls from same phone, aka, swap 749 * 4. active and held calls from different phones, aka, phone swap 750 * 751 * Final notification occurs via 752 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 753 * java.lang.Object) registerForPreciseCallStateChanged()}. 754 * 755 * @exception CallStateException if active call is ringing, waiting, or 756 * dialing/alerting, or heldCall can't be active. 757 * In these cases, this operation may not be performed. 758 */ switchHoldingAndActive(Call heldCall)759 public void switchHoldingAndActive(Call heldCall) throws CallStateException { 760 Phone activePhone = null; 761 Phone heldPhone = null; 762 763 if (VDBG) { 764 Rlog.d(LOG_TAG, "switchHoldingAndActive(" +heldCall + ")"); 765 Rlog.d(LOG_TAG, toString()); 766 } 767 768 if (hasActiveFgCall()) { 769 activePhone = getActiveFgCall().getPhone(); 770 } 771 772 if (heldCall != null) { 773 heldPhone = heldCall.getPhone(); 774 } 775 776 if (activePhone != null) { 777 activePhone.switchHoldingAndActive(); 778 } 779 780 if (heldPhone != null && heldPhone != activePhone) { 781 heldPhone.switchHoldingAndActive(); 782 } 783 784 if (VDBG) { 785 Rlog.d(LOG_TAG, "End switchHoldingAndActive(" +heldCall + ")"); 786 Rlog.d(LOG_TAG, toString()); 787 } 788 } 789 790 /** 791 * Hangup foreground call and resume the specific background call 792 * 793 * Note: this is noop if there is no foreground call or the heldCall is null 794 * 795 * @param heldCall to become foreground 796 * @throws CallStateException 797 */ hangupForegroundResumeBackground(Call heldCall)798 public void hangupForegroundResumeBackground(Call heldCall) throws CallStateException { 799 Phone foregroundPhone = null; 800 Phone backgroundPhone = null; 801 802 if (VDBG) { 803 Rlog.d(LOG_TAG, "hangupForegroundResumeBackground(" +heldCall + ")"); 804 Rlog.d(LOG_TAG, toString()); 805 } 806 807 if (hasActiveFgCall()) { 808 foregroundPhone = getFgPhone(); 809 if (heldCall != null) { 810 backgroundPhone = heldCall.getPhone(); 811 if (foregroundPhone == backgroundPhone) { 812 getActiveFgCall().hangup(); 813 } else { 814 // the call to be hangup and resumed belongs to different phones 815 getActiveFgCall().hangup(); 816 switchHoldingAndActive(heldCall); 817 } 818 } 819 } 820 821 if (VDBG) { 822 Rlog.d(LOG_TAG, "End hangupForegroundResumeBackground(" +heldCall + ")"); 823 Rlog.d(LOG_TAG, toString()); 824 } 825 } 826 827 /** 828 * Whether or not the phone can conference in the current phone 829 * state--that is, one call holding and one call active. 830 * @return true if the phone can conference; false otherwise. 831 */ canConference(Call heldCall)832 public boolean canConference(Call heldCall) { 833 Phone activePhone = null; 834 Phone heldPhone = null; 835 836 if (hasActiveFgCall()) { 837 activePhone = getActiveFgCall().getPhone(); 838 } 839 840 if (heldCall != null) { 841 heldPhone = heldCall.getPhone(); 842 } 843 844 return heldPhone.getClass().equals(activePhone.getClass()); 845 } 846 847 /** 848 * Whether or not the phone can conference in the current phone 849 * state--that is, one call holding and one call active. 850 * This method consider the phone object which is specific 851 * to the provided subId. 852 * @return true if the phone can conference; false otherwise. 853 */ canConference(Call heldCall, int subId)854 public boolean canConference(Call heldCall, int subId) { 855 Phone activePhone = null; 856 Phone heldPhone = null; 857 858 if (hasActiveFgCall(subId)) { 859 activePhone = getActiveFgCall(subId).getPhone(); 860 } 861 862 if (heldCall != null) { 863 heldPhone = heldCall.getPhone(); 864 } 865 866 return heldPhone.getClass().equals(activePhone.getClass()); 867 } 868 869 /** 870 * Conferences holding and active. Conference occurs asynchronously 871 * and may fail. Final notification occurs via 872 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 873 * java.lang.Object) registerForPreciseCallStateChanged()}. 874 * 875 * @exception CallStateException if canConference() would return false. 876 * In these cases, this operation may not be performed. 877 */ conference(Call heldCall)878 public void conference(Call heldCall) throws CallStateException { 879 int subId = heldCall.getPhone().getSubId(); 880 881 if (VDBG) { 882 Rlog.d(LOG_TAG, "conference(" +heldCall + ")"); 883 Rlog.d(LOG_TAG, toString()); 884 } 885 886 Phone fgPhone = getFgPhone(subId); 887 if (fgPhone != null) { 888 if (fgPhone instanceof SipPhone) { 889 ((SipPhone) fgPhone).conference(heldCall); 890 } else if (canConference(heldCall)) { 891 fgPhone.conference(); 892 } else { 893 throw(new CallStateException("Can't conference foreground and selected background call")); 894 } 895 } else { 896 Rlog.d(LOG_TAG, "conference: fgPhone=null"); 897 } 898 899 if (VDBG) { 900 Rlog.d(LOG_TAG, "End conference(" +heldCall + ")"); 901 Rlog.d(LOG_TAG, toString()); 902 } 903 904 } 905 906 /** 907 * Initiate a new voice connection. This happens asynchronously, so you 908 * cannot assume the audio path is connected (or a call index has been 909 * assigned) until PhoneStateChanged notification has occurred. 910 * 911 * @exception CallStateException if a new outgoing call is not currently 912 * possible because no more call slots exist or a call exists that is 913 * dialing, alerting, ringing, or waiting. Other errors are 914 * handled asynchronously. 915 */ dial(Phone phone, String dialString, int videoState)916 public Connection dial(Phone phone, String dialString, int videoState) 917 throws CallStateException { 918 int subId = phone.getSubId(); 919 Connection result; 920 921 if (VDBG) { 922 Rlog.d(LOG_TAG, " dial(" + phone + ", "+ dialString + ")" + 923 " subId = " + subId); 924 Rlog.d(LOG_TAG, toString()); 925 } 926 927 if (!canDial(phone)) { 928 /* 929 * canDial function only checks whether the phone can make a new call. 930 * InCall MMI commmands are basically supplementary services 931 * within a call eg: call hold, call deflection, explicit call transfer etc. 932 */ 933 String newDialString = PhoneNumberUtils.stripSeparators(dialString); 934 if (phone.handleInCallMmiCommands(newDialString)) { 935 return null; 936 } else { 937 throw new CallStateException("cannot dial in current state"); 938 } 939 } 940 941 if ( hasActiveFgCall(subId) ) { 942 Phone activePhone = getActiveFgCall(subId).getPhone(); 943 boolean hasBgCall = !(activePhone.getBackgroundCall().isIdle()); 944 945 if (DBG) { 946 Rlog.d(LOG_TAG, "hasBgCall: "+ hasBgCall + " sameChannel:" + (activePhone == phone)); 947 } 948 949 // Manipulation between IMS phone and its owner 950 // will be treated in GSM/CDMA phone. 951 Phone imsPhone = phone.getImsPhone(); 952 if (activePhone != phone 953 && (imsPhone == null || imsPhone != activePhone)) { 954 if (hasBgCall) { 955 Rlog.d(LOG_TAG, "Hangup"); 956 getActiveFgCall(subId).hangup(); 957 } else { 958 Rlog.d(LOG_TAG, "Switch"); 959 activePhone.switchHoldingAndActive(); 960 } 961 } 962 } 963 964 // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L. 965 //mIsEccDialing = PhoneNumberUtils.isEmergencyNumber(dialString); 966 967 result = phone.dial(dialString, videoState); 968 969 if (VDBG) { 970 Rlog.d(LOG_TAG, "End dial(" + phone + ", "+ dialString + ")"); 971 Rlog.d(LOG_TAG, toString()); 972 } 973 974 return result; 975 } 976 977 /** 978 * Initiate a new voice connection. This happens asynchronously, so you 979 * cannot assume the audio path is connected (or a call index has been 980 * assigned) until PhoneStateChanged notification has occurred. 981 * 982 * @exception CallStateException if a new outgoing call is not currently 983 * possible because no more call slots exist or a call exists that is 984 * dialing, alerting, ringing, or waiting. Other errors are 985 * handled asynchronously. 986 */ dial(Phone phone, String dialString, UUSInfo uusInfo, int videoState)987 public Connection dial(Phone phone, String dialString, UUSInfo uusInfo, int videoState) 988 throws CallStateException { 989 return phone.dial(dialString, uusInfo, videoState, null); 990 } 991 992 /** 993 * clear disconnect connection for each phone 994 */ clearDisconnected()995 public void clearDisconnected() { 996 for(Phone phone : mPhones) { 997 phone.clearDisconnected(); 998 } 999 } 1000 1001 /** 1002 * clear disconnect connection for a phone specific 1003 * to the provided subId 1004 */ clearDisconnected(int subId)1005 public void clearDisconnected(int subId) { 1006 for(Phone phone : mPhones) { 1007 if (phone.getSubId() == subId) { 1008 phone.clearDisconnected(); 1009 } 1010 } 1011 } 1012 1013 /** 1014 * Phone can make a call only if ALL of the following are true: 1015 * - Phone is not powered off 1016 * - There's no incoming or waiting call 1017 * - The foreground call is ACTIVE or IDLE or DISCONNECTED. 1018 * (We mainly need to make sure it *isn't* DIALING or ALERTING.) 1019 * @param phone 1020 * @return true if the phone can make a new call 1021 */ canDial(Phone phone)1022 private boolean canDial(Phone phone) { 1023 int serviceState = phone.getServiceState().getState(); 1024 int subId = phone.getSubId(); 1025 boolean hasRingingCall = hasActiveRingingCall(); 1026 Call.State fgCallState = getActiveFgCallState(subId); 1027 1028 boolean result = (serviceState != ServiceState.STATE_POWER_OFF 1029 && !hasRingingCall 1030 && ((fgCallState == Call.State.ACTIVE) 1031 || (fgCallState == Call.State.IDLE) 1032 || (fgCallState == Call.State.DISCONNECTED) 1033 /*As per 3GPP TS 51.010-1 section 31.13.1.4 1034 call should be alowed when the foreground 1035 call is in ALERTING state*/ 1036 || (fgCallState == Call.State.ALERTING))); 1037 1038 if (result == false) { 1039 Rlog.d(LOG_TAG, "canDial serviceState=" + serviceState 1040 + " hasRingingCall=" + hasRingingCall 1041 + " fgCallState=" + fgCallState); 1042 } 1043 return result; 1044 } 1045 1046 /** 1047 * Whether or not the phone can do explicit call transfer in the current 1048 * phone state--that is, one call holding and one call active. 1049 * @return true if the phone can do explicit call transfer; false otherwise. 1050 */ canTransfer(Call heldCall)1051 public boolean canTransfer(Call heldCall) { 1052 Phone activePhone = null; 1053 Phone heldPhone = null; 1054 1055 if (hasActiveFgCall()) { 1056 activePhone = getActiveFgCall().getPhone(); 1057 } 1058 1059 if (heldCall != null) { 1060 heldPhone = heldCall.getPhone(); 1061 } 1062 1063 return (heldPhone == activePhone && activePhone.canTransfer()); 1064 } 1065 1066 /** 1067 * Whether or not the phone specific to subId can do explicit call transfer 1068 * in the current phone state--that is, one call holding and one call active. 1069 * @return true if the phone can do explicit call transfer; false otherwise. 1070 */ canTransfer(Call heldCall, int subId)1071 public boolean canTransfer(Call heldCall, int subId) { 1072 Phone activePhone = null; 1073 Phone heldPhone = null; 1074 1075 if (hasActiveFgCall(subId)) { 1076 activePhone = getActiveFgCall(subId).getPhone(); 1077 } 1078 1079 if (heldCall != null) { 1080 heldPhone = heldCall.getPhone(); 1081 } 1082 1083 return (heldPhone == activePhone && activePhone.canTransfer()); 1084 } 1085 1086 /** 1087 * Connects the held call and active call 1088 * Disconnects the subscriber from both calls 1089 * 1090 * Explicit Call Transfer occurs asynchronously 1091 * and may fail. Final notification occurs via 1092 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 1093 * java.lang.Object) registerForPreciseCallStateChanged()}. 1094 * 1095 * @exception CallStateException if canTransfer() would return false. 1096 * In these cases, this operation may not be performed. 1097 */ explicitCallTransfer(Call heldCall)1098 public void explicitCallTransfer(Call heldCall) throws CallStateException { 1099 if (VDBG) { 1100 Rlog.d(LOG_TAG, " explicitCallTransfer(" + heldCall + ")"); 1101 Rlog.d(LOG_TAG, toString()); 1102 } 1103 1104 if (canTransfer(heldCall)) { 1105 heldCall.getPhone().explicitCallTransfer(); 1106 } 1107 1108 if (VDBG) { 1109 Rlog.d(LOG_TAG, "End explicitCallTransfer(" + heldCall + ")"); 1110 Rlog.d(LOG_TAG, toString()); 1111 } 1112 1113 } 1114 1115 /** 1116 * Returns a list of MMI codes that are pending for a phone. (They have initiated 1117 * but have not yet completed). 1118 * Presently there is only ever one. 1119 * 1120 * Use <code>registerForMmiInitiate</code> 1121 * and <code>registerForMmiComplete</code> for change notification. 1122 * @return null if phone doesn't have or support mmi code 1123 */ getPendingMmiCodes(Phone phone)1124 public List<? extends MmiCode> getPendingMmiCodes(Phone phone) { 1125 Rlog.e(LOG_TAG, "getPendingMmiCodes not implemented"); 1126 return null; 1127 } 1128 1129 /** 1130 * Sends user response to a USSD REQUEST message. An MmiCode instance 1131 * representing this response is sent to handlers registered with 1132 * registerForMmiInitiate. 1133 * 1134 * @param ussdMessge Message to send in the response. 1135 * @return false if phone doesn't support ussd service 1136 */ sendUssdResponse(Phone phone, String ussdMessge)1137 public boolean sendUssdResponse(Phone phone, String ussdMessge) { 1138 Rlog.e(LOG_TAG, "sendUssdResponse not implemented"); 1139 return false; 1140 } 1141 1142 /** 1143 * Mutes or unmutes the microphone for the active call. The microphone 1144 * is automatically unmuted if a call is answered, dialed, or resumed 1145 * from a holding state. 1146 * 1147 * @param muted true to mute the microphone, 1148 * false to activate the microphone. 1149 */ 1150 setMute(boolean muted)1151 public void setMute(boolean muted) { 1152 if (VDBG) { 1153 Rlog.d(LOG_TAG, " setMute(" + muted + ")"); 1154 Rlog.d(LOG_TAG, toString()); 1155 } 1156 1157 if (hasActiveFgCall()) { 1158 getActiveFgCall().getPhone().setMute(muted); 1159 } 1160 1161 if (VDBG) { 1162 Rlog.d(LOG_TAG, "End setMute(" + muted + ")"); 1163 Rlog.d(LOG_TAG, toString()); 1164 } 1165 } 1166 1167 /** 1168 * Gets current mute status. Use 1169 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 1170 * java.lang.Object) registerForPreciseCallStateChanged()} 1171 * as a change notifcation, although presently phone state changed is not 1172 * fired when setMute() is called. 1173 * 1174 * @return true is muting, false is unmuting 1175 */ getMute()1176 public boolean getMute() { 1177 if (hasActiveFgCall()) { 1178 return getActiveFgCall().getPhone().getMute(); 1179 } else if (hasActiveBgCall()) { 1180 return getFirstActiveBgCall().getPhone().getMute(); 1181 } 1182 return false; 1183 } 1184 1185 /** 1186 * Enables or disables echo suppression. 1187 */ setEchoSuppressionEnabled()1188 public void setEchoSuppressionEnabled() { 1189 if (VDBG) { 1190 Rlog.d(LOG_TAG, " setEchoSuppression()"); 1191 Rlog.d(LOG_TAG, toString()); 1192 } 1193 1194 if (hasActiveFgCall()) { 1195 getActiveFgCall().getPhone().setEchoSuppressionEnabled(); 1196 } 1197 1198 if (VDBG) { 1199 Rlog.d(LOG_TAG, "End setEchoSuppression()"); 1200 Rlog.d(LOG_TAG, toString()); 1201 } 1202 } 1203 1204 /** 1205 * Play a DTMF tone on the active call. 1206 * 1207 * @param c should be one of 0-9, '*' or '#'. Other values will be 1208 * silently ignored. 1209 * @return false if no active call or the active call doesn't support 1210 * dtmf tone 1211 */ sendDtmf(char c)1212 public boolean sendDtmf(char c) { 1213 boolean result = false; 1214 1215 if (VDBG) { 1216 Rlog.d(LOG_TAG, " sendDtmf(" + c + ")"); 1217 Rlog.d(LOG_TAG, toString()); 1218 } 1219 1220 if (hasActiveFgCall()) { 1221 getActiveFgCall().getPhone().sendDtmf(c); 1222 result = true; 1223 } 1224 1225 if (VDBG) { 1226 Rlog.d(LOG_TAG, "End sendDtmf(" + c + ")"); 1227 Rlog.d(LOG_TAG, toString()); 1228 } 1229 return result; 1230 } 1231 1232 /** 1233 * Start to paly a DTMF tone on the active call. 1234 * or there is a playing DTMF tone. 1235 * @param c should be one of 0-9, '*' or '#'. Other values will be 1236 * silently ignored. 1237 * 1238 * @return false if no active call or the active call doesn't support 1239 * dtmf tone 1240 */ startDtmf(char c)1241 public boolean startDtmf(char c) { 1242 boolean result = false; 1243 1244 if (VDBG) { 1245 Rlog.d(LOG_TAG, " startDtmf(" + c + ")"); 1246 Rlog.d(LOG_TAG, toString()); 1247 } 1248 1249 if (hasActiveFgCall()) { 1250 getActiveFgCall().getPhone().startDtmf(c); 1251 result = true; 1252 } 1253 1254 if (VDBG) { 1255 Rlog.d(LOG_TAG, "End startDtmf(" + c + ")"); 1256 Rlog.d(LOG_TAG, toString()); 1257 } 1258 1259 return result; 1260 } 1261 1262 /** 1263 * Stop the playing DTMF tone. Ignored if there is no playing DTMF 1264 * tone or no active call. 1265 */ stopDtmf()1266 public void stopDtmf() { 1267 if (VDBG) { 1268 Rlog.d(LOG_TAG, " stopDtmf()" ); 1269 Rlog.d(LOG_TAG, toString()); 1270 } 1271 1272 if (hasActiveFgCall()) getFgPhone().stopDtmf(); 1273 1274 if (VDBG) { 1275 Rlog.d(LOG_TAG, "End stopDtmf()"); 1276 Rlog.d(LOG_TAG, toString()); 1277 } 1278 } 1279 1280 /** 1281 * send burst DTMF tone, it can send the string as single character or multiple character 1282 * ignore if there is no active call or not valid digits string. 1283 * Valid digit means only includes characters ISO-LATIN characters 0-9, *, # 1284 * The difference between sendDtmf and sendBurstDtmf is sendDtmf only sends one character, 1285 * this api can send single character and multiple character, also, this api has response 1286 * back to caller. 1287 * 1288 * @param dtmfString is string representing the dialing digit(s) in the active call 1289 * @param on the DTMF ON length in milliseconds, or 0 for default 1290 * @param off the DTMF OFF length in milliseconds, or 0 for default 1291 * @param onComplete is the callback message when the action is processed by BP 1292 * 1293 */ sendBurstDtmf(String dtmfString, int on, int off, Message onComplete)1294 public boolean sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) { 1295 if (hasActiveFgCall()) { 1296 getActiveFgCall().getPhone().sendBurstDtmf(dtmfString, on, off, onComplete); 1297 return true; 1298 } 1299 return false; 1300 } 1301 1302 /** 1303 * Notifies when a voice connection has disconnected, either due to local 1304 * or remote hangup or error. 1305 * 1306 * Messages received from this will have the following members:<p> 1307 * <ul><li>Message.obj will be an AsyncResult</li> 1308 * <li>AsyncResult.userObj = obj</li> 1309 * <li>AsyncResult.result = a Connection object that is 1310 * no longer connected.</li></ul> 1311 */ registerForDisconnect(Handler h, int what, Object obj)1312 public void registerForDisconnect(Handler h, int what, Object obj) { 1313 mDisconnectRegistrants.addUnique(h, what, obj); 1314 } 1315 1316 /** 1317 * Unregisters for voice disconnection notification. 1318 * Extraneous calls are tolerated silently 1319 */ unregisterForDisconnect(Handler h)1320 public void unregisterForDisconnect(Handler h){ 1321 mDisconnectRegistrants.remove(h); 1322 } 1323 1324 /** 1325 * Register for getting notifications for change in the Call State {@link Call.State} 1326 * This is called PreciseCallState because the call state is more precise than what 1327 * can be obtained using the {@link PhoneStateListener} 1328 * 1329 * Resulting events will have an AsyncResult in <code>Message.obj</code>. 1330 * AsyncResult.userData will be set to the obj argument here. 1331 * The <em>h</em> parameter is held only by a weak reference. 1332 */ registerForPreciseCallStateChanged(Handler h, int what, Object obj)1333 public void registerForPreciseCallStateChanged(Handler h, int what, Object obj){ 1334 mPreciseCallStateRegistrants.addUnique(h, what, obj); 1335 } 1336 1337 /** 1338 * Unregisters for voice call state change notifications. 1339 * Extraneous calls are tolerated silently. 1340 */ unregisterForPreciseCallStateChanged(Handler h)1341 public void unregisterForPreciseCallStateChanged(Handler h){ 1342 mPreciseCallStateRegistrants.remove(h); 1343 } 1344 1345 /** 1346 * Notifies when a previously untracked non-ringing/waiting connection has appeared. 1347 * This is likely due to some other entity (eg, SIM card application) initiating a call. 1348 */ registerForUnknownConnection(Handler h, int what, Object obj)1349 public void registerForUnknownConnection(Handler h, int what, Object obj){ 1350 mUnknownConnectionRegistrants.addUnique(h, what, obj); 1351 } 1352 1353 /** 1354 * Unregisters for unknown connection notifications. 1355 */ unregisterForUnknownConnection(Handler h)1356 public void unregisterForUnknownConnection(Handler h){ 1357 mUnknownConnectionRegistrants.remove(h); 1358 } 1359 1360 1361 /** 1362 * Notifies when a new ringing or waiting connection has appeared.<p> 1363 * 1364 * Messages received from this: 1365 * Message.obj will be an AsyncResult 1366 * AsyncResult.userObj = obj 1367 * AsyncResult.result = a Connection. <p> 1368 * Please check Connection.isRinging() to make sure the Connection 1369 * has not dropped since this message was posted. 1370 * If Connection.isRinging() is true, then 1371 * Connection.getCall() == Phone.getRingingCall() 1372 */ registerForNewRingingConnection(Handler h, int what, Object obj)1373 public void registerForNewRingingConnection(Handler h, int what, Object obj){ 1374 mNewRingingConnectionRegistrants.addUnique(h, what, obj); 1375 } 1376 1377 /** 1378 * Unregisters for new ringing connection notification. 1379 * Extraneous calls are tolerated silently 1380 */ 1381 unregisterForNewRingingConnection(Handler h)1382 public void unregisterForNewRingingConnection(Handler h){ 1383 mNewRingingConnectionRegistrants.remove(h); 1384 } 1385 1386 /** 1387 * Notifies when an incoming call rings.<p> 1388 * 1389 * Messages received from this: 1390 * Message.obj will be an AsyncResult 1391 * AsyncResult.userObj = obj 1392 * AsyncResult.result = a Connection. <p> 1393 */ registerForIncomingRing(Handler h, int what, Object obj)1394 public void registerForIncomingRing(Handler h, int what, Object obj){ 1395 mIncomingRingRegistrants.addUnique(h, what, obj); 1396 } 1397 1398 /** 1399 * Unregisters for ring notification. 1400 * Extraneous calls are tolerated silently 1401 */ 1402 unregisterForIncomingRing(Handler h)1403 public void unregisterForIncomingRing(Handler h){ 1404 mIncomingRingRegistrants.remove(h); 1405 } 1406 1407 /** 1408 * Notifies when out-band ringback tone is needed.<p> 1409 * 1410 * Messages received from this: 1411 * Message.obj will be an AsyncResult 1412 * AsyncResult.userObj = obj 1413 * AsyncResult.result = boolean, true to start play ringback tone 1414 * and false to stop. <p> 1415 */ registerForRingbackTone(Handler h, int what, Object obj)1416 public void registerForRingbackTone(Handler h, int what, Object obj){ 1417 mRingbackToneRegistrants.addUnique(h, what, obj); 1418 } 1419 1420 /** 1421 * Unregisters for ringback tone notification. 1422 */ 1423 unregisterForRingbackTone(Handler h)1424 public void unregisterForRingbackTone(Handler h){ 1425 mRingbackToneRegistrants.remove(h); 1426 } 1427 1428 /** 1429 * Notifies when out-band on-hold tone is needed.<p> 1430 * 1431 * Messages received from this: 1432 * Message.obj will be an AsyncResult 1433 * AsyncResult.userObj = obj 1434 * AsyncResult.result = boolean, true to start play on-hold tone 1435 * and false to stop. <p> 1436 */ registerForOnHoldTone(Handler h, int what, Object obj)1437 public void registerForOnHoldTone(Handler h, int what, Object obj){ 1438 mOnHoldToneRegistrants.addUnique(h, what, obj); 1439 } 1440 1441 /** 1442 * Unregisters for on-hold tone notification. 1443 */ 1444 unregisterForOnHoldTone(Handler h)1445 public void unregisterForOnHoldTone(Handler h){ 1446 mOnHoldToneRegistrants.remove(h); 1447 } 1448 1449 /** 1450 * Registers the handler to reset the uplink mute state to get 1451 * uplink audio. 1452 */ registerForResendIncallMute(Handler h, int what, Object obj)1453 public void registerForResendIncallMute(Handler h, int what, Object obj){ 1454 mResendIncallMuteRegistrants.addUnique(h, what, obj); 1455 } 1456 1457 /** 1458 * Unregisters for resend incall mute notifications. 1459 */ unregisterForResendIncallMute(Handler h)1460 public void unregisterForResendIncallMute(Handler h){ 1461 mResendIncallMuteRegistrants.remove(h); 1462 } 1463 1464 /** 1465 * Register for notifications of initiation of a new MMI code request. 1466 * MMI codes for GSM are discussed in 3GPP TS 22.030.<p> 1467 * 1468 * Example: If Phone.dial is called with "*#31#", then the app will 1469 * be notified here.<p> 1470 * 1471 * The returned <code>Message.obj</code> will contain an AsyncResult. 1472 * 1473 * <code>obj.result</code> will be an "MmiCode" object. 1474 */ registerForMmiInitiate(Handler h, int what, Object obj)1475 public void registerForMmiInitiate(Handler h, int what, Object obj){ 1476 mMmiInitiateRegistrants.addUnique(h, what, obj); 1477 } 1478 1479 /** 1480 * Unregisters for new MMI initiate notification. 1481 * Extraneous calls are tolerated silently 1482 */ unregisterForMmiInitiate(Handler h)1483 public void unregisterForMmiInitiate(Handler h){ 1484 mMmiInitiateRegistrants.remove(h); 1485 } 1486 1487 /** 1488 * Register for notifications that an MMI request has completed 1489 * its network activity and is in its final state. This may mean a state 1490 * of COMPLETE, FAILED, or CANCELLED. 1491 * 1492 * <code>Message.obj</code> will contain an AsyncResult. 1493 * <code>obj.result</code> will be an "MmiCode" object 1494 */ registerForMmiComplete(Handler h, int what, Object obj)1495 public void registerForMmiComplete(Handler h, int what, Object obj){ 1496 mMmiCompleteRegistrants.addUnique(h, what, obj); 1497 } 1498 1499 /** 1500 * Unregisters for MMI complete notification. 1501 * Extraneous calls are tolerated silently 1502 */ unregisterForMmiComplete(Handler h)1503 public void unregisterForMmiComplete(Handler h){ 1504 mMmiCompleteRegistrants.remove(h); 1505 } 1506 1507 /** 1508 * Registration point for Ecm timer reset 1509 * @param h handler to notify 1510 * @param what user-defined message code 1511 * @param obj placed in Message.obj 1512 */ registerForEcmTimerReset(Handler h, int what, Object obj)1513 public void registerForEcmTimerReset(Handler h, int what, Object obj){ 1514 mEcmTimerResetRegistrants.addUnique(h, what, obj); 1515 } 1516 1517 /** 1518 * Unregister for notification for Ecm timer reset 1519 * @param h Handler to be removed from the registrant list. 1520 */ unregisterForEcmTimerReset(Handler h)1521 public void unregisterForEcmTimerReset(Handler h){ 1522 mEcmTimerResetRegistrants.remove(h); 1523 } 1524 1525 /** 1526 * Register for ServiceState changed. 1527 * Message.obj will contain an AsyncResult. 1528 * AsyncResult.result will be a ServiceState instance 1529 */ registerForServiceStateChanged(Handler h, int what, Object obj)1530 public void registerForServiceStateChanged(Handler h, int what, Object obj){ 1531 mServiceStateChangedRegistrants.addUnique(h, what, obj); 1532 } 1533 1534 /** 1535 * Unregisters for ServiceStateChange notification. 1536 * Extraneous calls are tolerated silently 1537 */ unregisterForServiceStateChanged(Handler h)1538 public void unregisterForServiceStateChanged(Handler h){ 1539 mServiceStateChangedRegistrants.remove(h); 1540 } 1541 1542 /** 1543 * Register for notifications when a supplementary service attempt fails. 1544 * Message.obj will contain an AsyncResult. 1545 * 1546 * @param h Handler that receives the notification message. 1547 * @param what User-defined message code. 1548 * @param obj User object. 1549 */ registerForSuppServiceFailed(Handler h, int what, Object obj)1550 public void registerForSuppServiceFailed(Handler h, int what, Object obj){ 1551 mSuppServiceFailedRegistrants.addUnique(h, what, obj); 1552 } 1553 1554 /** 1555 * Unregister for notifications when a supplementary service attempt fails. 1556 * Extraneous calls are tolerated silently 1557 * 1558 * @param h Handler to be removed from the registrant list. 1559 */ unregisterForSuppServiceFailed(Handler h)1560 public void unregisterForSuppServiceFailed(Handler h){ 1561 mSuppServiceFailedRegistrants.remove(h); 1562 } 1563 1564 /** 1565 * Register for notifications when a sInCall VoicePrivacy is enabled 1566 * 1567 * @param h Handler that receives the notification message. 1568 * @param what User-defined message code. 1569 * @param obj User object. 1570 */ registerForInCallVoicePrivacyOn(Handler h, int what, Object obj)1571 public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){ 1572 mInCallVoicePrivacyOnRegistrants.addUnique(h, what, obj); 1573 } 1574 1575 /** 1576 * Unregister for notifications when a sInCall VoicePrivacy is enabled 1577 * 1578 * @param h Handler to be removed from the registrant list. 1579 */ unregisterForInCallVoicePrivacyOn(Handler h)1580 public void unregisterForInCallVoicePrivacyOn(Handler h){ 1581 mInCallVoicePrivacyOnRegistrants.remove(h); 1582 } 1583 1584 /** 1585 * Register for notifications when a sInCall VoicePrivacy is disabled 1586 * 1587 * @param h Handler that receives the notification message. 1588 * @param what User-defined message code. 1589 * @param obj User object. 1590 */ registerForInCallVoicePrivacyOff(Handler h, int what, Object obj)1591 public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){ 1592 mInCallVoicePrivacyOffRegistrants.addUnique(h, what, obj); 1593 } 1594 1595 /** 1596 * Unregister for notifications when a sInCall VoicePrivacy is disabled 1597 * 1598 * @param h Handler to be removed from the registrant list. 1599 */ unregisterForInCallVoicePrivacyOff(Handler h)1600 public void unregisterForInCallVoicePrivacyOff(Handler h){ 1601 mInCallVoicePrivacyOffRegistrants.remove(h); 1602 } 1603 1604 /** 1605 * Register for notifications when CDMA call waiting comes 1606 * 1607 * @param h Handler that receives the notification message. 1608 * @param what User-defined message code. 1609 * @param obj User object. 1610 */ registerForCallWaiting(Handler h, int what, Object obj)1611 public void registerForCallWaiting(Handler h, int what, Object obj){ 1612 mCallWaitingRegistrants.addUnique(h, what, obj); 1613 } 1614 1615 /** 1616 * Unregister for notifications when CDMA Call waiting comes 1617 * @param h Handler to be removed from the registrant list. 1618 */ unregisterForCallWaiting(Handler h)1619 public void unregisterForCallWaiting(Handler h){ 1620 mCallWaitingRegistrants.remove(h); 1621 } 1622 1623 1624 /** 1625 * Register for signal information notifications from the network. 1626 * Message.obj will contain an AsyncResult. 1627 * AsyncResult.result will be a SuppServiceNotification instance. 1628 * 1629 * @param h Handler that receives the notification message. 1630 * @param what User-defined message code. 1631 * @param obj User object. 1632 */ 1633 registerForSignalInfo(Handler h, int what, Object obj)1634 public void registerForSignalInfo(Handler h, int what, Object obj){ 1635 mSignalInfoRegistrants.addUnique(h, what, obj); 1636 } 1637 1638 /** 1639 * Unregisters for signal information notifications. 1640 * Extraneous calls are tolerated silently 1641 * 1642 * @param h Handler to be removed from the registrant list. 1643 */ unregisterForSignalInfo(Handler h)1644 public void unregisterForSignalInfo(Handler h){ 1645 mSignalInfoRegistrants.remove(h); 1646 } 1647 1648 /** 1649 * Register for display information notifications from the network. 1650 * Message.obj will contain an AsyncResult. 1651 * AsyncResult.result will be a SuppServiceNotification instance. 1652 * 1653 * @param h Handler that receives the notification message. 1654 * @param what User-defined message code. 1655 * @param obj User object. 1656 */ registerForDisplayInfo(Handler h, int what, Object obj)1657 public void registerForDisplayInfo(Handler h, int what, Object obj){ 1658 mDisplayInfoRegistrants.addUnique(h, what, obj); 1659 } 1660 1661 /** 1662 * Unregisters for display information notifications. 1663 * Extraneous calls are tolerated silently 1664 * 1665 * @param h Handler to be removed from the registrant list. 1666 */ unregisterForDisplayInfo(Handler h)1667 public void unregisterForDisplayInfo(Handler h) { 1668 mDisplayInfoRegistrants.remove(h); 1669 } 1670 1671 /** 1672 * Register for notifications when CDMA OTA Provision status change 1673 * 1674 * @param h Handler that receives the notification message. 1675 * @param what User-defined message code. 1676 * @param obj User object. 1677 */ registerForCdmaOtaStatusChange(Handler h, int what, Object obj)1678 public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj){ 1679 mCdmaOtaStatusChangeRegistrants.addUnique(h, what, obj); 1680 } 1681 1682 /** 1683 * Unregister for notifications when CDMA OTA Provision status change 1684 * @param h Handler to be removed from the registrant list. 1685 */ unregisterForCdmaOtaStatusChange(Handler h)1686 public void unregisterForCdmaOtaStatusChange(Handler h){ 1687 mCdmaOtaStatusChangeRegistrants.remove(h); 1688 } 1689 1690 /** 1691 * Registration point for subscription info ready 1692 * @param h handler to notify 1693 * @param what what code of message when delivered 1694 * @param obj placed in Message.obj 1695 */ registerForSubscriptionInfoReady(Handler h, int what, Object obj)1696 public void registerForSubscriptionInfoReady(Handler h, int what, Object obj){ 1697 mSubscriptionInfoReadyRegistrants.addUnique(h, what, obj); 1698 } 1699 1700 /** 1701 * Unregister for notifications for subscription info 1702 * @param h Handler to be removed from the registrant list. 1703 */ unregisterForSubscriptionInfoReady(Handler h)1704 public void unregisterForSubscriptionInfoReady(Handler h){ 1705 mSubscriptionInfoReadyRegistrants.remove(h); 1706 } 1707 1708 /** 1709 * Sets an event to be fired when the telephony system processes 1710 * a post-dial character on an outgoing call.<p> 1711 * 1712 * Messages of type <code>what</code> will be sent to <code>h</code>. 1713 * The <code>obj</code> field of these Message's will be instances of 1714 * <code>AsyncResult</code>. <code>Message.obj.result</code> will be 1715 * a Connection object.<p> 1716 * 1717 * Message.arg1 will be the post dial character being processed, 1718 * or 0 ('\0') if end of string.<p> 1719 * 1720 * If Connection.getPostDialState() == WAIT, 1721 * the application must call 1722 * {@link com.android.internal.telephony.Connection#proceedAfterWaitChar() 1723 * Connection.proceedAfterWaitChar()} or 1724 * {@link com.android.internal.telephony.Connection#cancelPostDial() 1725 * Connection.cancelPostDial()} 1726 * for the telephony system to continue playing the post-dial 1727 * DTMF sequence.<p> 1728 * 1729 * If Connection.getPostDialState() == WILD, 1730 * the application must call 1731 * {@link com.android.internal.telephony.Connection#proceedAfterWildChar 1732 * Connection.proceedAfterWildChar()} 1733 * or 1734 * {@link com.android.internal.telephony.Connection#cancelPostDial() 1735 * Connection.cancelPostDial()} 1736 * for the telephony system to continue playing the 1737 * post-dial DTMF sequence.<p> 1738 * 1739 */ registerForPostDialCharacter(Handler h, int what, Object obj)1740 public void registerForPostDialCharacter(Handler h, int what, Object obj){ 1741 mPostDialCharacterRegistrants.addUnique(h, what, obj); 1742 } 1743 unregisterForPostDialCharacter(Handler h)1744 public void unregisterForPostDialCharacter(Handler h){ 1745 mPostDialCharacterRegistrants.remove(h); 1746 } 1747 1748 /** 1749 * Register for TTY mode change notifications from the network. 1750 * Message.obj will contain an AsyncResult. 1751 * AsyncResult.result will be an Integer containing new mode. 1752 * 1753 * @param h Handler that receives the notification message. 1754 * @param what User-defined message code. 1755 * @param obj User object. 1756 */ registerForTtyModeReceived(Handler h, int what, Object obj)1757 public void registerForTtyModeReceived(Handler h, int what, Object obj){ 1758 mTtyModeReceivedRegistrants.addUnique(h, what, obj); 1759 } 1760 1761 /** 1762 * Unregisters for TTY mode change notifications. 1763 * Extraneous calls are tolerated silently 1764 * 1765 * @param h Handler to be removed from the registrant list. 1766 */ unregisterForTtyModeReceived(Handler h)1767 public void unregisterForTtyModeReceived(Handler h) { 1768 mTtyModeReceivedRegistrants.remove(h); 1769 } 1770 1771 /* APIs to access foregroudCalls, backgroudCalls, and ringingCalls 1772 * 1. APIs to access list of calls 1773 * 2. APIs to check if any active call, which has connection other than 1774 * disconnected ones, pleaser refer to Call.isIdle() 1775 * 3. APIs to return first active call 1776 * 4. APIs to return the connections of first active call 1777 * 5. APIs to return other property of first active call 1778 */ 1779 1780 /** 1781 * @return list of all ringing calls 1782 */ getRingingCalls()1783 public List<Call> getRingingCalls() { 1784 return Collections.unmodifiableList(mRingingCalls); 1785 } 1786 1787 /** 1788 * @return list of all foreground calls 1789 */ getForegroundCalls()1790 public List<Call> getForegroundCalls() { 1791 return Collections.unmodifiableList(mForegroundCalls); 1792 } 1793 1794 /** 1795 * @return list of all background calls 1796 */ getBackgroundCalls()1797 public List<Call> getBackgroundCalls() { 1798 return Collections.unmodifiableList(mBackgroundCalls); 1799 } 1800 1801 /** 1802 * Return true if there is at least one active foreground call 1803 */ hasActiveFgCall()1804 public boolean hasActiveFgCall() { 1805 return (getFirstActiveCall(mForegroundCalls) != null); 1806 } 1807 1808 /** 1809 * Return true if there is at least one active foreground call 1810 * on a particular subId or an active sip call 1811 */ hasActiveFgCall(int subId)1812 public boolean hasActiveFgCall(int subId) { 1813 return (getFirstActiveCall(mForegroundCalls, subId) != null); 1814 } 1815 1816 /** 1817 * Return true if there is at least one active background call 1818 */ hasActiveBgCall()1819 public boolean hasActiveBgCall() { 1820 // TODO since hasActiveBgCall may get called often 1821 // better to cache it to improve performance 1822 return (getFirstActiveCall(mBackgroundCalls) != null); 1823 } 1824 1825 /** 1826 * Return true if there is at least one active background call 1827 * on a particular subId or an active sip call 1828 */ hasActiveBgCall(int subId)1829 public boolean hasActiveBgCall(int subId) { 1830 // TODO since hasActiveBgCall may get called often 1831 // better to cache it to improve performance 1832 return (getFirstActiveCall(mBackgroundCalls, subId) != null); 1833 } 1834 1835 /** 1836 * Return true if there is at least one active ringing call 1837 * 1838 */ hasActiveRingingCall()1839 public boolean hasActiveRingingCall() { 1840 return (getFirstActiveCall(mRingingCalls) != null); 1841 } 1842 1843 /** 1844 * Return true if there is at least one active ringing call 1845 */ hasActiveRingingCall(int subId)1846 public boolean hasActiveRingingCall(int subId) { 1847 return (getFirstActiveCall(mRingingCalls, subId) != null); 1848 } 1849 1850 /** 1851 * return the active foreground call from foreground calls 1852 * 1853 * Active call means the call is NOT in Call.State.IDLE 1854 * 1855 * 1. If there is active foreground call, return it 1856 * 2. If there is no active foreground call, return the 1857 * foreground call associated with default phone, which state is IDLE. 1858 * 3. If there is no phone registered at all, return null. 1859 * 1860 */ getActiveFgCall()1861 public Call getActiveFgCall() { 1862 Call call = getFirstNonIdleCall(mForegroundCalls); 1863 if (call == null) { 1864 call = (mDefaultPhone == null) 1865 ? null 1866 : mDefaultPhone.getForegroundCall(); 1867 } 1868 return call; 1869 } 1870 getActiveFgCall(int subId)1871 public Call getActiveFgCall(int subId) { 1872 Call call = getFirstNonIdleCall(mForegroundCalls, subId); 1873 if (call == null) { 1874 Phone phone = getPhone(subId); 1875 call = (phone == null) 1876 ? null 1877 : phone.getForegroundCall(); 1878 } 1879 return call; 1880 } 1881 1882 // Returns the first call that is not in IDLE state. If both active calls 1883 // and disconnecting/disconnected calls exist, return the first active call. getFirstNonIdleCall(List<Call> calls)1884 private Call getFirstNonIdleCall(List<Call> calls) { 1885 Call result = null; 1886 for (Call call : calls) { 1887 if (!call.isIdle()) { 1888 return call; 1889 } else if (call.getState() != Call.State.IDLE) { 1890 if (result == null) result = call; 1891 } 1892 } 1893 return result; 1894 } 1895 1896 // Returns the first call that is not in IDLE state. If both active calls 1897 // and disconnecting/disconnected calls exist, return the first active call. getFirstNonIdleCall(List<Call> calls, int subId)1898 private Call getFirstNonIdleCall(List<Call> calls, int subId) { 1899 Call result = null; 1900 for (Call call : calls) { 1901 if ((call.getPhone().getSubId() == subId) || 1902 (call.getPhone() instanceof SipPhone)) { 1903 if (!call.isIdle()) { 1904 return call; 1905 } else if (call.getState() != Call.State.IDLE) { 1906 if (result == null) result = call; 1907 } 1908 } 1909 } 1910 return result; 1911 } 1912 1913 /** 1914 * return one active background call from background calls 1915 * 1916 * Active call means the call is NOT idle defined by Call.isIdle() 1917 * 1918 * 1. If there is only one active background call, return it 1919 * 2. If there is more than one active background call, return the first one 1920 * 3. If there is no active background call, return the background call 1921 * associated with default phone, which state is IDLE. 1922 * 4. If there is no background call at all, return null. 1923 * 1924 * Complete background calls list can be get by getBackgroundCalls() 1925 */ getFirstActiveBgCall()1926 public Call getFirstActiveBgCall() { 1927 Call call = getFirstNonIdleCall(mBackgroundCalls); 1928 if (call == null) { 1929 call = (mDefaultPhone == null) 1930 ? null 1931 : mDefaultPhone.getBackgroundCall(); 1932 } 1933 return call; 1934 } 1935 1936 /** 1937 * return one active background call from background calls of the 1938 * requested subId. 1939 * 1940 * Active call means the call is NOT idle defined by Call.isIdle() 1941 * 1942 * 1. If there is only one active background call on given sub or 1943 * on SIP Phone, return it 1944 * 2. If there is more than one active background call, return the background call 1945 * associated with the active sub. 1946 * 3. If there is no background call at all, return null. 1947 * 1948 * Complete background calls list can be get by getBackgroundCalls() 1949 */ getFirstActiveBgCall(int subId)1950 public Call getFirstActiveBgCall(int subId) { 1951 Phone phone = getPhone(subId); 1952 if (hasMoreThanOneHoldingCall(subId)) { 1953 return phone.getBackgroundCall(); 1954 } else { 1955 Call call = getFirstNonIdleCall(mBackgroundCalls, subId); 1956 if (call == null) { 1957 call = (phone == null) 1958 ? null 1959 : phone.getBackgroundCall(); 1960 } 1961 return call; 1962 } 1963 } 1964 1965 /** 1966 * return one active ringing call from ringing calls 1967 * 1968 * Active call means the call is NOT idle defined by Call.isIdle() 1969 * 1970 * 1. If there is only one active ringing call, return it 1971 * 2. If there is more than one active ringing call, return the first one 1972 * 3. If there is no active ringing call, return the ringing call 1973 * associated with default phone, which state is IDLE. 1974 * 4. If there is no ringing call at all, return null. 1975 * 1976 * Complete ringing calls list can be get by getRingingCalls() 1977 */ getFirstActiveRingingCall()1978 public Call getFirstActiveRingingCall() { 1979 Call call = getFirstNonIdleCall(mRingingCalls); 1980 if (call == null) { 1981 call = (mDefaultPhone == null) 1982 ? null 1983 : mDefaultPhone.getRingingCall(); 1984 } 1985 return call; 1986 } 1987 getFirstActiveRingingCall(int subId)1988 public Call getFirstActiveRingingCall(int subId) { 1989 Phone phone = getPhone(subId); 1990 Call call = getFirstNonIdleCall(mRingingCalls, subId); 1991 if (call == null) { 1992 call = (phone == null) 1993 ? null 1994 : phone.getRingingCall(); 1995 } 1996 return call; 1997 } 1998 1999 /** 2000 * @return the state of active foreground call 2001 * return IDLE if there is no active foreground call 2002 */ getActiveFgCallState()2003 public Call.State getActiveFgCallState() { 2004 Call fgCall = getActiveFgCall(); 2005 2006 if (fgCall != null) { 2007 return fgCall.getState(); 2008 } 2009 2010 return Call.State.IDLE; 2011 } 2012 getActiveFgCallState(int subId)2013 public Call.State getActiveFgCallState(int subId) { 2014 Call fgCall = getActiveFgCall(subId); 2015 2016 if (fgCall != null) { 2017 return fgCall.getState(); 2018 } 2019 2020 return Call.State.IDLE; 2021 } 2022 2023 /** 2024 * @return the connections of active foreground call 2025 * return empty list if there is no active foreground call 2026 */ getFgCallConnections()2027 public List<Connection> getFgCallConnections() { 2028 Call fgCall = getActiveFgCall(); 2029 if ( fgCall != null) { 2030 return fgCall.getConnections(); 2031 } 2032 return mEmptyConnections; 2033 } 2034 2035 /** 2036 * @return the connections of active foreground call 2037 * return empty list if there is no active foreground call 2038 */ getFgCallConnections(int subId)2039 public List<Connection> getFgCallConnections(int subId) { 2040 Call fgCall = getActiveFgCall(subId); 2041 if ( fgCall != null) { 2042 return fgCall.getConnections(); 2043 } 2044 return mEmptyConnections; 2045 } 2046 2047 /** 2048 * @return the connections of active background call 2049 * return empty list if there is no active background call 2050 */ getBgCallConnections()2051 public List<Connection> getBgCallConnections() { 2052 Call bgCall = getFirstActiveBgCall(); 2053 if ( bgCall != null) { 2054 return bgCall.getConnections(); 2055 } 2056 return mEmptyConnections; 2057 } 2058 2059 /** 2060 * @return the connections of active background call 2061 * return empty list if there is no active background call 2062 */ getBgCallConnections(int subId)2063 public List<Connection> getBgCallConnections(int subId) { 2064 Call bgCall = getFirstActiveBgCall(subId); 2065 if ( bgCall != null) { 2066 return bgCall.getConnections(); 2067 } 2068 return mEmptyConnections; 2069 } 2070 2071 /** 2072 * @return the latest connection of active foreground call 2073 * return null if there is no active foreground call 2074 */ getFgCallLatestConnection()2075 public Connection getFgCallLatestConnection() { 2076 Call fgCall = getActiveFgCall(); 2077 if ( fgCall != null) { 2078 return fgCall.getLatestConnection(); 2079 } 2080 return null; 2081 } 2082 2083 /** 2084 * @return the latest connection of active foreground call 2085 * return null if there is no active foreground call 2086 */ getFgCallLatestConnection(int subId)2087 public Connection getFgCallLatestConnection(int subId) { 2088 Call fgCall = getActiveFgCall(subId); 2089 if ( fgCall != null) { 2090 return fgCall.getLatestConnection(); 2091 } 2092 return null; 2093 } 2094 2095 /** 2096 * @return true if there is at least one Foreground call in disconnected state 2097 */ hasDisconnectedFgCall()2098 public boolean hasDisconnectedFgCall() { 2099 return (getFirstCallOfState(mForegroundCalls, Call.State.DISCONNECTED) != null); 2100 } 2101 2102 /** 2103 * @return true if there is at least one Foreground call in disconnected state 2104 */ hasDisconnectedFgCall(int subId)2105 public boolean hasDisconnectedFgCall(int subId) { 2106 return (getFirstCallOfState(mForegroundCalls, Call.State.DISCONNECTED, 2107 subId) != null); 2108 } 2109 2110 /** 2111 * @return true if there is at least one background call in disconnected state 2112 */ hasDisconnectedBgCall()2113 public boolean hasDisconnectedBgCall() { 2114 return (getFirstCallOfState(mBackgroundCalls, Call.State.DISCONNECTED) != null); 2115 } 2116 2117 /** 2118 * @return true if there is at least one background call in disconnected state 2119 */ hasDisconnectedBgCall(int subId)2120 public boolean hasDisconnectedBgCall(int subId) { 2121 return (getFirstCallOfState(mBackgroundCalls, Call.State.DISCONNECTED, 2122 subId) != null); 2123 } 2124 2125 2126 /** 2127 * @return the first active call from a call list 2128 */ getFirstActiveCall(ArrayList<Call> calls)2129 private Call getFirstActiveCall(ArrayList<Call> calls) { 2130 for (Call call : calls) { 2131 if (!call.isIdle()) { 2132 return call; 2133 } 2134 } 2135 return null; 2136 } 2137 2138 /** 2139 * @return the first active call from a call list 2140 */ getFirstActiveCall(ArrayList<Call> calls, int subId)2141 private Call getFirstActiveCall(ArrayList<Call> calls, int subId) { 2142 for (Call call : calls) { 2143 if ((!call.isIdle()) && ((call.getPhone().getSubId() == subId) || 2144 (call.getPhone() instanceof SipPhone))) { 2145 return call; 2146 } 2147 } 2148 return null; 2149 } 2150 2151 /** 2152 * @return the first call in a the Call.state from a call list 2153 */ getFirstCallOfState(ArrayList<Call> calls, Call.State state)2154 private Call getFirstCallOfState(ArrayList<Call> calls, Call.State state) { 2155 for (Call call : calls) { 2156 if (call.getState() == state) { 2157 return call; 2158 } 2159 } 2160 return null; 2161 } 2162 2163 /** 2164 * @return the first call in a the Call.state from a call list 2165 */ getFirstCallOfState(ArrayList<Call> calls, Call.State state, int subId)2166 private Call getFirstCallOfState(ArrayList<Call> calls, Call.State state, 2167 int subId) { 2168 for (Call call : calls) { 2169 if ((call.getState() == state) || 2170 ((call.getPhone().getSubId() == subId) || 2171 (call.getPhone() instanceof SipPhone))) { 2172 return call; 2173 } 2174 } 2175 return null; 2176 } 2177 hasMoreThanOneRingingCall()2178 private boolean hasMoreThanOneRingingCall() { 2179 int count = 0; 2180 for (Call call : mRingingCalls) { 2181 if (call.getState().isRinging()) { 2182 if (++count > 1) return true; 2183 } 2184 } 2185 return false; 2186 } 2187 2188 /** 2189 * @return true if more than one active ringing call exists on 2190 * the active subId. 2191 * This checks for the active calls on provided 2192 * subId and also active calls on SIP Phone. 2193 * 2194 */ hasMoreThanOneRingingCall(int subId)2195 private boolean hasMoreThanOneRingingCall(int subId) { 2196 int count = 0; 2197 for (Call call : mRingingCalls) { 2198 if ((call.getState().isRinging()) && 2199 ((call.getPhone().getSubId() == subId) || 2200 (call.getPhone() instanceof SipPhone))) { 2201 if (++count > 1) return true; 2202 } 2203 } 2204 return false; 2205 } 2206 2207 /** 2208 * @return true if more than one active background call exists on 2209 * the provided subId. 2210 * This checks for the background calls on provided 2211 * subId and also background calls on SIP Phone. 2212 * 2213 */ hasMoreThanOneHoldingCall(int subId)2214 private boolean hasMoreThanOneHoldingCall(int subId) { 2215 int count = 0; 2216 for (Call call : mBackgroundCalls) { 2217 if ((call.getState() == Call.State.HOLDING) && 2218 ((call.getPhone().getSubId() == subId) || 2219 (call.getPhone() instanceof SipPhone))) { 2220 if (++count > 1) return true; 2221 } 2222 } 2223 return false; 2224 } 2225 2226 /* FIXME Taken from klp-sprout-dev but setAudioMode was removed in L. 2227 private boolean isServiceStateInService() { 2228 boolean bInService = false; 2229 2230 for (Phone phone : mPhones) { 2231 bInService = (phone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE); 2232 if (bInService) { 2233 break; 2234 } 2235 } 2236 2237 if (VDBG) Rlog.d(LOG_TAG, "[isServiceStateInService] bInService = " + bInService); 2238 return bInService; 2239 } 2240 */ 2241 2242 private class CallManagerHandler extends Handler { 2243 @Override handleMessage(Message msg)2244 public void handleMessage(Message msg) { 2245 2246 switch (msg.what) { 2247 case EVENT_DISCONNECT: 2248 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_DISCONNECT)"); 2249 mDisconnectRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2250 // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L. 2251 //mIsEccDialing = false; 2252 break; 2253 case EVENT_PRECISE_CALL_STATE_CHANGED: 2254 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_PRECISE_CALL_STATE_CHANGED)"); 2255 mPreciseCallStateRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2256 break; 2257 case EVENT_NEW_RINGING_CONNECTION: 2258 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_NEW_RINGING_CONNECTION)"); 2259 Connection c = (Connection) ((AsyncResult) msg.obj).result; 2260 int subId = c.getCall().getPhone().getSubId(); 2261 if (getActiveFgCallState(subId).isDialing() || hasMoreThanOneRingingCall()) { 2262 try { 2263 Rlog.d(LOG_TAG, "silently drop incoming call: " + c.getCall()); 2264 c.getCall().hangup(); 2265 } catch (CallStateException e) { 2266 Rlog.w(LOG_TAG, "new ringing connection", e); 2267 } 2268 } else { 2269 mNewRingingConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2270 } 2271 break; 2272 case EVENT_UNKNOWN_CONNECTION: 2273 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_UNKNOWN_CONNECTION)"); 2274 mUnknownConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2275 break; 2276 case EVENT_INCOMING_RING: 2277 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_INCOMING_RING)"); 2278 // The event may come from RIL who's not aware of an ongoing fg call 2279 if (!hasActiveFgCall()) { 2280 mIncomingRingRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2281 } 2282 break; 2283 case EVENT_RINGBACK_TONE: 2284 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RINGBACK_TONE)"); 2285 mRingbackToneRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2286 break; 2287 case EVENT_IN_CALL_VOICE_PRIVACY_ON: 2288 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_ON)"); 2289 mInCallVoicePrivacyOnRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2290 break; 2291 case EVENT_IN_CALL_VOICE_PRIVACY_OFF: 2292 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_OFF)"); 2293 mInCallVoicePrivacyOffRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2294 break; 2295 case EVENT_CALL_WAITING: 2296 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_CALL_WAITING)"); 2297 mCallWaitingRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2298 break; 2299 case EVENT_DISPLAY_INFO: 2300 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_DISPLAY_INFO)"); 2301 mDisplayInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2302 break; 2303 case EVENT_SIGNAL_INFO: 2304 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SIGNAL_INFO)"); 2305 mSignalInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2306 break; 2307 case EVENT_CDMA_OTA_STATUS_CHANGE: 2308 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_CDMA_OTA_STATUS_CHANGE)"); 2309 mCdmaOtaStatusChangeRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2310 break; 2311 case EVENT_RESEND_INCALL_MUTE: 2312 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RESEND_INCALL_MUTE)"); 2313 mResendIncallMuteRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2314 break; 2315 case EVENT_MMI_INITIATE: 2316 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_MMI_INITIATE)"); 2317 mMmiInitiateRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2318 break; 2319 case EVENT_MMI_COMPLETE: 2320 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_MMI_COMPLETE)"); 2321 mMmiCompleteRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2322 break; 2323 case EVENT_ECM_TIMER_RESET: 2324 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_ECM_TIMER_RESET)"); 2325 mEcmTimerResetRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2326 break; 2327 case EVENT_SUBSCRIPTION_INFO_READY: 2328 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SUBSCRIPTION_INFO_READY)"); 2329 mSubscriptionInfoReadyRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2330 break; 2331 case EVENT_SUPP_SERVICE_FAILED: 2332 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SUPP_SERVICE_FAILED)"); 2333 mSuppServiceFailedRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2334 break; 2335 case EVENT_SERVICE_STATE_CHANGED: 2336 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SERVICE_STATE_CHANGED)"); 2337 mServiceStateChangedRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2338 // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L. 2339 //setAudioMode(); 2340 break; 2341 case EVENT_POST_DIAL_CHARACTER: 2342 // we need send the character that is being processed in msg.arg1 2343 // so can't use notifyRegistrants() 2344 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_POST_DIAL_CHARACTER)"); 2345 for(int i=0; i < mPostDialCharacterRegistrants.size(); i++) { 2346 Message notifyMsg; 2347 notifyMsg = ((Registrant)mPostDialCharacterRegistrants.get(i)).messageForRegistrant(); 2348 notifyMsg.obj = msg.obj; 2349 notifyMsg.arg1 = msg.arg1; 2350 notifyMsg.sendToTarget(); 2351 } 2352 break; 2353 case EVENT_ONHOLD_TONE: 2354 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_ONHOLD_TONE)"); 2355 mOnHoldToneRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2356 break; 2357 case EVENT_TTY_MODE_RECEIVED: 2358 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_TTY_MODE_RECEIVED)"); 2359 mTtyModeReceivedRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2360 break; 2361 /* FIXME Taken from klp-sprout-dev but setAudioMode was removed in L. 2362 case EVENT_RADIO_OFF_OR_NOT_AVAILABLE: 2363 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RADIO_OFF_OR_NOT_AVAILABLE)"); 2364 setAudioMode(); 2365 break; 2366 */ 2367 } 2368 } 2369 }; 2370 2371 @Override toString()2372 public String toString() { 2373 Call call; 2374 StringBuilder b = new StringBuilder(); 2375 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) { 2376 b.append("CallManager {"); 2377 b.append("\nstate = " + getState(i)); 2378 call = getActiveFgCall(i); 2379 if (call != null) { 2380 b.append("\n- Foreground: " + getActiveFgCallState(i)); 2381 b.append(" from " + call.getPhone()); 2382 b.append("\n Conn: ").append(getFgCallConnections(i)); 2383 } 2384 call = getFirstActiveBgCall(i); 2385 if (call != null) { 2386 b.append("\n- Background: " + call.getState()); 2387 b.append(" from " + call.getPhone()); 2388 b.append("\n Conn: ").append(getBgCallConnections(i)); 2389 } 2390 call = getFirstActiveRingingCall(i); 2391 if (call != null) { 2392 b.append("\n- Ringing: " +call.getState()); 2393 b.append(" from " + call.getPhone()); 2394 } 2395 } 2396 2397 for (Phone phone : getAllPhones()) { 2398 if (phone != null) { 2399 b.append("\nPhone: " + phone + ", name = " + phone.getPhoneName() 2400 + ", state = " + phone.getState()); 2401 call = phone.getForegroundCall(); 2402 if (call != null) { 2403 b.append("\n- Foreground: ").append(call); 2404 } 2405 call = phone.getBackgroundCall(); 2406 if (call != null) { 2407 b.append(" Background: ").append(call); 2408 } 2409 call = phone.getRingingCall(); 2410 if (call != null) { 2411 b.append(" Ringing: ").append(call); 2412 } 2413 } 2414 } 2415 b.append("\n}"); 2416 return b.toString(); 2417 } 2418 } 2419