1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony; 18 19 import com.android.internal.telephony.sip.SipPhone; 20 21 import android.content.Context; 22 import android.media.AudioManager; 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.telephony.PhoneStateListener; 29 import android.telephony.ServiceState; 30 import android.util.Log; 31 32 import java.util.ArrayList; 33 import java.util.Collections; 34 import java.util.List; 35 36 37 38 /** 39 * @hide 40 * 41 * CallManager class provides an abstract layer for PhoneApp to access 42 * and control calls. It implements Phone interface. 43 * 44 * CallManager provides call and connection control as well as 45 * channel capability. 46 * 47 * There are three categories of APIs CallManager provided 48 * 49 * 1. Call control and operation, such as dial() and hangup() 50 * 2. Channel capabilities, such as CanConference() 51 * 3. Register notification 52 * 53 * 54 */ 55 public final class CallManager { 56 57 private static final String LOG_TAG ="CallManager"; 58 private static final boolean DBG = true; 59 private static final boolean VDBG = false; 60 61 private static final int EVENT_DISCONNECT = 100; 62 private static final int EVENT_PRECISE_CALL_STATE_CHANGED = 101; 63 private static final int EVENT_NEW_RINGING_CONNECTION = 102; 64 private static final int EVENT_UNKNOWN_CONNECTION = 103; 65 private static final int EVENT_INCOMING_RING = 104; 66 private static final int EVENT_RINGBACK_TONE = 105; 67 private static final int EVENT_IN_CALL_VOICE_PRIVACY_ON = 106; 68 private static final int EVENT_IN_CALL_VOICE_PRIVACY_OFF = 107; 69 private static final int EVENT_CALL_WAITING = 108; 70 private static final int EVENT_DISPLAY_INFO = 109; 71 private static final int EVENT_SIGNAL_INFO = 110; 72 private static final int EVENT_CDMA_OTA_STATUS_CHANGE = 111; 73 private static final int EVENT_RESEND_INCALL_MUTE = 112; 74 private static final int EVENT_MMI_INITIATE = 113; 75 private static final int EVENT_MMI_COMPLETE = 114; 76 private static final int EVENT_ECM_TIMER_RESET = 115; 77 private static final int EVENT_SUBSCRIPTION_INFO_READY = 116; 78 private static final int EVENT_SUPP_SERVICE_FAILED = 117; 79 private static final int EVENT_SERVICE_STATE_CHANGED = 118; 80 private static final int EVENT_POST_DIAL_CHARACTER = 119; 81 82 // Singleton instance 83 private static final CallManager INSTANCE = new CallManager(); 84 85 // list of registered phones, which are PhoneBase objs 86 private final ArrayList<Phone> mPhones; 87 88 // list of supported ringing calls 89 private final ArrayList<Call> mRingingCalls; 90 91 // list of supported background calls 92 private final ArrayList<Call> mBackgroundCalls; 93 94 // list of supported foreground calls 95 private final ArrayList<Call> mForegroundCalls; 96 97 // empty connection list 98 private final ArrayList<Connection> emptyConnections = new ArrayList<Connection>(); 99 100 // default phone as the first phone registered, which is PhoneBase obj 101 private Phone mDefaultPhone; 102 103 // state registrants 104 protected final RegistrantList mPreciseCallStateRegistrants 105 = new RegistrantList(); 106 107 protected final RegistrantList mNewRingingConnectionRegistrants 108 = new RegistrantList(); 109 110 protected final RegistrantList mIncomingRingRegistrants 111 = new RegistrantList(); 112 113 protected final RegistrantList mDisconnectRegistrants 114 = new RegistrantList(); 115 116 protected final RegistrantList mMmiRegistrants 117 = new RegistrantList(); 118 119 protected final RegistrantList mUnknownConnectionRegistrants 120 = new RegistrantList(); 121 122 protected final RegistrantList mRingbackToneRegistrants 123 = new RegistrantList(); 124 125 protected final RegistrantList mInCallVoicePrivacyOnRegistrants 126 = new RegistrantList(); 127 128 protected final RegistrantList mInCallVoicePrivacyOffRegistrants 129 = new RegistrantList(); 130 131 protected final RegistrantList mCallWaitingRegistrants 132 = new RegistrantList(); 133 134 protected final RegistrantList mDisplayInfoRegistrants 135 = new RegistrantList(); 136 137 protected final RegistrantList mSignalInfoRegistrants 138 = new RegistrantList(); 139 140 protected final RegistrantList mCdmaOtaStatusChangeRegistrants 141 = new RegistrantList(); 142 143 protected final RegistrantList mResendIncallMuteRegistrants 144 = new RegistrantList(); 145 146 protected final RegistrantList mMmiInitiateRegistrants 147 = new RegistrantList(); 148 149 protected final RegistrantList mMmiCompleteRegistrants 150 = new RegistrantList(); 151 152 protected final RegistrantList mEcmTimerResetRegistrants 153 = new RegistrantList(); 154 155 protected final RegistrantList mSubscriptionInfoReadyRegistrants 156 = new RegistrantList(); 157 158 protected final RegistrantList mSuppServiceFailedRegistrants 159 = new RegistrantList(); 160 161 protected final RegistrantList mServiceStateChangedRegistrants 162 = new RegistrantList(); 163 164 protected final RegistrantList mPostDialCharacterRegistrants 165 = new RegistrantList(); 166 167 private CallManager() { 168 mPhones = new ArrayList<Phone>(); 169 mRingingCalls = new ArrayList<Call>(); 170 mBackgroundCalls = new ArrayList<Call>(); 171 mForegroundCalls = new ArrayList<Call>(); 172 mDefaultPhone = null; 173 } 174 175 /** 176 * get singleton instance of CallManager 177 * @return CallManager 178 */ 179 public static CallManager getInstance() { 180 return INSTANCE; 181 } 182 183 /** 184 * Get the corresponding PhoneBase obj 185 * 186 * @param phone a Phone object 187 * @return the corresponding PhoneBase obj in Phone if Phone 188 * is a PhoneProxy obj 189 * or the Phone itself if Phone is not a PhoneProxy obj 190 */ 191 private static Phone getPhoneBase(Phone phone) { 192 if (phone instanceof PhoneProxy) { 193 return phone.getForegroundCall().getPhone(); 194 } 195 return phone; 196 } 197 198 /** 199 * Check if two phones refer to the same PhoneBase obj 200 * 201 * Note: PhoneBase, not PhoneProxy, is to be used inside of CallManager 202 * 203 * Both PhoneBase and PhoneProxy implement Phone interface, so 204 * they have same phone APIs, such as dial(). The real implementation, for 205 * example in GSM, is in GSMPhone as extend from PhoneBase, so that 206 * foregroundCall.getPhone() returns GSMPhone obj. On the other hand, 207 * PhoneFactory.getDefaultPhone() returns PhoneProxy obj, which has a class 208 * member of GSMPhone. 209 * 210 * So for phone returned by PhoneFacotry, which is used by PhoneApp, 211 * phone.getForegroundCall().getPhone() != phone 212 * but 213 * isSamePhone(phone, phone.getForegroundCall().getPhone()) == true 214 * 215 * @param p1 is the first Phone obj 216 * @param p2 is the second Phone obj 217 * @return true if p1 and p2 refer to the same phone 218 */ 219 public static boolean isSamePhone(Phone p1, Phone p2) { 220 return (getPhoneBase(p1) == getPhoneBase(p2)); 221 } 222 223 /** 224 * Returns all the registered phone objects. 225 * @return all the registered phone objects. 226 */ 227 public List<Phone> getAllPhones() { 228 return Collections.unmodifiableList(mPhones); 229 } 230 231 /** 232 * Get current coarse-grained voice call state. 233 * If the Call Manager has an active call and call waiting occurs, 234 * then the phone state is RINGING not OFFHOOK 235 * 236 */ 237 public Phone.State getState() { 238 Phone.State s = Phone.State.IDLE; 239 240 for (Phone phone : mPhones) { 241 if (phone.getState() == Phone.State.RINGING) { 242 s = Phone.State.RINGING; 243 } else if (phone.getState() == Phone.State.OFFHOOK) { 244 if (s == Phone.State.IDLE) s = Phone.State.OFFHOOK; 245 } 246 } 247 return s; 248 } 249 250 /** 251 * @return the service state of CallManager, which represents the 252 * highest priority state of all the service states of phones 253 * 254 * The priority is defined as 255 * 256 * STATE_IN_SERIVCE > STATE_OUT_OF_SERIVCE > STATE_EMERGENCY > STATE_POWER_OFF 257 * 258 */ 259 260 public int getServiceState() { 261 int resultState = ServiceState.STATE_OUT_OF_SERVICE; 262 263 for (Phone phone : mPhones) { 264 int serviceState = phone.getServiceState().getState(); 265 if (serviceState == ServiceState.STATE_IN_SERVICE) { 266 // IN_SERVICE has the highest priority 267 resultState = serviceState; 268 break; 269 } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE) { 270 // OUT_OF_SERVICE replaces EMERGENCY_ONLY and POWER_OFF 271 // Note: EMERGENCY_ONLY is not in use at this moment 272 if ( resultState == ServiceState.STATE_EMERGENCY_ONLY || 273 resultState == ServiceState.STATE_POWER_OFF) { 274 resultState = serviceState; 275 } 276 } else if (serviceState == ServiceState.STATE_EMERGENCY_ONLY) { 277 if (resultState == ServiceState.STATE_POWER_OFF) { 278 resultState = serviceState; 279 } 280 } 281 } 282 return resultState; 283 } 284 285 /** 286 * Register phone to CallManager 287 * @param phone to be registered 288 * @return true if register successfully 289 */ 290 public boolean registerPhone(Phone phone) { 291 Phone basePhone = getPhoneBase(phone); 292 293 if (basePhone != null && !mPhones.contains(basePhone)) { 294 295 if (DBG) { 296 Log.d(LOG_TAG, "registerPhone(" + 297 phone.getPhoneName() + " " + phone + ")"); 298 } 299 300 if (mPhones.isEmpty()) { 301 mDefaultPhone = basePhone; 302 } 303 mPhones.add(basePhone); 304 mRingingCalls.add(basePhone.getRingingCall()); 305 mBackgroundCalls.add(basePhone.getBackgroundCall()); 306 mForegroundCalls.add(basePhone.getForegroundCall()); 307 registerForPhoneStates(basePhone); 308 return true; 309 } 310 return false; 311 } 312 313 /** 314 * unregister phone from CallManager 315 * @param phone to be unregistered 316 */ 317 public void unregisterPhone(Phone phone) { 318 Phone basePhone = getPhoneBase(phone); 319 320 if (basePhone != null && mPhones.contains(basePhone)) { 321 322 if (DBG) { 323 Log.d(LOG_TAG, "unregisterPhone(" + 324 phone.getPhoneName() + " " + phone + ")"); 325 } 326 327 mPhones.remove(basePhone); 328 mRingingCalls.remove(basePhone.getRingingCall()); 329 mBackgroundCalls.remove(basePhone.getBackgroundCall()); 330 mForegroundCalls.remove(basePhone.getForegroundCall()); 331 unregisterForPhoneStates(basePhone); 332 if (basePhone == mDefaultPhone) { 333 if (mPhones.isEmpty()) { 334 mDefaultPhone = null; 335 } else { 336 mDefaultPhone = mPhones.get(0); 337 } 338 } 339 } 340 } 341 342 /** 343 * return the default phone or null if no phone available 344 */ 345 public Phone getDefaultPhone() { 346 return mDefaultPhone; 347 } 348 349 /** 350 * @return the phone associated with the foreground call 351 */ 352 public Phone getFgPhone() { 353 return getActiveFgCall().getPhone(); 354 } 355 356 /** 357 * @return the phone associated with the background call 358 */ 359 public Phone getBgPhone() { 360 return getFirstActiveBgCall().getPhone(); 361 } 362 363 /** 364 * @return the phone associated with the ringing call 365 */ 366 public Phone getRingingPhone() { 367 return getFirstActiveRingingCall().getPhone(); 368 } 369 370 public void setAudioMode() { 371 Context context = getContext(); 372 if (context == null) return; 373 AudioManager audioManager = (AudioManager) 374 context.getSystemService(Context.AUDIO_SERVICE); 375 376 int mode = AudioManager.MODE_NORMAL; 377 switch (getState()) { 378 case RINGING: 379 mode = AudioManager.MODE_RINGTONE; 380 break; 381 case OFFHOOK: 382 Phone fgPhone = getFgPhone(); 383 // Enable IN_CALL mode while foreground call is in DIALING, 384 // ALERTING, ACTIVE and DISCONNECTING state and not from sipPhone 385 if (getActiveFgCallState() != Call.State.IDLE 386 && getActiveFgCallState() != Call.State.DISCONNECTED 387 && !(fgPhone instanceof SipPhone)) { 388 mode = AudioManager.MODE_IN_CALL; 389 } 390 break; 391 } 392 // calling audioManager.setMode() multiple times in a short period of 393 // time seems to break the audio recorder in in-call mode 394 if (audioManager.getMode() != mode) audioManager.setMode(mode); 395 } 396 397 private Context getContext() { 398 Phone defaultPhone = getDefaultPhone(); 399 return ((defaultPhone == null) ? null : defaultPhone.getContext()); 400 } 401 402 private void registerForPhoneStates(Phone phone) { 403 // for common events supported by all phones 404 phone.registerForPreciseCallStateChanged(mHandler, EVENT_PRECISE_CALL_STATE_CHANGED, null); 405 phone.registerForDisconnect(mHandler, EVENT_DISCONNECT, null); 406 phone.registerForNewRingingConnection(mHandler, EVENT_NEW_RINGING_CONNECTION, null); 407 phone.registerForUnknownConnection(mHandler, EVENT_UNKNOWN_CONNECTION, null); 408 phone.registerForIncomingRing(mHandler, EVENT_INCOMING_RING, null); 409 phone.registerForRingbackTone(mHandler, EVENT_RINGBACK_TONE, null); 410 phone.registerForInCallVoicePrivacyOn(mHandler, EVENT_IN_CALL_VOICE_PRIVACY_ON, null); 411 phone.registerForInCallVoicePrivacyOff(mHandler, EVENT_IN_CALL_VOICE_PRIVACY_OFF, null); 412 phone.registerForDisplayInfo(mHandler, EVENT_DISPLAY_INFO, null); 413 phone.registerForSignalInfo(mHandler, EVENT_SIGNAL_INFO, null); 414 phone.registerForResendIncallMute(mHandler, EVENT_RESEND_INCALL_MUTE, null); 415 phone.registerForMmiInitiate(mHandler, EVENT_MMI_INITIATE, null); 416 phone.registerForMmiComplete(mHandler, EVENT_MMI_COMPLETE, null); 417 phone.registerForSuppServiceFailed(mHandler, EVENT_SUPP_SERVICE_FAILED, null); 418 phone.registerForServiceStateChanged(mHandler, EVENT_SERVICE_STATE_CHANGED, null); 419 420 // for events supported only by GSM and CDMA phone 421 if (phone.getPhoneType() == Phone.PHONE_TYPE_GSM || 422 phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) { 423 phone.setOnPostDialCharacter(mHandler, EVENT_POST_DIAL_CHARACTER, null); 424 } 425 426 // for events supported only by CDMA phone 427 if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA ){ 428 phone.registerForCdmaOtaStatusChange(mHandler, EVENT_CDMA_OTA_STATUS_CHANGE, null); 429 phone.registerForSubscriptionInfoReady(mHandler, EVENT_SUBSCRIPTION_INFO_READY, null); 430 phone.registerForCallWaiting(mHandler, EVENT_CALL_WAITING, null); 431 phone.registerForEcmTimerReset(mHandler, EVENT_ECM_TIMER_RESET, null); 432 } 433 } 434 435 private void unregisterForPhoneStates(Phone phone) { 436 // for common events supported by all phones 437 phone.unregisterForPreciseCallStateChanged(mHandler); 438 phone.unregisterForDisconnect(mHandler); 439 phone.unregisterForNewRingingConnection(mHandler); 440 phone.unregisterForUnknownConnection(mHandler); 441 phone.unregisterForIncomingRing(mHandler); 442 phone.unregisterForRingbackTone(mHandler); 443 phone.unregisterForInCallVoicePrivacyOn(mHandler); 444 phone.unregisterForInCallVoicePrivacyOff(mHandler); 445 phone.unregisterForDisplayInfo(mHandler); 446 phone.unregisterForSignalInfo(mHandler); 447 phone.unregisterForResendIncallMute(mHandler); 448 phone.unregisterForMmiInitiate(mHandler); 449 phone.unregisterForMmiComplete(mHandler); 450 phone.unregisterForSuppServiceFailed(mHandler); 451 phone.unregisterForServiceStateChanged(mHandler); 452 453 // for events supported only by GSM and CDMA phone 454 if (phone.getPhoneType() == Phone.PHONE_TYPE_GSM || 455 phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) { 456 phone.setOnPostDialCharacter(null, EVENT_POST_DIAL_CHARACTER, null); 457 } 458 459 // for events supported only by CDMA phone 460 if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA ){ 461 phone.unregisterForCdmaOtaStatusChange(mHandler); 462 phone.unregisterForSubscriptionInfoReady(mHandler); 463 phone.unregisterForCallWaiting(mHandler); 464 phone.unregisterForEcmTimerReset(mHandler); 465 } 466 } 467 468 /** 469 * Answers a ringing or waiting call. 470 * 471 * Active call, if any, go on hold. 472 * If active call can't be held, i.e., a background call of the same channel exists, 473 * the active call will be hang up. 474 * 475 * Answering occurs asynchronously, and final notification occurs via 476 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 477 * java.lang.Object) registerForPreciseCallStateChanged()}. 478 * 479 * @exception CallStateException when call is not ringing or waiting 480 */ 481 public void acceptCall(Call ringingCall) throws CallStateException { 482 Phone ringingPhone = ringingCall.getPhone(); 483 484 if (VDBG) { 485 Log.d(LOG_TAG, "acceptCall(" +ringingCall + " from " + ringingCall.getPhone() + ")"); 486 Log.d(LOG_TAG, this.toString()); 487 } 488 489 if ( hasActiveFgCall() ) { 490 Phone activePhone = getActiveFgCall().getPhone(); 491 boolean hasBgCall = ! (activePhone.getBackgroundCall().isIdle()); 492 boolean sameChannel = (activePhone == ringingPhone); 493 494 if (VDBG) { 495 Log.d(LOG_TAG, "hasBgCall: "+ hasBgCall + "sameChannel:" + sameChannel); 496 } 497 498 if (sameChannel && hasBgCall) { 499 getActiveFgCall().hangup(); 500 } else if (!sameChannel && !hasBgCall) { 501 activePhone.switchHoldingAndActive(); 502 } else if (!sameChannel && hasBgCall) { 503 getActiveFgCall().hangup(); 504 } 505 } 506 507 ringingPhone.acceptCall(); 508 509 if (VDBG) { 510 Log.d(LOG_TAG, "End acceptCall(" +ringingCall + ")"); 511 Log.d(LOG_TAG, this.toString()); 512 } 513 } 514 515 /** 516 * Reject (ignore) a ringing call. In GSM, this means UDUB 517 * (User Determined User Busy). Reject occurs asynchronously, 518 * and final notification occurs via 519 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 520 * java.lang.Object) registerForPreciseCallStateChanged()}. 521 * 522 * @exception CallStateException when no call is ringing or waiting 523 */ 524 public void rejectCall(Call ringingCall) throws CallStateException { 525 if (VDBG) { 526 Log.d(LOG_TAG, "rejectCall(" +ringingCall + ")"); 527 Log.d(LOG_TAG, this.toString()); 528 } 529 530 Phone ringingPhone = ringingCall.getPhone(); 531 532 ringingPhone.rejectCall(); 533 534 if (VDBG) { 535 Log.d(LOG_TAG, "End rejectCall(" +ringingCall + ")"); 536 Log.d(LOG_TAG, this.toString()); 537 } 538 } 539 540 /** 541 * Places active call on hold, and makes held call active. 542 * Switch occurs asynchronously and may fail. 543 * 544 * There are 4 scenarios 545 * 1. only active call but no held call, aka, hold 546 * 2. no active call but only held call, aka, unhold 547 * 3. both active and held calls from same phone, aka, swap 548 * 4. active and held calls from different phones, aka, phone swap 549 * 550 * Final notification occurs via 551 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 552 * java.lang.Object) registerForPreciseCallStateChanged()}. 553 * 554 * @exception CallStateException if active call is ringing, waiting, or 555 * dialing/alerting, or heldCall can't be active. 556 * In these cases, this operation may not be performed. 557 */ 558 public void switchHoldingAndActive(Call heldCall) throws CallStateException { 559 Phone activePhone = null; 560 Phone heldPhone = null; 561 562 if (VDBG) { 563 Log.d(LOG_TAG, "switchHoldingAndActive(" +heldCall + ")"); 564 Log.d(LOG_TAG, this.toString()); 565 } 566 567 if (hasActiveFgCall()) { 568 activePhone = getActiveFgCall().getPhone(); 569 } 570 571 if (heldCall != null) { 572 heldPhone = heldCall.getPhone(); 573 } 574 575 if (activePhone != null) { 576 activePhone.switchHoldingAndActive(); 577 } 578 579 if (heldPhone != null && heldPhone != activePhone) { 580 heldPhone.switchHoldingAndActive(); 581 } 582 583 if (VDBG) { 584 Log.d(LOG_TAG, "End switchHoldingAndActive(" +heldCall + ")"); 585 Log.d(LOG_TAG, this.toString()); 586 } 587 } 588 589 /** 590 * Hangup foreground call and resume the specific background call 591 * 592 * Note: this is noop if there is no foreground call or the heldCall is null 593 * 594 * @param heldCall to become foreground 595 * @throws CallStateException 596 */ 597 public void hangupForegroundResumeBackground(Call heldCall) throws CallStateException { 598 Phone foregroundPhone = null; 599 Phone backgroundPhone = null; 600 601 if (VDBG) { 602 Log.d(LOG_TAG, "hangupForegroundResumeBackground(" +heldCall + ")"); 603 Log.d(LOG_TAG, this.toString()); 604 } 605 606 if (hasActiveFgCall()) { 607 foregroundPhone = getFgPhone(); 608 if (heldCall != null) { 609 backgroundPhone = heldCall.getPhone(); 610 if (foregroundPhone == backgroundPhone) { 611 getActiveFgCall().hangup(); 612 } else { 613 // the call to be hangup and resumed belongs to different phones 614 getActiveFgCall().hangup(); 615 switchHoldingAndActive(heldCall); 616 } 617 } 618 } 619 620 if (VDBG) { 621 Log.d(LOG_TAG, "End hangupForegroundResumeBackground(" +heldCall + ")"); 622 Log.d(LOG_TAG, this.toString()); 623 } 624 } 625 626 /** 627 * Whether or not the phone can conference in the current phone 628 * state--that is, one call holding and one call active. 629 * @return true if the phone can conference; false otherwise. 630 */ 631 public boolean canConference(Call heldCall) { 632 Phone activePhone = null; 633 Phone heldPhone = null; 634 635 if (hasActiveFgCall()) { 636 activePhone = getActiveFgCall().getPhone(); 637 } 638 639 if (heldCall != null) { 640 heldPhone = heldCall.getPhone(); 641 } 642 643 return heldPhone.getClass().equals(activePhone.getClass()); 644 } 645 646 /** 647 * Conferences holding and active. Conference occurs asynchronously 648 * and may fail. Final notification occurs via 649 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 650 * java.lang.Object) registerForPreciseCallStateChanged()}. 651 * 652 * @exception CallStateException if canConference() would return false. 653 * In these cases, this operation may not be performed. 654 */ 655 public void conference(Call heldCall) throws CallStateException { 656 657 if (VDBG) { 658 Log.d(LOG_TAG, "conference(" +heldCall + ")"); 659 Log.d(LOG_TAG, this.toString()); 660 } 661 662 663 Phone fgPhone = getFgPhone(); 664 if (fgPhone instanceof SipPhone) { 665 ((SipPhone) fgPhone).conference(heldCall); 666 } else if (canConference(heldCall)) { 667 fgPhone.conference(); 668 } else { 669 throw(new CallStateException("Can't conference foreground and selected background call")); 670 } 671 672 if (VDBG) { 673 Log.d(LOG_TAG, "End conference(" +heldCall + ")"); 674 Log.d(LOG_TAG, this.toString()); 675 } 676 677 } 678 679 /** 680 * Initiate a new voice connection. This happens asynchronously, so you 681 * cannot assume the audio path is connected (or a call index has been 682 * assigned) until PhoneStateChanged notification has occurred. 683 * 684 * @exception CallStateException if a new outgoing call is not currently 685 * possible because no more call slots exist or a call exists that is 686 * dialing, alerting, ringing, or waiting. Other errors are 687 * handled asynchronously. 688 */ 689 public Connection dial(Phone phone, String dialString) throws CallStateException { 690 Phone basePhone = getPhoneBase(phone); 691 Connection result; 692 693 if (VDBG) { 694 Log.d(LOG_TAG, " dial(" + basePhone + ", "+ dialString + ")"); 695 Log.d(LOG_TAG, this.toString()); 696 } 697 698 if ( hasActiveFgCall() ) { 699 Phone activePhone = getActiveFgCall().getPhone(); 700 boolean hasBgCall = !(activePhone.getBackgroundCall().isIdle()); 701 702 if (DBG) { 703 Log.d(LOG_TAG, "hasBgCall: "+ hasBgCall + " sameChannel:" + (activePhone == basePhone)); 704 } 705 706 if (activePhone != basePhone) { 707 if (hasBgCall) { 708 Log.d(LOG_TAG, "Hangup"); 709 getActiveFgCall().hangup(); 710 } else { 711 Log.d(LOG_TAG, "Switch"); 712 activePhone.switchHoldingAndActive(); 713 } 714 } 715 } 716 717 result = basePhone.dial(dialString); 718 719 if (VDBG) { 720 Log.d(LOG_TAG, "End dial(" + basePhone + ", "+ dialString + ")"); 721 Log.d(LOG_TAG, this.toString()); 722 } 723 724 return result; 725 } 726 727 /** 728 * Initiate a new voice connection. This happens asynchronously, so you 729 * cannot assume the audio path is connected (or a call index has been 730 * assigned) until PhoneStateChanged notification has occurred. 731 * 732 * @exception CallStateException if a new outgoing call is not currently 733 * possible because no more call slots exist or a call exists that is 734 * dialing, alerting, ringing, or waiting. Other errors are 735 * handled asynchronously. 736 */ 737 public Connection dial(Phone phone, String dialString, UUSInfo uusInfo) throws CallStateException { 738 return phone.dial(dialString, uusInfo); 739 } 740 741 /** 742 * clear disconnect connection for each phone 743 */ 744 public void clearDisconnected() { 745 for(Phone phone : mPhones) { 746 phone.clearDisconnected(); 747 } 748 } 749 750 /** 751 * Whether or not the phone can do explicit call transfer in the current 752 * phone state--that is, one call holding and one call active. 753 * @return true if the phone can do explicit call transfer; false otherwise. 754 */ 755 public boolean canTransfer(Call heldCall) { 756 Phone activePhone = null; 757 Phone heldPhone = null; 758 759 if (hasActiveFgCall()) { 760 activePhone = getActiveFgCall().getPhone(); 761 } 762 763 if (heldCall != null) { 764 heldPhone = heldCall.getPhone(); 765 } 766 767 return (heldPhone == activePhone && activePhone.canTransfer()); 768 } 769 770 /** 771 * Connects the held call and active call 772 * Disconnects the subscriber from both calls 773 * 774 * Explicit Call Transfer occurs asynchronously 775 * and may fail. Final notification occurs via 776 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 777 * java.lang.Object) registerForPreciseCallStateChanged()}. 778 * 779 * @exception CallStateException if canTransfer() would return false. 780 * In these cases, this operation may not be performed. 781 */ 782 public void explicitCallTransfer(Call heldCall) throws CallStateException { 783 if (VDBG) { 784 Log.d(LOG_TAG, " explicitCallTransfer(" + heldCall + ")"); 785 Log.d(LOG_TAG, this.toString()); 786 } 787 788 if (canTransfer(heldCall)) { 789 heldCall.getPhone().explicitCallTransfer(); 790 } 791 792 if (VDBG) { 793 Log.d(LOG_TAG, "End explicitCallTransfer(" + heldCall + ")"); 794 Log.d(LOG_TAG, this.toString()); 795 } 796 797 } 798 799 /** 800 * Returns a list of MMI codes that are pending for a phone. (They have initiated 801 * but have not yet completed). 802 * Presently there is only ever one. 803 * 804 * Use <code>registerForMmiInitiate</code> 805 * and <code>registerForMmiComplete</code> for change notification. 806 * @return null if phone doesn't have or support mmi code 807 */ 808 public List<? extends MmiCode> getPendingMmiCodes(Phone phone) { 809 Log.e(LOG_TAG, "getPendingMmiCodes not implemented"); 810 return null; 811 } 812 813 /** 814 * Sends user response to a USSD REQUEST message. An MmiCode instance 815 * representing this response is sent to handlers registered with 816 * registerForMmiInitiate. 817 * 818 * @param ussdMessge Message to send in the response. 819 * @return false if phone doesn't support ussd service 820 */ 821 public boolean sendUssdResponse(Phone phone, String ussdMessge) { 822 Log.e(LOG_TAG, "sendUssdResponse not implemented"); 823 return false; 824 } 825 826 /** 827 * Mutes or unmutes the microphone for the active call. The microphone 828 * is automatically unmuted if a call is answered, dialed, or resumed 829 * from a holding state. 830 * 831 * @param muted true to mute the microphone, 832 * false to activate the microphone. 833 */ 834 835 public void setMute(boolean muted) { 836 if (VDBG) { 837 Log.d(LOG_TAG, " setMute(" + muted + ")"); 838 Log.d(LOG_TAG, this.toString()); 839 } 840 841 if (hasActiveFgCall()) { 842 getActiveFgCall().getPhone().setMute(muted); 843 } 844 845 if (VDBG) { 846 Log.d(LOG_TAG, "End setMute(" + muted + ")"); 847 Log.d(LOG_TAG, this.toString()); 848 } 849 } 850 851 /** 852 * Gets current mute status. Use 853 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 854 * java.lang.Object) registerForPreciseCallStateChanged()} 855 * as a change notifcation, although presently phone state changed is not 856 * fired when setMute() is called. 857 * 858 * @return true is muting, false is unmuting 859 */ 860 public boolean getMute() { 861 if (hasActiveFgCall()) { 862 return getActiveFgCall().getPhone().getMute(); 863 } 864 return false; 865 } 866 867 /** 868 * Enables or disables echo suppression. 869 */ 870 public void setEchoSuppressionEnabled(boolean enabled) { 871 if (VDBG) { 872 Log.d(LOG_TAG, " setEchoSuppression(" + enabled + ")"); 873 Log.d(LOG_TAG, this.toString()); 874 } 875 876 if (hasActiveFgCall()) { 877 getActiveFgCall().getPhone().setEchoSuppressionEnabled(enabled); 878 } 879 880 if (VDBG) { 881 Log.d(LOG_TAG, "End setEchoSuppression(" + enabled + ")"); 882 Log.d(LOG_TAG, this.toString()); 883 } 884 } 885 886 /** 887 * Play a DTMF tone on the active call. 888 * 889 * @param c should be one of 0-9, '*' or '#'. Other values will be 890 * silently ignored. 891 * @return false if no active call or the active call doesn't support 892 * dtmf tone 893 */ 894 public boolean sendDtmf(char c) { 895 boolean result = false; 896 897 if (VDBG) { 898 Log.d(LOG_TAG, " sendDtmf(" + c + ")"); 899 Log.d(LOG_TAG, this.toString()); 900 } 901 902 if (hasActiveFgCall()) { 903 getActiveFgCall().getPhone().sendDtmf(c); 904 result = true; 905 } 906 907 if (VDBG) { 908 Log.d(LOG_TAG, "End sendDtmf(" + c + ")"); 909 Log.d(LOG_TAG, this.toString()); 910 } 911 return result; 912 } 913 914 /** 915 * Start to paly a DTMF tone on the active call. 916 * or there is a playing DTMF tone. 917 * @param c should be one of 0-9, '*' or '#'. Other values will be 918 * silently ignored. 919 * 920 * @return false if no active call or the active call doesn't support 921 * dtmf tone 922 */ 923 public boolean startDtmf(char c) { 924 boolean result = false; 925 926 if (VDBG) { 927 Log.d(LOG_TAG, " startDtmf(" + c + ")"); 928 Log.d(LOG_TAG, this.toString()); 929 } 930 931 if (hasActiveFgCall()) { 932 getActiveFgCall().getPhone().startDtmf(c); 933 result = true; 934 } 935 936 if (VDBG) { 937 Log.d(LOG_TAG, "End startDtmf(" + c + ")"); 938 Log.d(LOG_TAG, this.toString()); 939 } 940 941 return result; 942 } 943 944 /** 945 * Stop the playing DTMF tone. Ignored if there is no playing DTMF 946 * tone or no active call. 947 */ 948 public void stopDtmf() { 949 if (VDBG) { 950 Log.d(LOG_TAG, " stopDtmf()" ); 951 Log.d(LOG_TAG, this.toString()); 952 } 953 954 if (hasActiveFgCall()) getFgPhone().stopDtmf(); 955 956 if (VDBG) { 957 Log.d(LOG_TAG, "End stopDtmf()"); 958 Log.d(LOG_TAG, this.toString()); 959 } 960 } 961 962 /** 963 * send burst DTMF tone, it can send the string as single character or multiple character 964 * ignore if there is no active call or not valid digits string. 965 * Valid digit means only includes characters ISO-LATIN characters 0-9, *, # 966 * The difference between sendDtmf and sendBurstDtmf is sendDtmf only sends one character, 967 * this api can send single character and multiple character, also, this api has response 968 * back to caller. 969 * 970 * @param dtmfString is string representing the dialing digit(s) in the active call 971 * @param on the DTMF ON length in milliseconds, or 0 for default 972 * @param off the DTMF OFF length in milliseconds, or 0 for default 973 * @param onComplete is the callback message when the action is processed by BP 974 * 975 */ 976 public boolean sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) { 977 if (hasActiveFgCall()) { 978 getActiveFgCall().getPhone().sendBurstDtmf(dtmfString, on, off, onComplete); 979 return true; 980 } 981 return false; 982 } 983 984 /** 985 * Notifies when a voice connection has disconnected, either due to local 986 * or remote hangup or error. 987 * 988 * Messages received from this will have the following members:<p> 989 * <ul><li>Message.obj will be an AsyncResult</li> 990 * <li>AsyncResult.userObj = obj</li> 991 * <li>AsyncResult.result = a Connection object that is 992 * no longer connected.</li></ul> 993 */ 994 public void registerForDisconnect(Handler h, int what, Object obj) { 995 mDisconnectRegistrants.addUnique(h, what, obj); 996 } 997 998 /** 999 * Unregisters for voice disconnection notification. 1000 * Extraneous calls are tolerated silently 1001 */ 1002 public void unregisterForDisconnect(Handler h){ 1003 mDisconnectRegistrants.remove(h); 1004 } 1005 1006 /** 1007 * Register for getting notifications for change in the Call State {@link Call.State} 1008 * This is called PreciseCallState because the call state is more precise than the 1009 * {@link Phone.State} which can be obtained using the {@link PhoneStateListener} 1010 * 1011 * Resulting events will have an AsyncResult in <code>Message.obj</code>. 1012 * AsyncResult.userData will be set to the obj argument here. 1013 * The <em>h</em> parameter is held only by a weak reference. 1014 */ 1015 public void registerForPreciseCallStateChanged(Handler h, int what, Object obj){ 1016 mPreciseCallStateRegistrants.addUnique(h, what, obj); 1017 } 1018 1019 /** 1020 * Unregisters for voice call state change notifications. 1021 * Extraneous calls are tolerated silently. 1022 */ 1023 public void unregisterForPreciseCallStateChanged(Handler h){ 1024 mPreciseCallStateRegistrants.remove(h); 1025 } 1026 1027 /** 1028 * Notifies when a previously untracked non-ringing/waiting connection has appeared. 1029 * This is likely due to some other entity (eg, SIM card application) initiating a call. 1030 */ 1031 public void registerForUnknownConnection(Handler h, int what, Object obj){ 1032 mUnknownConnectionRegistrants.addUnique(h, what, obj); 1033 } 1034 1035 /** 1036 * Unregisters for unknown connection notifications. 1037 */ 1038 public void unregisterForUnknownConnection(Handler h){ 1039 mUnknownConnectionRegistrants.remove(h); 1040 } 1041 1042 1043 /** 1044 * Notifies when a new ringing or waiting connection has appeared.<p> 1045 * 1046 * Messages received from this: 1047 * Message.obj will be an AsyncResult 1048 * AsyncResult.userObj = obj 1049 * AsyncResult.result = a Connection. <p> 1050 * Please check Connection.isRinging() to make sure the Connection 1051 * has not dropped since this message was posted. 1052 * If Connection.isRinging() is true, then 1053 * Connection.getCall() == Phone.getRingingCall() 1054 */ 1055 public void registerForNewRingingConnection(Handler h, int what, Object obj){ 1056 mNewRingingConnectionRegistrants.addUnique(h, what, obj); 1057 } 1058 1059 /** 1060 * Unregisters for new ringing connection notification. 1061 * Extraneous calls are tolerated silently 1062 */ 1063 1064 public void unregisterForNewRingingConnection(Handler h){ 1065 mNewRingingConnectionRegistrants.remove(h); 1066 } 1067 1068 /** 1069 * Notifies when an incoming call rings.<p> 1070 * 1071 * Messages received from this: 1072 * Message.obj will be an AsyncResult 1073 * AsyncResult.userObj = obj 1074 * AsyncResult.result = a Connection. <p> 1075 */ 1076 public void registerForIncomingRing(Handler h, int what, Object obj){ 1077 mIncomingRingRegistrants.addUnique(h, what, obj); 1078 } 1079 1080 /** 1081 * Unregisters for ring notification. 1082 * Extraneous calls are tolerated silently 1083 */ 1084 1085 public void unregisterForIncomingRing(Handler h){ 1086 mIncomingRingRegistrants.remove(h); 1087 } 1088 1089 /** 1090 * Notifies when out-band ringback tone is needed.<p> 1091 * 1092 * Messages received from this: 1093 * Message.obj will be an AsyncResult 1094 * AsyncResult.userObj = obj 1095 * AsyncResult.result = boolean, true to start play ringback tone 1096 * and false to stop. <p> 1097 */ 1098 public void registerForRingbackTone(Handler h, int what, Object obj){ 1099 mRingbackToneRegistrants.addUnique(h, what, obj); 1100 } 1101 1102 /** 1103 * Unregisters for ringback tone notification. 1104 */ 1105 1106 public void unregisterForRingbackTone(Handler h){ 1107 mRingbackToneRegistrants.remove(h); 1108 } 1109 1110 /** 1111 * Registers the handler to reset the uplink mute state to get 1112 * uplink audio. 1113 */ 1114 public void registerForResendIncallMute(Handler h, int what, Object obj){ 1115 mResendIncallMuteRegistrants.addUnique(h, what, obj); 1116 } 1117 1118 /** 1119 * Unregisters for resend incall mute notifications. 1120 */ 1121 public void unregisterForResendIncallMute(Handler h){ 1122 mResendIncallMuteRegistrants.remove(h); 1123 } 1124 1125 /** 1126 * Register for notifications of initiation of a new MMI code request. 1127 * MMI codes for GSM are discussed in 3GPP TS 22.030.<p> 1128 * 1129 * Example: If Phone.dial is called with "*#31#", then the app will 1130 * be notified here.<p> 1131 * 1132 * The returned <code>Message.obj</code> will contain an AsyncResult. 1133 * 1134 * <code>obj.result</code> will be an "MmiCode" object. 1135 */ 1136 public void registerForMmiInitiate(Handler h, int what, Object obj){ 1137 mMmiInitiateRegistrants.addUnique(h, what, obj); 1138 } 1139 1140 /** 1141 * Unregisters for new MMI initiate notification. 1142 * Extraneous calls are tolerated silently 1143 */ 1144 public void unregisterForMmiInitiate(Handler h){ 1145 mMmiInitiateRegistrants.remove(h); 1146 } 1147 1148 /** 1149 * Register for notifications that an MMI request has completed 1150 * its network activity and is in its final state. This may mean a state 1151 * of COMPLETE, FAILED, or CANCELLED. 1152 * 1153 * <code>Message.obj</code> will contain an AsyncResult. 1154 * <code>obj.result</code> will be an "MmiCode" object 1155 */ 1156 public void registerForMmiComplete(Handler h, int what, Object obj){ 1157 mMmiCompleteRegistrants.addUnique(h, what, obj); 1158 } 1159 1160 /** 1161 * Unregisters for MMI complete notification. 1162 * Extraneous calls are tolerated silently 1163 */ 1164 public void unregisterForMmiComplete(Handler h){ 1165 mMmiCompleteRegistrants.remove(h); 1166 } 1167 1168 /** 1169 * Registration point for Ecm timer reset 1170 * @param h handler to notify 1171 * @param what user-defined message code 1172 * @param obj placed in Message.obj 1173 */ 1174 public void registerForEcmTimerReset(Handler h, int what, Object obj){ 1175 mEcmTimerResetRegistrants.addUnique(h, what, obj); 1176 } 1177 1178 /** 1179 * Unregister for notification for Ecm timer reset 1180 * @param h Handler to be removed from the registrant list. 1181 */ 1182 public void unregisterForEcmTimerReset(Handler h){ 1183 mEcmTimerResetRegistrants.remove(h); 1184 } 1185 1186 /** 1187 * Register for ServiceState changed. 1188 * Message.obj will contain an AsyncResult. 1189 * AsyncResult.result will be a ServiceState instance 1190 */ 1191 public void registerForServiceStateChanged(Handler h, int what, Object obj){ 1192 mServiceStateChangedRegistrants.addUnique(h, what, obj); 1193 } 1194 1195 /** 1196 * Unregisters for ServiceStateChange notification. 1197 * Extraneous calls are tolerated silently 1198 */ 1199 public void unregisterForServiceStateChanged(Handler h){ 1200 mServiceStateChangedRegistrants.remove(h); 1201 } 1202 1203 /** 1204 * Register for notifications when a supplementary service attempt fails. 1205 * Message.obj will contain an AsyncResult. 1206 * 1207 * @param h Handler that receives the notification message. 1208 * @param what User-defined message code. 1209 * @param obj User object. 1210 */ 1211 public void registerForSuppServiceFailed(Handler h, int what, Object obj){ 1212 mSuppServiceFailedRegistrants.addUnique(h, what, obj); 1213 } 1214 1215 /** 1216 * Unregister for notifications when a supplementary service attempt fails. 1217 * Extraneous calls are tolerated silently 1218 * 1219 * @param h Handler to be removed from the registrant list. 1220 */ 1221 public void unregisterForSuppServiceFailed(Handler h){ 1222 mSuppServiceFailedRegistrants.remove(h); 1223 } 1224 1225 /** 1226 * Register for notifications when a sInCall VoicePrivacy is enabled 1227 * 1228 * @param h Handler that receives the notification message. 1229 * @param what User-defined message code. 1230 * @param obj User object. 1231 */ 1232 public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){ 1233 mInCallVoicePrivacyOnRegistrants.addUnique(h, what, obj); 1234 } 1235 1236 /** 1237 * Unregister for notifications when a sInCall VoicePrivacy is enabled 1238 * 1239 * @param h Handler to be removed from the registrant list. 1240 */ 1241 public void unregisterForInCallVoicePrivacyOn(Handler h){ 1242 mInCallVoicePrivacyOnRegistrants.remove(h); 1243 } 1244 1245 /** 1246 * Register for notifications when a sInCall VoicePrivacy is disabled 1247 * 1248 * @param h Handler that receives the notification message. 1249 * @param what User-defined message code. 1250 * @param obj User object. 1251 */ 1252 public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){ 1253 mInCallVoicePrivacyOffRegistrants.addUnique(h, what, obj); 1254 } 1255 1256 /** 1257 * Unregister for notifications when a sInCall VoicePrivacy is disabled 1258 * 1259 * @param h Handler to be removed from the registrant list. 1260 */ 1261 public void unregisterForInCallVoicePrivacyOff(Handler h){ 1262 mInCallVoicePrivacyOffRegistrants.remove(h); 1263 } 1264 1265 /** 1266 * Register for notifications when CDMA call waiting comes 1267 * 1268 * @param h Handler that receives the notification message. 1269 * @param what User-defined message code. 1270 * @param obj User object. 1271 */ 1272 public void registerForCallWaiting(Handler h, int what, Object obj){ 1273 mCallWaitingRegistrants.addUnique(h, what, obj); 1274 } 1275 1276 /** 1277 * Unregister for notifications when CDMA Call waiting comes 1278 * @param h Handler to be removed from the registrant list. 1279 */ 1280 public void unregisterForCallWaiting(Handler h){ 1281 mCallWaitingRegistrants.remove(h); 1282 } 1283 1284 1285 /** 1286 * Register for signal information notifications from the network. 1287 * Message.obj will contain an AsyncResult. 1288 * AsyncResult.result will be a SuppServiceNotification instance. 1289 * 1290 * @param h Handler that receives the notification message. 1291 * @param what User-defined message code. 1292 * @param obj User object. 1293 */ 1294 1295 public void registerForSignalInfo(Handler h, int what, Object obj){ 1296 mSignalInfoRegistrants.addUnique(h, what, obj); 1297 } 1298 1299 /** 1300 * Unregisters for signal information notifications. 1301 * Extraneous calls are tolerated silently 1302 * 1303 * @param h Handler to be removed from the registrant list. 1304 */ 1305 public void unregisterForSignalInfo(Handler h){ 1306 mSignalInfoRegistrants.remove(h); 1307 } 1308 1309 /** 1310 * Register for display information notifications from the network. 1311 * Message.obj will contain an AsyncResult. 1312 * AsyncResult.result will be a SuppServiceNotification instance. 1313 * 1314 * @param h Handler that receives the notification message. 1315 * @param what User-defined message code. 1316 * @param obj User object. 1317 */ 1318 public void registerForDisplayInfo(Handler h, int what, Object obj){ 1319 mDisplayInfoRegistrants.addUnique(h, what, obj); 1320 } 1321 1322 /** 1323 * Unregisters for display information notifications. 1324 * Extraneous calls are tolerated silently 1325 * 1326 * @param h Handler to be removed from the registrant list. 1327 */ 1328 public void unregisterForDisplayInfo(Handler h) { 1329 mDisplayInfoRegistrants.remove(h); 1330 } 1331 1332 /** 1333 * Register for notifications when CDMA OTA Provision status change 1334 * 1335 * @param h Handler that receives the notification message. 1336 * @param what User-defined message code. 1337 * @param obj User object. 1338 */ 1339 public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj){ 1340 mCdmaOtaStatusChangeRegistrants.addUnique(h, what, obj); 1341 } 1342 1343 /** 1344 * Unregister for notifications when CDMA OTA Provision status change 1345 * @param h Handler to be removed from the registrant list. 1346 */ 1347 public void unregisterForCdmaOtaStatusChange(Handler h){ 1348 mCdmaOtaStatusChangeRegistrants.remove(h); 1349 } 1350 1351 /** 1352 * Registration point for subscription info ready 1353 * @param h handler to notify 1354 * @param what what code of message when delivered 1355 * @param obj placed in Message.obj 1356 */ 1357 public void registerForSubscriptionInfoReady(Handler h, int what, Object obj){ 1358 mSubscriptionInfoReadyRegistrants.addUnique(h, what, obj); 1359 } 1360 1361 /** 1362 * Unregister for notifications for subscription info 1363 * @param h Handler to be removed from the registrant list. 1364 */ 1365 public void unregisterForSubscriptionInfoReady(Handler h){ 1366 mSubscriptionInfoReadyRegistrants.remove(h); 1367 } 1368 1369 /** 1370 * Sets an event to be fired when the telephony system processes 1371 * a post-dial character on an outgoing call.<p> 1372 * 1373 * Messages of type <code>what</code> will be sent to <code>h</code>. 1374 * The <code>obj</code> field of these Message's will be instances of 1375 * <code>AsyncResult</code>. <code>Message.obj.result</code> will be 1376 * a Connection object.<p> 1377 * 1378 * Message.arg1 will be the post dial character being processed, 1379 * or 0 ('\0') if end of string.<p> 1380 * 1381 * If Connection.getPostDialState() == WAIT, 1382 * the application must call 1383 * {@link com.android.internal.telephony.Connection#proceedAfterWaitChar() 1384 * Connection.proceedAfterWaitChar()} or 1385 * {@link com.android.internal.telephony.Connection#cancelPostDial() 1386 * Connection.cancelPostDial()} 1387 * for the telephony system to continue playing the post-dial 1388 * DTMF sequence.<p> 1389 * 1390 * If Connection.getPostDialState() == WILD, 1391 * the application must call 1392 * {@link com.android.internal.telephony.Connection#proceedAfterWildChar 1393 * Connection.proceedAfterWildChar()} 1394 * or 1395 * {@link com.android.internal.telephony.Connection#cancelPostDial() 1396 * Connection.cancelPostDial()} 1397 * for the telephony system to continue playing the 1398 * post-dial DTMF sequence.<p> 1399 * 1400 */ 1401 public void registerForPostDialCharacter(Handler h, int what, Object obj){ 1402 mPostDialCharacterRegistrants.addUnique(h, what, obj); 1403 } 1404 1405 public void unregisterForPostDialCharacter(Handler h){ 1406 mPostDialCharacterRegistrants.remove(h); 1407 } 1408 1409 /* APIs to access foregroudCalls, backgroudCalls, and ringingCalls 1410 * 1. APIs to access list of calls 1411 * 2. APIs to check if any active call, which has connection other than 1412 * disconnected ones, pleaser refer to Call.isIdle() 1413 * 3. APIs to return first active call 1414 * 4. APIs to return the connections of first active call 1415 * 5. APIs to return other property of first active call 1416 */ 1417 1418 /** 1419 * @return list of all ringing calls 1420 */ 1421 public List<Call> getRingingCalls() { 1422 return Collections.unmodifiableList(mRingingCalls); 1423 } 1424 1425 /** 1426 * @return list of all foreground calls 1427 */ 1428 public List<Call> getForegroundCalls() { 1429 return Collections.unmodifiableList(mForegroundCalls); 1430 } 1431 1432 /** 1433 * @return list of all background calls 1434 */ 1435 public List<Call> getBackgroundCalls() { 1436 return Collections.unmodifiableList(mBackgroundCalls); 1437 } 1438 1439 /** 1440 * Return true if there is at least one active foreground call 1441 */ 1442 public boolean hasActiveFgCall() { 1443 return (getFirstActiveCall(mForegroundCalls) != null); 1444 } 1445 1446 /** 1447 * Return true if there is at least one active background call 1448 */ 1449 public boolean hasActiveBgCall() { 1450 // TODO since hasActiveBgCall may get called often 1451 // better to cache it to improve performance 1452 return (getFirstActiveCall(mBackgroundCalls) != null); 1453 } 1454 1455 /** 1456 * Return true if there is at least one active ringing call 1457 * 1458 */ 1459 public boolean hasActiveRingingCall() { 1460 return (getFirstActiveCall(mRingingCalls) != null); 1461 } 1462 1463 /** 1464 * return the active foreground call from foreground calls 1465 * 1466 * Active call means the call is NOT in Call.State.IDLE 1467 * 1468 * 1. If there is active foreground call, return it 1469 * 2. If there is no active foreground call, return the 1470 * foreground call associated with default phone, which state is IDLE. 1471 * 3. If there is no phone registered at all, return null. 1472 * 1473 */ 1474 public Call getActiveFgCall() { 1475 Call call = getFirstNonIdleCall(mForegroundCalls); 1476 if (call == null) { 1477 call = (mDefaultPhone == null) 1478 ? null 1479 : mDefaultPhone.getForegroundCall(); 1480 } 1481 return call; 1482 } 1483 1484 // Returns the first call that is not in IDLE state. If both active calls 1485 // and disconnecting/disconnected calls exist, return the first active call. 1486 private Call getFirstNonIdleCall(List<Call> calls) { 1487 Call result = null; 1488 for (Call call : calls) { 1489 if (!call.isIdle()) { 1490 return call; 1491 } else if (call.getState() != Call.State.IDLE) { 1492 if (result == null) result = call; 1493 } 1494 } 1495 return result; 1496 } 1497 1498 /** 1499 * return one active background call from background calls 1500 * 1501 * Active call means the call is NOT idle defined by Call.isIdle() 1502 * 1503 * 1. If there is only one active background call, return it 1504 * 2. If there is more than one active background call, return the first one 1505 * 3. If there is no active background call, return the background call 1506 * associated with default phone, which state is IDLE. 1507 * 4. If there is no background call at all, return null. 1508 * 1509 * Complete background calls list can be get by getBackgroundCalls() 1510 */ 1511 public Call getFirstActiveBgCall() { 1512 Call call = getFirstNonIdleCall(mBackgroundCalls); 1513 if (call == null) { 1514 call = (mDefaultPhone == null) 1515 ? null 1516 : mDefaultPhone.getBackgroundCall(); 1517 } 1518 return call; 1519 } 1520 1521 /** 1522 * return one active ringing call from ringing calls 1523 * 1524 * Active call means the call is NOT idle defined by Call.isIdle() 1525 * 1526 * 1. If there is only one active ringing call, return it 1527 * 2. If there is more than one active ringing call, return the first one 1528 * 3. If there is no active ringing call, return the ringing call 1529 * associated with default phone, which state is IDLE. 1530 * 4. If there is no ringing call at all, return null. 1531 * 1532 * Complete ringing calls list can be get by getRingingCalls() 1533 */ 1534 public Call getFirstActiveRingingCall() { 1535 Call call = getFirstNonIdleCall(mRingingCalls); 1536 if (call == null) { 1537 call = (mDefaultPhone == null) 1538 ? null 1539 : mDefaultPhone.getRingingCall(); 1540 } 1541 return call; 1542 } 1543 1544 /** 1545 * @return the state of active foreground call 1546 * return IDLE if there is no active foreground call 1547 */ 1548 public Call.State getActiveFgCallState() { 1549 Call fgCall = getActiveFgCall(); 1550 1551 if (fgCall != null) { 1552 return fgCall.getState(); 1553 } 1554 1555 return Call.State.IDLE; 1556 } 1557 1558 /** 1559 * @return the connections of active foreground call 1560 * return empty list if there is no active foreground call 1561 */ 1562 public List<Connection> getFgCallConnections() { 1563 Call fgCall = getActiveFgCall(); 1564 if ( fgCall != null) { 1565 return fgCall.getConnections(); 1566 } 1567 return emptyConnections; 1568 } 1569 1570 /** 1571 * @return the connections of active background call 1572 * return empty list if there is no active background call 1573 */ 1574 public List<Connection> getBgCallConnections() { 1575 Call bgCall = getFirstActiveBgCall(); 1576 if ( bgCall != null) { 1577 return bgCall.getConnections(); 1578 } 1579 return emptyConnections; 1580 } 1581 1582 /** 1583 * @return the latest connection of active foreground call 1584 * return null if there is no active foreground call 1585 */ 1586 public Connection getFgCallLatestConnection() { 1587 Call fgCall = getActiveFgCall(); 1588 if ( fgCall != null) { 1589 return fgCall.getLatestConnection(); 1590 } 1591 return null; 1592 } 1593 1594 /** 1595 * @return true if there is at least one Foreground call in disconnected state 1596 */ 1597 public boolean hasDisconnectedFgCall() { 1598 return (getFirstCallOfState(mForegroundCalls, Call.State.DISCONNECTED) != null); 1599 } 1600 1601 /** 1602 * @return true if there is at least one background call in disconnected state 1603 */ 1604 public boolean hasDisconnectedBgCall() { 1605 return (getFirstCallOfState(mBackgroundCalls, Call.State.DISCONNECTED) != null); 1606 } 1607 1608 /** 1609 * @return the first active call from a call list 1610 */ 1611 private Call getFirstActiveCall(ArrayList<Call> calls) { 1612 for (Call call : calls) { 1613 if (!call.isIdle()) { 1614 return call; 1615 } 1616 } 1617 return null; 1618 } 1619 1620 /** 1621 * @return the first call in a the Call.state from a call list 1622 */ 1623 private Call getFirstCallOfState(ArrayList<Call> calls, Call.State state) { 1624 for (Call call : calls) { 1625 if (call.getState() == state) { 1626 return call; 1627 } 1628 } 1629 return null; 1630 } 1631 1632 1633 private boolean hasMoreThanOneRingingCall() { 1634 int count = 0; 1635 for (Call call : mRingingCalls) { 1636 if (call.getState().isRinging()) { 1637 if (++count > 1) return true; 1638 } 1639 } 1640 return false; 1641 } 1642 1643 private Handler mHandler = new Handler() { 1644 1645 @Override 1646 public void handleMessage(Message msg) { 1647 1648 switch (msg.what) { 1649 case EVENT_DISCONNECT: 1650 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_DISCONNECT)"); 1651 mDisconnectRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1652 break; 1653 case EVENT_PRECISE_CALL_STATE_CHANGED: 1654 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_PRECISE_CALL_STATE_CHANGED)"); 1655 mPreciseCallStateRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1656 break; 1657 case EVENT_NEW_RINGING_CONNECTION: 1658 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_NEW_RINGING_CONNECTION)"); 1659 if (getActiveFgCallState().isDialing() || hasMoreThanOneRingingCall()) { 1660 Connection c = (Connection) ((AsyncResult) msg.obj).result; 1661 try { 1662 Log.d(LOG_TAG, "silently drop incoming call: " + c.getCall()); 1663 c.getCall().hangup(); 1664 } catch (CallStateException e) { 1665 Log.w(LOG_TAG, "new ringing connection", e); 1666 } 1667 } else { 1668 mNewRingingConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1669 } 1670 break; 1671 case EVENT_UNKNOWN_CONNECTION: 1672 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_UNKNOWN_CONNECTION)"); 1673 mUnknownConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1674 break; 1675 case EVENT_INCOMING_RING: 1676 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_INCOMING_RING)"); 1677 // The event may come from RIL who's not aware of an ongoing fg call 1678 if (!hasActiveFgCall()) { 1679 mIncomingRingRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1680 } 1681 break; 1682 case EVENT_RINGBACK_TONE: 1683 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_RINGBACK_TONE)"); 1684 mRingbackToneRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1685 break; 1686 case EVENT_IN_CALL_VOICE_PRIVACY_ON: 1687 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_ON)"); 1688 mInCallVoicePrivacyOnRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1689 break; 1690 case EVENT_IN_CALL_VOICE_PRIVACY_OFF: 1691 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_OFF)"); 1692 mInCallVoicePrivacyOffRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1693 break; 1694 case EVENT_CALL_WAITING: 1695 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_CALL_WAITING)"); 1696 mCallWaitingRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1697 break; 1698 case EVENT_DISPLAY_INFO: 1699 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_DISPLAY_INFO)"); 1700 mDisplayInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1701 break; 1702 case EVENT_SIGNAL_INFO: 1703 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_SIGNAL_INFO)"); 1704 mSignalInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1705 break; 1706 case EVENT_CDMA_OTA_STATUS_CHANGE: 1707 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_CDMA_OTA_STATUS_CHANGE)"); 1708 mCdmaOtaStatusChangeRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1709 break; 1710 case EVENT_RESEND_INCALL_MUTE: 1711 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_RESEND_INCALL_MUTE)"); 1712 mResendIncallMuteRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1713 break; 1714 case EVENT_MMI_INITIATE: 1715 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_MMI_INITIATE)"); 1716 mMmiInitiateRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1717 break; 1718 case EVENT_MMI_COMPLETE: 1719 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_MMI_COMPLETE)"); 1720 mMmiCompleteRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1721 break; 1722 case EVENT_ECM_TIMER_RESET: 1723 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_ECM_TIMER_RESET)"); 1724 mEcmTimerResetRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1725 break; 1726 case EVENT_SUBSCRIPTION_INFO_READY: 1727 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_SUBSCRIPTION_INFO_READY)"); 1728 mSubscriptionInfoReadyRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1729 break; 1730 case EVENT_SUPP_SERVICE_FAILED: 1731 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_SUPP_SERVICE_FAILED)"); 1732 mSuppServiceFailedRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1733 break; 1734 case EVENT_SERVICE_STATE_CHANGED: 1735 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_SERVICE_STATE_CHANGED)"); 1736 mServiceStateChangedRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1737 break; 1738 case EVENT_POST_DIAL_CHARACTER: 1739 // we need send the character that is being processed in msg.arg1 1740 // so can't use notifyRegistrants() 1741 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_POST_DIAL_CHARACTER)"); 1742 for(int i=0; i < mPostDialCharacterRegistrants.size(); i++) { 1743 Message notifyMsg; 1744 notifyMsg = ((Registrant)mPostDialCharacterRegistrants.get(i)).messageForRegistrant(); 1745 notifyMsg.obj = msg.obj; 1746 notifyMsg.arg1 = msg.arg1; 1747 notifyMsg.sendToTarget(); 1748 } 1749 break; 1750 } 1751 } 1752 }; 1753 1754 @Override 1755 public String toString() { 1756 Call call; 1757 StringBuilder b = new StringBuilder(); 1758 1759 b.append("########### Dump CallManager ############"); 1760 b.append("\nCallManager state = " + getState()); 1761 call = getActiveFgCall(); 1762 b.append("\n - Foreground: " + getActiveFgCallState()); 1763 b.append(" from " + call.getPhone()); 1764 b.append("\n Conn: ").append(getFgCallConnections()); 1765 call = getFirstActiveBgCall(); 1766 b.append("\n - Background: " + call.getState()); 1767 b.append(" from " + call.getPhone()); 1768 b.append("\n Conn: ").append(getBgCallConnections()); 1769 call = getFirstActiveRingingCall(); 1770 b.append("\n - Ringing: " +call.getState()); 1771 b.append(" from " + call.getPhone()); 1772 1773 for (Phone phone : getAllPhones()) { 1774 if (phone != null) { 1775 b.append("\n Phone: " + phone + ", name = " + phone.getPhoneName() 1776 + ", state = " + phone.getState()); 1777 call = phone.getForegroundCall(); 1778 b.append("\n - Foreground: ").append(call); 1779 call = phone.getBackgroundCall(); 1780 b.append(" Background: ").append(call); 1781 call = phone.getRingingCall(); 1782 b.append(" Ringing: ").append(call); 1783 } 1784 } 1785 b.append("\n########## End Dump CallManager ##########"); 1786 return b.toString(); 1787 } 1788 } 1789