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