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