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