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 // change the audio mode and request/abandon audio focus according to phone state, 377 // but only on audio mode transitions 378 switch (getState()) { 379 case RINGING: 380 if (audioManager.getMode() != AudioManager.MODE_RINGTONE) { 381 // only request audio focus if the ringtone is going to be heard 382 if (audioManager.getStreamVolume(AudioManager.STREAM_RING) > 0) { 383 if (VDBG) Log.d(LOG_TAG, "requestAudioFocus on STREAM_RING"); 384 audioManager.requestAudioFocusForCall(AudioManager.STREAM_RING, 385 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); 386 } 387 audioManager.setMode(AudioManager.MODE_RINGTONE); 388 } 389 break; 390 case OFFHOOK: 391 Phone offhookPhone = getFgPhone(); 392 if (getActiveFgCallState() == Call.State.IDLE) { 393 // There is no active Fg calls, the OFFHOOK state 394 // is set by the Bg call. So set the phone to bgPhone. 395 offhookPhone = getBgPhone(); 396 } 397 398 int newAudioMode = AudioManager.MODE_IN_CALL; 399 if (offhookPhone instanceof SipPhone) { 400 // enable IN_COMMUNICATION audio mode instead for sipPhone 401 newAudioMode = AudioManager.MODE_IN_COMMUNICATION; 402 } 403 if (audioManager.getMode() != newAudioMode) { 404 // request audio focus before setting the new mode 405 if (VDBG) Log.d(LOG_TAG, "requestAudioFocus on STREAM_VOICE_CALL"); 406 audioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL, 407 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); 408 audioManager.setMode(newAudioMode); 409 } 410 break; 411 case IDLE: 412 if (audioManager.getMode() != AudioManager.MODE_NORMAL) { 413 audioManager.setMode(AudioManager.MODE_NORMAL); 414 if (VDBG) Log.d(LOG_TAG, "abandonAudioFocus"); 415 // abandon audio focus after the mode has been set back to normal 416 audioManager.abandonAudioFocusForCall(); 417 } 418 break; 419 } 420 } 421 422 private Context getContext() { 423 Phone defaultPhone = getDefaultPhone(); 424 return ((defaultPhone == null) ? null : defaultPhone.getContext()); 425 } 426 427 private void registerForPhoneStates(Phone phone) { 428 // for common events supported by all phones 429 phone.registerForPreciseCallStateChanged(mHandler, EVENT_PRECISE_CALL_STATE_CHANGED, null); 430 phone.registerForDisconnect(mHandler, EVENT_DISCONNECT, null); 431 phone.registerForNewRingingConnection(mHandler, EVENT_NEW_RINGING_CONNECTION, null); 432 phone.registerForUnknownConnection(mHandler, EVENT_UNKNOWN_CONNECTION, null); 433 phone.registerForIncomingRing(mHandler, EVENT_INCOMING_RING, null); 434 phone.registerForRingbackTone(mHandler, EVENT_RINGBACK_TONE, null); 435 phone.registerForInCallVoicePrivacyOn(mHandler, EVENT_IN_CALL_VOICE_PRIVACY_ON, null); 436 phone.registerForInCallVoicePrivacyOff(mHandler, EVENT_IN_CALL_VOICE_PRIVACY_OFF, null); 437 phone.registerForDisplayInfo(mHandler, EVENT_DISPLAY_INFO, null); 438 phone.registerForSignalInfo(mHandler, EVENT_SIGNAL_INFO, null); 439 phone.registerForResendIncallMute(mHandler, EVENT_RESEND_INCALL_MUTE, null); 440 phone.registerForMmiInitiate(mHandler, EVENT_MMI_INITIATE, null); 441 phone.registerForMmiComplete(mHandler, EVENT_MMI_COMPLETE, null); 442 phone.registerForSuppServiceFailed(mHandler, EVENT_SUPP_SERVICE_FAILED, null); 443 phone.registerForServiceStateChanged(mHandler, EVENT_SERVICE_STATE_CHANGED, null); 444 445 // for events supported only by GSM and CDMA phone 446 if (phone.getPhoneType() == Phone.PHONE_TYPE_GSM || 447 phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) { 448 phone.setOnPostDialCharacter(mHandler, EVENT_POST_DIAL_CHARACTER, null); 449 } 450 451 // for events supported only by CDMA phone 452 if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA ){ 453 phone.registerForCdmaOtaStatusChange(mHandler, EVENT_CDMA_OTA_STATUS_CHANGE, null); 454 phone.registerForSubscriptionInfoReady(mHandler, EVENT_SUBSCRIPTION_INFO_READY, null); 455 phone.registerForCallWaiting(mHandler, EVENT_CALL_WAITING, null); 456 phone.registerForEcmTimerReset(mHandler, EVENT_ECM_TIMER_RESET, null); 457 } 458 } 459 460 private void unregisterForPhoneStates(Phone phone) { 461 // for common events supported by all phones 462 phone.unregisterForPreciseCallStateChanged(mHandler); 463 phone.unregisterForDisconnect(mHandler); 464 phone.unregisterForNewRingingConnection(mHandler); 465 phone.unregisterForUnknownConnection(mHandler); 466 phone.unregisterForIncomingRing(mHandler); 467 phone.unregisterForRingbackTone(mHandler); 468 phone.unregisterForInCallVoicePrivacyOn(mHandler); 469 phone.unregisterForInCallVoicePrivacyOff(mHandler); 470 phone.unregisterForDisplayInfo(mHandler); 471 phone.unregisterForSignalInfo(mHandler); 472 phone.unregisterForResendIncallMute(mHandler); 473 phone.unregisterForMmiInitiate(mHandler); 474 phone.unregisterForMmiComplete(mHandler); 475 phone.unregisterForSuppServiceFailed(mHandler); 476 phone.unregisterForServiceStateChanged(mHandler); 477 478 // for events supported only by GSM and CDMA phone 479 if (phone.getPhoneType() == Phone.PHONE_TYPE_GSM || 480 phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) { 481 phone.setOnPostDialCharacter(null, EVENT_POST_DIAL_CHARACTER, null); 482 } 483 484 // for events supported only by CDMA phone 485 if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA ){ 486 phone.unregisterForCdmaOtaStatusChange(mHandler); 487 phone.unregisterForSubscriptionInfoReady(mHandler); 488 phone.unregisterForCallWaiting(mHandler); 489 phone.unregisterForEcmTimerReset(mHandler); 490 } 491 } 492 493 /** 494 * Answers a ringing or waiting call. 495 * 496 * Active call, if any, go on hold. 497 * If active call can't be held, i.e., a background call of the same channel exists, 498 * the active call will be hang up. 499 * 500 * Answering occurs asynchronously, and final notification occurs via 501 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 502 * java.lang.Object) registerForPreciseCallStateChanged()}. 503 * 504 * @exception CallStateException when call is not ringing or waiting 505 */ 506 public void acceptCall(Call ringingCall) throws CallStateException { 507 Phone ringingPhone = ringingCall.getPhone(); 508 509 if (VDBG) { 510 Log.d(LOG_TAG, "acceptCall(" +ringingCall + " from " + ringingCall.getPhone() + ")"); 511 Log.d(LOG_TAG, this.toString()); 512 } 513 514 if ( hasActiveFgCall() ) { 515 Phone activePhone = getActiveFgCall().getPhone(); 516 boolean hasBgCall = ! (activePhone.getBackgroundCall().isIdle()); 517 boolean sameChannel = (activePhone == ringingPhone); 518 519 if (VDBG) { 520 Log.d(LOG_TAG, "hasBgCall: "+ hasBgCall + "sameChannel:" + sameChannel); 521 } 522 523 if (sameChannel && hasBgCall) { 524 getActiveFgCall().hangup(); 525 } else if (!sameChannel && !hasBgCall) { 526 activePhone.switchHoldingAndActive(); 527 } else if (!sameChannel && hasBgCall) { 528 getActiveFgCall().hangup(); 529 } 530 } 531 532 ringingPhone.acceptCall(); 533 534 if (VDBG) { 535 Log.d(LOG_TAG, "End acceptCall(" +ringingCall + ")"); 536 Log.d(LOG_TAG, this.toString()); 537 } 538 } 539 540 /** 541 * Reject (ignore) a ringing call. In GSM, this means UDUB 542 * (User Determined User Busy). Reject occurs asynchronously, 543 * and final notification occurs via 544 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 545 * java.lang.Object) registerForPreciseCallStateChanged()}. 546 * 547 * @exception CallStateException when no call is ringing or waiting 548 */ 549 public void rejectCall(Call ringingCall) throws CallStateException { 550 if (VDBG) { 551 Log.d(LOG_TAG, "rejectCall(" +ringingCall + ")"); 552 Log.d(LOG_TAG, this.toString()); 553 } 554 555 Phone ringingPhone = ringingCall.getPhone(); 556 557 ringingPhone.rejectCall(); 558 559 if (VDBG) { 560 Log.d(LOG_TAG, "End rejectCall(" +ringingCall + ")"); 561 Log.d(LOG_TAG, this.toString()); 562 } 563 } 564 565 /** 566 * Places active call on hold, and makes held call active. 567 * Switch occurs asynchronously and may fail. 568 * 569 * There are 4 scenarios 570 * 1. only active call but no held call, aka, hold 571 * 2. no active call but only held call, aka, unhold 572 * 3. both active and held calls from same phone, aka, swap 573 * 4. active and held calls from different phones, aka, phone swap 574 * 575 * Final notification occurs via 576 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 577 * java.lang.Object) registerForPreciseCallStateChanged()}. 578 * 579 * @exception CallStateException if active call is ringing, waiting, or 580 * dialing/alerting, or heldCall can't be active. 581 * In these cases, this operation may not be performed. 582 */ 583 public void switchHoldingAndActive(Call heldCall) throws CallStateException { 584 Phone activePhone = null; 585 Phone heldPhone = null; 586 587 if (VDBG) { 588 Log.d(LOG_TAG, "switchHoldingAndActive(" +heldCall + ")"); 589 Log.d(LOG_TAG, this.toString()); 590 } 591 592 if (hasActiveFgCall()) { 593 activePhone = getActiveFgCall().getPhone(); 594 } 595 596 if (heldCall != null) { 597 heldPhone = heldCall.getPhone(); 598 } 599 600 if (activePhone != null) { 601 activePhone.switchHoldingAndActive(); 602 } 603 604 if (heldPhone != null && heldPhone != activePhone) { 605 heldPhone.switchHoldingAndActive(); 606 } 607 608 if (VDBG) { 609 Log.d(LOG_TAG, "End switchHoldingAndActive(" +heldCall + ")"); 610 Log.d(LOG_TAG, this.toString()); 611 } 612 } 613 614 /** 615 * Hangup foreground call and resume the specific background call 616 * 617 * Note: this is noop if there is no foreground call or the heldCall is null 618 * 619 * @param heldCall to become foreground 620 * @throws CallStateException 621 */ 622 public void hangupForegroundResumeBackground(Call heldCall) throws CallStateException { 623 Phone foregroundPhone = null; 624 Phone backgroundPhone = null; 625 626 if (VDBG) { 627 Log.d(LOG_TAG, "hangupForegroundResumeBackground(" +heldCall + ")"); 628 Log.d(LOG_TAG, this.toString()); 629 } 630 631 if (hasActiveFgCall()) { 632 foregroundPhone = getFgPhone(); 633 if (heldCall != null) { 634 backgroundPhone = heldCall.getPhone(); 635 if (foregroundPhone == backgroundPhone) { 636 getActiveFgCall().hangup(); 637 } else { 638 // the call to be hangup and resumed belongs to different phones 639 getActiveFgCall().hangup(); 640 switchHoldingAndActive(heldCall); 641 } 642 } 643 } 644 645 if (VDBG) { 646 Log.d(LOG_TAG, "End hangupForegroundResumeBackground(" +heldCall + ")"); 647 Log.d(LOG_TAG, this.toString()); 648 } 649 } 650 651 /** 652 * Whether or not the phone can conference in the current phone 653 * state--that is, one call holding and one call active. 654 * @return true if the phone can conference; false otherwise. 655 */ 656 public boolean canConference(Call heldCall) { 657 Phone activePhone = null; 658 Phone heldPhone = null; 659 660 if (hasActiveFgCall()) { 661 activePhone = getActiveFgCall().getPhone(); 662 } 663 664 if (heldCall != null) { 665 heldPhone = heldCall.getPhone(); 666 } 667 668 return heldPhone.getClass().equals(activePhone.getClass()); 669 } 670 671 /** 672 * Conferences holding and active. Conference occurs asynchronously 673 * and may fail. Final notification occurs via 674 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 675 * java.lang.Object) registerForPreciseCallStateChanged()}. 676 * 677 * @exception CallStateException if canConference() would return false. 678 * In these cases, this operation may not be performed. 679 */ 680 public void conference(Call heldCall) throws CallStateException { 681 682 if (VDBG) { 683 Log.d(LOG_TAG, "conference(" +heldCall + ")"); 684 Log.d(LOG_TAG, this.toString()); 685 } 686 687 688 Phone fgPhone = getFgPhone(); 689 if (fgPhone instanceof SipPhone) { 690 ((SipPhone) fgPhone).conference(heldCall); 691 } else if (canConference(heldCall)) { 692 fgPhone.conference(); 693 } else { 694 throw(new CallStateException("Can't conference foreground and selected background call")); 695 } 696 697 if (VDBG) { 698 Log.d(LOG_TAG, "End conference(" +heldCall + ")"); 699 Log.d(LOG_TAG, this.toString()); 700 } 701 702 } 703 704 /** 705 * Initiate a new voice connection. This happens asynchronously, so you 706 * cannot assume the audio path is connected (or a call index has been 707 * assigned) until PhoneStateChanged notification has occurred. 708 * 709 * @exception CallStateException if a new outgoing call is not currently 710 * possible because no more call slots exist or a call exists that is 711 * dialing, alerting, ringing, or waiting. Other errors are 712 * handled asynchronously. 713 */ 714 public Connection dial(Phone phone, String dialString) throws CallStateException { 715 Phone basePhone = getPhoneBase(phone); 716 Connection result; 717 718 if (VDBG) { 719 Log.d(LOG_TAG, " dial(" + basePhone + ", "+ dialString + ")"); 720 Log.d(LOG_TAG, this.toString()); 721 } 722 723 if (!canDial(phone)) { 724 throw new CallStateException("cannot dial in current state"); 725 } 726 727 if ( hasActiveFgCall() ) { 728 Phone activePhone = getActiveFgCall().getPhone(); 729 boolean hasBgCall = !(activePhone.getBackgroundCall().isIdle()); 730 731 if (DBG) { 732 Log.d(LOG_TAG, "hasBgCall: "+ hasBgCall + " sameChannel:" + (activePhone == basePhone)); 733 } 734 735 if (activePhone != basePhone) { 736 if (hasBgCall) { 737 Log.d(LOG_TAG, "Hangup"); 738 getActiveFgCall().hangup(); 739 } else { 740 Log.d(LOG_TAG, "Switch"); 741 activePhone.switchHoldingAndActive(); 742 } 743 } 744 } 745 746 result = basePhone.dial(dialString); 747 748 if (VDBG) { 749 Log.d(LOG_TAG, "End dial(" + basePhone + ", "+ dialString + ")"); 750 Log.d(LOG_TAG, this.toString()); 751 } 752 753 return result; 754 } 755 756 /** 757 * Initiate a new voice connection. This happens asynchronously, so you 758 * cannot assume the audio path is connected (or a call index has been 759 * assigned) until PhoneStateChanged notification has occurred. 760 * 761 * @exception CallStateException if a new outgoing call is not currently 762 * possible because no more call slots exist or a call exists that is 763 * dialing, alerting, ringing, or waiting. Other errors are 764 * handled asynchronously. 765 */ 766 public Connection dial(Phone phone, String dialString, UUSInfo uusInfo) throws CallStateException { 767 return phone.dial(dialString, uusInfo); 768 } 769 770 /** 771 * clear disconnect connection for each phone 772 */ 773 public void clearDisconnected() { 774 for(Phone phone : mPhones) { 775 phone.clearDisconnected(); 776 } 777 } 778 779 /** 780 * Phone can make a call only if ALL of the following are true: 781 * - Phone is not powered off 782 * - There's no incoming or waiting call 783 * - There's available call slot in either foreground or background 784 * - The foreground call is ACTIVE or IDLE or DISCONNECTED. 785 * (We mainly need to make sure it *isn't* DIALING or ALERTING.) 786 * @param phone 787 * @return true if the phone can make a new call 788 */ 789 private boolean canDial(Phone phone) { 790 int serviceState = phone.getServiceState().getState(); 791 boolean hasRingingCall = hasActiveRingingCall(); 792 boolean hasActiveCall = hasActiveFgCall(); 793 boolean hasHoldingCall = hasActiveBgCall(); 794 boolean allLinesTaken = hasActiveCall && hasHoldingCall; 795 Call.State fgCallState = getActiveFgCallState(); 796 797 boolean result = (serviceState != ServiceState.STATE_POWER_OFF 798 && !hasRingingCall 799 && !allLinesTaken 800 && ((fgCallState == Call.State.ACTIVE) 801 || (fgCallState == Call.State.IDLE) 802 || (fgCallState == Call.State.DISCONNECTED))); 803 804 if (result == false) { 805 Log.d(LOG_TAG, "canDial serviceState=" + serviceState 806 + " hasRingingCall=" + hasRingingCall 807 + " hasActiveCall=" + hasActiveCall 808 + " hasHoldingCall=" + hasHoldingCall 809 + " allLinesTaken=" + allLinesTaken 810 + " fgCallState=" + fgCallState); 811 } 812 return result; 813 } 814 815 /** 816 * Whether or not the phone can do explicit call transfer in the current 817 * phone state--that is, one call holding and one call active. 818 * @return true if the phone can do explicit call transfer; false otherwise. 819 */ 820 public boolean canTransfer(Call heldCall) { 821 Phone activePhone = null; 822 Phone heldPhone = null; 823 824 if (hasActiveFgCall()) { 825 activePhone = getActiveFgCall().getPhone(); 826 } 827 828 if (heldCall != null) { 829 heldPhone = heldCall.getPhone(); 830 } 831 832 return (heldPhone == activePhone && activePhone.canTransfer()); 833 } 834 835 /** 836 * Connects the held call and active call 837 * Disconnects the subscriber from both calls 838 * 839 * Explicit Call Transfer occurs asynchronously 840 * and may fail. Final notification occurs via 841 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 842 * java.lang.Object) registerForPreciseCallStateChanged()}. 843 * 844 * @exception CallStateException if canTransfer() would return false. 845 * In these cases, this operation may not be performed. 846 */ 847 public void explicitCallTransfer(Call heldCall) throws CallStateException { 848 if (VDBG) { 849 Log.d(LOG_TAG, " explicitCallTransfer(" + heldCall + ")"); 850 Log.d(LOG_TAG, this.toString()); 851 } 852 853 if (canTransfer(heldCall)) { 854 heldCall.getPhone().explicitCallTransfer(); 855 } 856 857 if (VDBG) { 858 Log.d(LOG_TAG, "End explicitCallTransfer(" + heldCall + ")"); 859 Log.d(LOG_TAG, this.toString()); 860 } 861 862 } 863 864 /** 865 * Returns a list of MMI codes that are pending for a phone. (They have initiated 866 * but have not yet completed). 867 * Presently there is only ever one. 868 * 869 * Use <code>registerForMmiInitiate</code> 870 * and <code>registerForMmiComplete</code> for change notification. 871 * @return null if phone doesn't have or support mmi code 872 */ 873 public List<? extends MmiCode> getPendingMmiCodes(Phone phone) { 874 Log.e(LOG_TAG, "getPendingMmiCodes not implemented"); 875 return null; 876 } 877 878 /** 879 * Sends user response to a USSD REQUEST message. An MmiCode instance 880 * representing this response is sent to handlers registered with 881 * registerForMmiInitiate. 882 * 883 * @param ussdMessge Message to send in the response. 884 * @return false if phone doesn't support ussd service 885 */ 886 public boolean sendUssdResponse(Phone phone, String ussdMessge) { 887 Log.e(LOG_TAG, "sendUssdResponse not implemented"); 888 return false; 889 } 890 891 /** 892 * Mutes or unmutes the microphone for the active call. The microphone 893 * is automatically unmuted if a call is answered, dialed, or resumed 894 * from a holding state. 895 * 896 * @param muted true to mute the microphone, 897 * false to activate the microphone. 898 */ 899 900 public void setMute(boolean muted) { 901 if (VDBG) { 902 Log.d(LOG_TAG, " setMute(" + muted + ")"); 903 Log.d(LOG_TAG, this.toString()); 904 } 905 906 if (hasActiveFgCall()) { 907 getActiveFgCall().getPhone().setMute(muted); 908 } 909 910 if (VDBG) { 911 Log.d(LOG_TAG, "End setMute(" + muted + ")"); 912 Log.d(LOG_TAG, this.toString()); 913 } 914 } 915 916 /** 917 * Gets current mute status. Use 918 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 919 * java.lang.Object) registerForPreciseCallStateChanged()} 920 * as a change notifcation, although presently phone state changed is not 921 * fired when setMute() is called. 922 * 923 * @return true is muting, false is unmuting 924 */ 925 public boolean getMute() { 926 if (hasActiveFgCall()) { 927 return getActiveFgCall().getPhone().getMute(); 928 } else if (hasActiveBgCall()) { 929 return getFirstActiveBgCall().getPhone().getMute(); 930 } 931 return false; 932 } 933 934 /** 935 * Enables or disables echo suppression. 936 */ 937 public void setEchoSuppressionEnabled(boolean enabled) { 938 if (VDBG) { 939 Log.d(LOG_TAG, " setEchoSuppression(" + enabled + ")"); 940 Log.d(LOG_TAG, this.toString()); 941 } 942 943 if (hasActiveFgCall()) { 944 getActiveFgCall().getPhone().setEchoSuppressionEnabled(enabled); 945 } 946 947 if (VDBG) { 948 Log.d(LOG_TAG, "End setEchoSuppression(" + enabled + ")"); 949 Log.d(LOG_TAG, this.toString()); 950 } 951 } 952 953 /** 954 * Play a DTMF tone on the active call. 955 * 956 * @param c should be one of 0-9, '*' or '#'. Other values will be 957 * silently ignored. 958 * @return false if no active call or the active call doesn't support 959 * dtmf tone 960 */ 961 public boolean sendDtmf(char c) { 962 boolean result = false; 963 964 if (VDBG) { 965 Log.d(LOG_TAG, " sendDtmf(" + c + ")"); 966 Log.d(LOG_TAG, this.toString()); 967 } 968 969 if (hasActiveFgCall()) { 970 getActiveFgCall().getPhone().sendDtmf(c); 971 result = true; 972 } 973 974 if (VDBG) { 975 Log.d(LOG_TAG, "End sendDtmf(" + c + ")"); 976 Log.d(LOG_TAG, this.toString()); 977 } 978 return result; 979 } 980 981 /** 982 * Start to paly a DTMF tone on the active call. 983 * or there is a playing DTMF tone. 984 * @param c should be one of 0-9, '*' or '#'. Other values will be 985 * silently ignored. 986 * 987 * @return false if no active call or the active call doesn't support 988 * dtmf tone 989 */ 990 public boolean startDtmf(char c) { 991 boolean result = false; 992 993 if (VDBG) { 994 Log.d(LOG_TAG, " startDtmf(" + c + ")"); 995 Log.d(LOG_TAG, this.toString()); 996 } 997 998 if (hasActiveFgCall()) { 999 getActiveFgCall().getPhone().startDtmf(c); 1000 result = true; 1001 } 1002 1003 if (VDBG) { 1004 Log.d(LOG_TAG, "End startDtmf(" + c + ")"); 1005 Log.d(LOG_TAG, this.toString()); 1006 } 1007 1008 return result; 1009 } 1010 1011 /** 1012 * Stop the playing DTMF tone. Ignored if there is no playing DTMF 1013 * tone or no active call. 1014 */ 1015 public void stopDtmf() { 1016 if (VDBG) { 1017 Log.d(LOG_TAG, " stopDtmf()" ); 1018 Log.d(LOG_TAG, this.toString()); 1019 } 1020 1021 if (hasActiveFgCall()) getFgPhone().stopDtmf(); 1022 1023 if (VDBG) { 1024 Log.d(LOG_TAG, "End stopDtmf()"); 1025 Log.d(LOG_TAG, this.toString()); 1026 } 1027 } 1028 1029 /** 1030 * send burst DTMF tone, it can send the string as single character or multiple character 1031 * ignore if there is no active call or not valid digits string. 1032 * Valid digit means only includes characters ISO-LATIN characters 0-9, *, # 1033 * The difference between sendDtmf and sendBurstDtmf is sendDtmf only sends one character, 1034 * this api can send single character and multiple character, also, this api has response 1035 * back to caller. 1036 * 1037 * @param dtmfString is string representing the dialing digit(s) in the active call 1038 * @param on the DTMF ON length in milliseconds, or 0 for default 1039 * @param off the DTMF OFF length in milliseconds, or 0 for default 1040 * @param onComplete is the callback message when the action is processed by BP 1041 * 1042 */ 1043 public boolean sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) { 1044 if (hasActiveFgCall()) { 1045 getActiveFgCall().getPhone().sendBurstDtmf(dtmfString, on, off, onComplete); 1046 return true; 1047 } 1048 return false; 1049 } 1050 1051 /** 1052 * Notifies when a voice connection has disconnected, either due to local 1053 * or remote hangup or error. 1054 * 1055 * Messages received from this will have the following members:<p> 1056 * <ul><li>Message.obj will be an AsyncResult</li> 1057 * <li>AsyncResult.userObj = obj</li> 1058 * <li>AsyncResult.result = a Connection object that is 1059 * no longer connected.</li></ul> 1060 */ 1061 public void registerForDisconnect(Handler h, int what, Object obj) { 1062 mDisconnectRegistrants.addUnique(h, what, obj); 1063 } 1064 1065 /** 1066 * Unregisters for voice disconnection notification. 1067 * Extraneous calls are tolerated silently 1068 */ 1069 public void unregisterForDisconnect(Handler h){ 1070 mDisconnectRegistrants.remove(h); 1071 } 1072 1073 /** 1074 * Register for getting notifications for change in the Call State {@link Call.State} 1075 * This is called PreciseCallState because the call state is more precise than the 1076 * {@link Phone.State} which can be obtained using the {@link PhoneStateListener} 1077 * 1078 * Resulting events will have an AsyncResult in <code>Message.obj</code>. 1079 * AsyncResult.userData will be set to the obj argument here. 1080 * The <em>h</em> parameter is held only by a weak reference. 1081 */ 1082 public void registerForPreciseCallStateChanged(Handler h, int what, Object obj){ 1083 mPreciseCallStateRegistrants.addUnique(h, what, obj); 1084 } 1085 1086 /** 1087 * Unregisters for voice call state change notifications. 1088 * Extraneous calls are tolerated silently. 1089 */ 1090 public void unregisterForPreciseCallStateChanged(Handler h){ 1091 mPreciseCallStateRegistrants.remove(h); 1092 } 1093 1094 /** 1095 * Notifies when a previously untracked non-ringing/waiting connection has appeared. 1096 * This is likely due to some other entity (eg, SIM card application) initiating a call. 1097 */ 1098 public void registerForUnknownConnection(Handler h, int what, Object obj){ 1099 mUnknownConnectionRegistrants.addUnique(h, what, obj); 1100 } 1101 1102 /** 1103 * Unregisters for unknown connection notifications. 1104 */ 1105 public void unregisterForUnknownConnection(Handler h){ 1106 mUnknownConnectionRegistrants.remove(h); 1107 } 1108 1109 1110 /** 1111 * Notifies when a new ringing or waiting connection has appeared.<p> 1112 * 1113 * Messages received from this: 1114 * Message.obj will be an AsyncResult 1115 * AsyncResult.userObj = obj 1116 * AsyncResult.result = a Connection. <p> 1117 * Please check Connection.isRinging() to make sure the Connection 1118 * has not dropped since this message was posted. 1119 * If Connection.isRinging() is true, then 1120 * Connection.getCall() == Phone.getRingingCall() 1121 */ 1122 public void registerForNewRingingConnection(Handler h, int what, Object obj){ 1123 mNewRingingConnectionRegistrants.addUnique(h, what, obj); 1124 } 1125 1126 /** 1127 * Unregisters for new ringing connection notification. 1128 * Extraneous calls are tolerated silently 1129 */ 1130 1131 public void unregisterForNewRingingConnection(Handler h){ 1132 mNewRingingConnectionRegistrants.remove(h); 1133 } 1134 1135 /** 1136 * Notifies when an incoming call rings.<p> 1137 * 1138 * Messages received from this: 1139 * Message.obj will be an AsyncResult 1140 * AsyncResult.userObj = obj 1141 * AsyncResult.result = a Connection. <p> 1142 */ 1143 public void registerForIncomingRing(Handler h, int what, Object obj){ 1144 mIncomingRingRegistrants.addUnique(h, what, obj); 1145 } 1146 1147 /** 1148 * Unregisters for ring notification. 1149 * Extraneous calls are tolerated silently 1150 */ 1151 1152 public void unregisterForIncomingRing(Handler h){ 1153 mIncomingRingRegistrants.remove(h); 1154 } 1155 1156 /** 1157 * Notifies when out-band ringback tone is needed.<p> 1158 * 1159 * Messages received from this: 1160 * Message.obj will be an AsyncResult 1161 * AsyncResult.userObj = obj 1162 * AsyncResult.result = boolean, true to start play ringback tone 1163 * and false to stop. <p> 1164 */ 1165 public void registerForRingbackTone(Handler h, int what, Object obj){ 1166 mRingbackToneRegistrants.addUnique(h, what, obj); 1167 } 1168 1169 /** 1170 * Unregisters for ringback tone notification. 1171 */ 1172 1173 public void unregisterForRingbackTone(Handler h){ 1174 mRingbackToneRegistrants.remove(h); 1175 } 1176 1177 /** 1178 * Registers the handler to reset the uplink mute state to get 1179 * uplink audio. 1180 */ 1181 public void registerForResendIncallMute(Handler h, int what, Object obj){ 1182 mResendIncallMuteRegistrants.addUnique(h, what, obj); 1183 } 1184 1185 /** 1186 * Unregisters for resend incall mute notifications. 1187 */ 1188 public void unregisterForResendIncallMute(Handler h){ 1189 mResendIncallMuteRegistrants.remove(h); 1190 } 1191 1192 /** 1193 * Register for notifications of initiation of a new MMI code request. 1194 * MMI codes for GSM are discussed in 3GPP TS 22.030.<p> 1195 * 1196 * Example: If Phone.dial is called with "*#31#", then the app will 1197 * be notified here.<p> 1198 * 1199 * The returned <code>Message.obj</code> will contain an AsyncResult. 1200 * 1201 * <code>obj.result</code> will be an "MmiCode" object. 1202 */ 1203 public void registerForMmiInitiate(Handler h, int what, Object obj){ 1204 mMmiInitiateRegistrants.addUnique(h, what, obj); 1205 } 1206 1207 /** 1208 * Unregisters for new MMI initiate notification. 1209 * Extraneous calls are tolerated silently 1210 */ 1211 public void unregisterForMmiInitiate(Handler h){ 1212 mMmiInitiateRegistrants.remove(h); 1213 } 1214 1215 /** 1216 * Register for notifications that an MMI request has completed 1217 * its network activity and is in its final state. This may mean a state 1218 * of COMPLETE, FAILED, or CANCELLED. 1219 * 1220 * <code>Message.obj</code> will contain an AsyncResult. 1221 * <code>obj.result</code> will be an "MmiCode" object 1222 */ 1223 public void registerForMmiComplete(Handler h, int what, Object obj){ 1224 mMmiCompleteRegistrants.addUnique(h, what, obj); 1225 } 1226 1227 /** 1228 * Unregisters for MMI complete notification. 1229 * Extraneous calls are tolerated silently 1230 */ 1231 public void unregisterForMmiComplete(Handler h){ 1232 mMmiCompleteRegistrants.remove(h); 1233 } 1234 1235 /** 1236 * Registration point for Ecm timer reset 1237 * @param h handler to notify 1238 * @param what user-defined message code 1239 * @param obj placed in Message.obj 1240 */ 1241 public void registerForEcmTimerReset(Handler h, int what, Object obj){ 1242 mEcmTimerResetRegistrants.addUnique(h, what, obj); 1243 } 1244 1245 /** 1246 * Unregister for notification for Ecm timer reset 1247 * @param h Handler to be removed from the registrant list. 1248 */ 1249 public void unregisterForEcmTimerReset(Handler h){ 1250 mEcmTimerResetRegistrants.remove(h); 1251 } 1252 1253 /** 1254 * Register for ServiceState changed. 1255 * Message.obj will contain an AsyncResult. 1256 * AsyncResult.result will be a ServiceState instance 1257 */ 1258 public void registerForServiceStateChanged(Handler h, int what, Object obj){ 1259 mServiceStateChangedRegistrants.addUnique(h, what, obj); 1260 } 1261 1262 /** 1263 * Unregisters for ServiceStateChange notification. 1264 * Extraneous calls are tolerated silently 1265 */ 1266 public void unregisterForServiceStateChanged(Handler h){ 1267 mServiceStateChangedRegistrants.remove(h); 1268 } 1269 1270 /** 1271 * Register for notifications when a supplementary service attempt fails. 1272 * Message.obj will contain an AsyncResult. 1273 * 1274 * @param h Handler that receives the notification message. 1275 * @param what User-defined message code. 1276 * @param obj User object. 1277 */ 1278 public void registerForSuppServiceFailed(Handler h, int what, Object obj){ 1279 mSuppServiceFailedRegistrants.addUnique(h, what, obj); 1280 } 1281 1282 /** 1283 * Unregister for notifications when a supplementary service attempt fails. 1284 * Extraneous calls are tolerated silently 1285 * 1286 * @param h Handler to be removed from the registrant list. 1287 */ 1288 public void unregisterForSuppServiceFailed(Handler h){ 1289 mSuppServiceFailedRegistrants.remove(h); 1290 } 1291 1292 /** 1293 * Register for notifications when a sInCall VoicePrivacy is enabled 1294 * 1295 * @param h Handler that receives the notification message. 1296 * @param what User-defined message code. 1297 * @param obj User object. 1298 */ 1299 public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){ 1300 mInCallVoicePrivacyOnRegistrants.addUnique(h, what, obj); 1301 } 1302 1303 /** 1304 * Unregister for notifications when a sInCall VoicePrivacy is enabled 1305 * 1306 * @param h Handler to be removed from the registrant list. 1307 */ 1308 public void unregisterForInCallVoicePrivacyOn(Handler h){ 1309 mInCallVoicePrivacyOnRegistrants.remove(h); 1310 } 1311 1312 /** 1313 * Register for notifications when a sInCall VoicePrivacy is disabled 1314 * 1315 * @param h Handler that receives the notification message. 1316 * @param what User-defined message code. 1317 * @param obj User object. 1318 */ 1319 public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){ 1320 mInCallVoicePrivacyOffRegistrants.addUnique(h, what, obj); 1321 } 1322 1323 /** 1324 * Unregister for notifications when a sInCall VoicePrivacy is disabled 1325 * 1326 * @param h Handler to be removed from the registrant list. 1327 */ 1328 public void unregisterForInCallVoicePrivacyOff(Handler h){ 1329 mInCallVoicePrivacyOffRegistrants.remove(h); 1330 } 1331 1332 /** 1333 * Register for notifications when CDMA call waiting comes 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 registerForCallWaiting(Handler h, int what, Object obj){ 1340 mCallWaitingRegistrants.addUnique(h, what, obj); 1341 } 1342 1343 /** 1344 * Unregister for notifications when CDMA Call waiting comes 1345 * @param h Handler to be removed from the registrant list. 1346 */ 1347 public void unregisterForCallWaiting(Handler h){ 1348 mCallWaitingRegistrants.remove(h); 1349 } 1350 1351 1352 /** 1353 * Register for signal information notifications from the network. 1354 * Message.obj will contain an AsyncResult. 1355 * AsyncResult.result will be a SuppServiceNotification instance. 1356 * 1357 * @param h Handler that receives the notification message. 1358 * @param what User-defined message code. 1359 * @param obj User object. 1360 */ 1361 1362 public void registerForSignalInfo(Handler h, int what, Object obj){ 1363 mSignalInfoRegistrants.addUnique(h, what, obj); 1364 } 1365 1366 /** 1367 * Unregisters for signal information notifications. 1368 * Extraneous calls are tolerated silently 1369 * 1370 * @param h Handler to be removed from the registrant list. 1371 */ 1372 public void unregisterForSignalInfo(Handler h){ 1373 mSignalInfoRegistrants.remove(h); 1374 } 1375 1376 /** 1377 * Register for display information notifications from the network. 1378 * Message.obj will contain an AsyncResult. 1379 * AsyncResult.result will be a SuppServiceNotification instance. 1380 * 1381 * @param h Handler that receives the notification message. 1382 * @param what User-defined message code. 1383 * @param obj User object. 1384 */ 1385 public void registerForDisplayInfo(Handler h, int what, Object obj){ 1386 mDisplayInfoRegistrants.addUnique(h, what, obj); 1387 } 1388 1389 /** 1390 * Unregisters for display information notifications. 1391 * Extraneous calls are tolerated silently 1392 * 1393 * @param h Handler to be removed from the registrant list. 1394 */ 1395 public void unregisterForDisplayInfo(Handler h) { 1396 mDisplayInfoRegistrants.remove(h); 1397 } 1398 1399 /** 1400 * Register for notifications when CDMA OTA Provision status change 1401 * 1402 * @param h Handler that receives the notification message. 1403 * @param what User-defined message code. 1404 * @param obj User object. 1405 */ 1406 public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj){ 1407 mCdmaOtaStatusChangeRegistrants.addUnique(h, what, obj); 1408 } 1409 1410 /** 1411 * Unregister for notifications when CDMA OTA Provision status change 1412 * @param h Handler to be removed from the registrant list. 1413 */ 1414 public void unregisterForCdmaOtaStatusChange(Handler h){ 1415 mCdmaOtaStatusChangeRegistrants.remove(h); 1416 } 1417 1418 /** 1419 * Registration point for subscription info ready 1420 * @param h handler to notify 1421 * @param what what code of message when delivered 1422 * @param obj placed in Message.obj 1423 */ 1424 public void registerForSubscriptionInfoReady(Handler h, int what, Object obj){ 1425 mSubscriptionInfoReadyRegistrants.addUnique(h, what, obj); 1426 } 1427 1428 /** 1429 * Unregister for notifications for subscription info 1430 * @param h Handler to be removed from the registrant list. 1431 */ 1432 public void unregisterForSubscriptionInfoReady(Handler h){ 1433 mSubscriptionInfoReadyRegistrants.remove(h); 1434 } 1435 1436 /** 1437 * Sets an event to be fired when the telephony system processes 1438 * a post-dial character on an outgoing call.<p> 1439 * 1440 * Messages of type <code>what</code> will be sent to <code>h</code>. 1441 * The <code>obj</code> field of these Message's will be instances of 1442 * <code>AsyncResult</code>. <code>Message.obj.result</code> will be 1443 * a Connection object.<p> 1444 * 1445 * Message.arg1 will be the post dial character being processed, 1446 * or 0 ('\0') if end of string.<p> 1447 * 1448 * If Connection.getPostDialState() == WAIT, 1449 * the application must call 1450 * {@link com.android.internal.telephony.Connection#proceedAfterWaitChar() 1451 * Connection.proceedAfterWaitChar()} or 1452 * {@link com.android.internal.telephony.Connection#cancelPostDial() 1453 * Connection.cancelPostDial()} 1454 * for the telephony system to continue playing the post-dial 1455 * DTMF sequence.<p> 1456 * 1457 * If Connection.getPostDialState() == WILD, 1458 * the application must call 1459 * {@link com.android.internal.telephony.Connection#proceedAfterWildChar 1460 * Connection.proceedAfterWildChar()} 1461 * or 1462 * {@link com.android.internal.telephony.Connection#cancelPostDial() 1463 * Connection.cancelPostDial()} 1464 * for the telephony system to continue playing the 1465 * post-dial DTMF sequence.<p> 1466 * 1467 */ 1468 public void registerForPostDialCharacter(Handler h, int what, Object obj){ 1469 mPostDialCharacterRegistrants.addUnique(h, what, obj); 1470 } 1471 1472 public void unregisterForPostDialCharacter(Handler h){ 1473 mPostDialCharacterRegistrants.remove(h); 1474 } 1475 1476 /* APIs to access foregroudCalls, backgroudCalls, and ringingCalls 1477 * 1. APIs to access list of calls 1478 * 2. APIs to check if any active call, which has connection other than 1479 * disconnected ones, pleaser refer to Call.isIdle() 1480 * 3. APIs to return first active call 1481 * 4. APIs to return the connections of first active call 1482 * 5. APIs to return other property of first active call 1483 */ 1484 1485 /** 1486 * @return list of all ringing calls 1487 */ 1488 public List<Call> getRingingCalls() { 1489 return Collections.unmodifiableList(mRingingCalls); 1490 } 1491 1492 /** 1493 * @return list of all foreground calls 1494 */ 1495 public List<Call> getForegroundCalls() { 1496 return Collections.unmodifiableList(mForegroundCalls); 1497 } 1498 1499 /** 1500 * @return list of all background calls 1501 */ 1502 public List<Call> getBackgroundCalls() { 1503 return Collections.unmodifiableList(mBackgroundCalls); 1504 } 1505 1506 /** 1507 * Return true if there is at least one active foreground call 1508 */ 1509 public boolean hasActiveFgCall() { 1510 return (getFirstActiveCall(mForegroundCalls) != null); 1511 } 1512 1513 /** 1514 * Return true if there is at least one active background call 1515 */ 1516 public boolean hasActiveBgCall() { 1517 // TODO since hasActiveBgCall may get called often 1518 // better to cache it to improve performance 1519 return (getFirstActiveCall(mBackgroundCalls) != null); 1520 } 1521 1522 /** 1523 * Return true if there is at least one active ringing call 1524 * 1525 */ 1526 public boolean hasActiveRingingCall() { 1527 return (getFirstActiveCall(mRingingCalls) != null); 1528 } 1529 1530 /** 1531 * return the active foreground call from foreground calls 1532 * 1533 * Active call means the call is NOT in Call.State.IDLE 1534 * 1535 * 1. If there is active foreground call, return it 1536 * 2. If there is no active foreground call, return the 1537 * foreground call associated with default phone, which state is IDLE. 1538 * 3. If there is no phone registered at all, return null. 1539 * 1540 */ 1541 public Call getActiveFgCall() { 1542 Call call = getFirstNonIdleCall(mForegroundCalls); 1543 if (call == null) { 1544 call = (mDefaultPhone == null) 1545 ? null 1546 : mDefaultPhone.getForegroundCall(); 1547 } 1548 return call; 1549 } 1550 1551 // Returns the first call that is not in IDLE state. If both active calls 1552 // and disconnecting/disconnected calls exist, return the first active call. 1553 private Call getFirstNonIdleCall(List<Call> calls) { 1554 Call result = null; 1555 for (Call call : calls) { 1556 if (!call.isIdle()) { 1557 return call; 1558 } else if (call.getState() != Call.State.IDLE) { 1559 if (result == null) result = call; 1560 } 1561 } 1562 return result; 1563 } 1564 1565 /** 1566 * return one active background call from background calls 1567 * 1568 * Active call means the call is NOT idle defined by Call.isIdle() 1569 * 1570 * 1. If there is only one active background call, return it 1571 * 2. If there is more than one active background call, return the first one 1572 * 3. If there is no active background call, return the background call 1573 * associated with default phone, which state is IDLE. 1574 * 4. If there is no background call at all, return null. 1575 * 1576 * Complete background calls list can be get by getBackgroundCalls() 1577 */ 1578 public Call getFirstActiveBgCall() { 1579 Call call = getFirstNonIdleCall(mBackgroundCalls); 1580 if (call == null) { 1581 call = (mDefaultPhone == null) 1582 ? null 1583 : mDefaultPhone.getBackgroundCall(); 1584 } 1585 return call; 1586 } 1587 1588 /** 1589 * return one active ringing call from ringing calls 1590 * 1591 * Active call means the call is NOT idle defined by Call.isIdle() 1592 * 1593 * 1. If there is only one active ringing call, return it 1594 * 2. If there is more than one active ringing call, return the first one 1595 * 3. If there is no active ringing call, return the ringing call 1596 * associated with default phone, which state is IDLE. 1597 * 4. If there is no ringing call at all, return null. 1598 * 1599 * Complete ringing calls list can be get by getRingingCalls() 1600 */ 1601 public Call getFirstActiveRingingCall() { 1602 Call call = getFirstNonIdleCall(mRingingCalls); 1603 if (call == null) { 1604 call = (mDefaultPhone == null) 1605 ? null 1606 : mDefaultPhone.getRingingCall(); 1607 } 1608 return call; 1609 } 1610 1611 /** 1612 * @return the state of active foreground call 1613 * return IDLE if there is no active foreground call 1614 */ 1615 public Call.State getActiveFgCallState() { 1616 Call fgCall = getActiveFgCall(); 1617 1618 if (fgCall != null) { 1619 return fgCall.getState(); 1620 } 1621 1622 return Call.State.IDLE; 1623 } 1624 1625 /** 1626 * @return the connections of active foreground call 1627 * return empty list if there is no active foreground call 1628 */ 1629 public List<Connection> getFgCallConnections() { 1630 Call fgCall = getActiveFgCall(); 1631 if ( fgCall != null) { 1632 return fgCall.getConnections(); 1633 } 1634 return emptyConnections; 1635 } 1636 1637 /** 1638 * @return the connections of active background call 1639 * return empty list if there is no active background call 1640 */ 1641 public List<Connection> getBgCallConnections() { 1642 Call bgCall = getFirstActiveBgCall(); 1643 if ( bgCall != null) { 1644 return bgCall.getConnections(); 1645 } 1646 return emptyConnections; 1647 } 1648 1649 /** 1650 * @return the latest connection of active foreground call 1651 * return null if there is no active foreground call 1652 */ 1653 public Connection getFgCallLatestConnection() { 1654 Call fgCall = getActiveFgCall(); 1655 if ( fgCall != null) { 1656 return fgCall.getLatestConnection(); 1657 } 1658 return null; 1659 } 1660 1661 /** 1662 * @return true if there is at least one Foreground call in disconnected state 1663 */ 1664 public boolean hasDisconnectedFgCall() { 1665 return (getFirstCallOfState(mForegroundCalls, Call.State.DISCONNECTED) != null); 1666 } 1667 1668 /** 1669 * @return true if there is at least one background call in disconnected state 1670 */ 1671 public boolean hasDisconnectedBgCall() { 1672 return (getFirstCallOfState(mBackgroundCalls, Call.State.DISCONNECTED) != null); 1673 } 1674 1675 /** 1676 * @return the first active call from a call list 1677 */ 1678 private Call getFirstActiveCall(ArrayList<Call> calls) { 1679 for (Call call : calls) { 1680 if (!call.isIdle()) { 1681 return call; 1682 } 1683 } 1684 return null; 1685 } 1686 1687 /** 1688 * @return the first call in a the Call.state from a call list 1689 */ 1690 private Call getFirstCallOfState(ArrayList<Call> calls, Call.State state) { 1691 for (Call call : calls) { 1692 if (call.getState() == state) { 1693 return call; 1694 } 1695 } 1696 return null; 1697 } 1698 1699 1700 private boolean hasMoreThanOneRingingCall() { 1701 int count = 0; 1702 for (Call call : mRingingCalls) { 1703 if (call.getState().isRinging()) { 1704 if (++count > 1) return true; 1705 } 1706 } 1707 return false; 1708 } 1709 1710 private Handler mHandler = new Handler() { 1711 1712 @Override 1713 public void handleMessage(Message msg) { 1714 1715 switch (msg.what) { 1716 case EVENT_DISCONNECT: 1717 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_DISCONNECT)"); 1718 mDisconnectRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1719 break; 1720 case EVENT_PRECISE_CALL_STATE_CHANGED: 1721 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_PRECISE_CALL_STATE_CHANGED)"); 1722 mPreciseCallStateRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1723 break; 1724 case EVENT_NEW_RINGING_CONNECTION: 1725 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_NEW_RINGING_CONNECTION)"); 1726 if (getActiveFgCallState().isDialing() || hasMoreThanOneRingingCall()) { 1727 Connection c = (Connection) ((AsyncResult) msg.obj).result; 1728 try { 1729 Log.d(LOG_TAG, "silently drop incoming call: " + c.getCall()); 1730 c.getCall().hangup(); 1731 } catch (CallStateException e) { 1732 Log.w(LOG_TAG, "new ringing connection", e); 1733 } 1734 } else { 1735 mNewRingingConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1736 } 1737 break; 1738 case EVENT_UNKNOWN_CONNECTION: 1739 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_UNKNOWN_CONNECTION)"); 1740 mUnknownConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1741 break; 1742 case EVENT_INCOMING_RING: 1743 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_INCOMING_RING)"); 1744 // The event may come from RIL who's not aware of an ongoing fg call 1745 if (!hasActiveFgCall()) { 1746 mIncomingRingRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1747 } 1748 break; 1749 case EVENT_RINGBACK_TONE: 1750 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_RINGBACK_TONE)"); 1751 mRingbackToneRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1752 break; 1753 case EVENT_IN_CALL_VOICE_PRIVACY_ON: 1754 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_ON)"); 1755 mInCallVoicePrivacyOnRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1756 break; 1757 case EVENT_IN_CALL_VOICE_PRIVACY_OFF: 1758 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_OFF)"); 1759 mInCallVoicePrivacyOffRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1760 break; 1761 case EVENT_CALL_WAITING: 1762 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_CALL_WAITING)"); 1763 mCallWaitingRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1764 break; 1765 case EVENT_DISPLAY_INFO: 1766 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_DISPLAY_INFO)"); 1767 mDisplayInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1768 break; 1769 case EVENT_SIGNAL_INFO: 1770 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_SIGNAL_INFO)"); 1771 mSignalInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1772 break; 1773 case EVENT_CDMA_OTA_STATUS_CHANGE: 1774 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_CDMA_OTA_STATUS_CHANGE)"); 1775 mCdmaOtaStatusChangeRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1776 break; 1777 case EVENT_RESEND_INCALL_MUTE: 1778 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_RESEND_INCALL_MUTE)"); 1779 mResendIncallMuteRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1780 break; 1781 case EVENT_MMI_INITIATE: 1782 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_MMI_INITIATE)"); 1783 mMmiInitiateRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1784 break; 1785 case EVENT_MMI_COMPLETE: 1786 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_MMI_COMPLETE)"); 1787 mMmiCompleteRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1788 break; 1789 case EVENT_ECM_TIMER_RESET: 1790 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_ECM_TIMER_RESET)"); 1791 mEcmTimerResetRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1792 break; 1793 case EVENT_SUBSCRIPTION_INFO_READY: 1794 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_SUBSCRIPTION_INFO_READY)"); 1795 mSubscriptionInfoReadyRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1796 break; 1797 case EVENT_SUPP_SERVICE_FAILED: 1798 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_SUPP_SERVICE_FAILED)"); 1799 mSuppServiceFailedRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1800 break; 1801 case EVENT_SERVICE_STATE_CHANGED: 1802 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_SERVICE_STATE_CHANGED)"); 1803 mServiceStateChangedRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1804 break; 1805 case EVENT_POST_DIAL_CHARACTER: 1806 // we need send the character that is being processed in msg.arg1 1807 // so can't use notifyRegistrants() 1808 if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_POST_DIAL_CHARACTER)"); 1809 for(int i=0; i < mPostDialCharacterRegistrants.size(); i++) { 1810 Message notifyMsg; 1811 notifyMsg = ((Registrant)mPostDialCharacterRegistrants.get(i)).messageForRegistrant(); 1812 notifyMsg.obj = msg.obj; 1813 notifyMsg.arg1 = msg.arg1; 1814 notifyMsg.sendToTarget(); 1815 } 1816 break; 1817 } 1818 } 1819 }; 1820 1821 @Override 1822 public String toString() { 1823 Call call; 1824 StringBuilder b = new StringBuilder(); 1825 1826 b.append("CallManager {"); 1827 b.append("\nstate = " + getState()); 1828 call = getActiveFgCall(); 1829 b.append("\n- Foreground: " + getActiveFgCallState()); 1830 b.append(" from " + call.getPhone()); 1831 b.append("\n Conn: ").append(getFgCallConnections()); 1832 call = getFirstActiveBgCall(); 1833 b.append("\n- Background: " + call.getState()); 1834 b.append(" from " + call.getPhone()); 1835 b.append("\n Conn: ").append(getBgCallConnections()); 1836 call = getFirstActiveRingingCall(); 1837 b.append("\n- Ringing: " +call.getState()); 1838 b.append(" from " + call.getPhone()); 1839 1840 for (Phone phone : getAllPhones()) { 1841 if (phone != null) { 1842 b.append("\nPhone: " + phone + ", name = " + phone.getPhoneName() 1843 + ", state = " + phone.getState()); 1844 call = phone.getForegroundCall(); 1845 b.append("\n- Foreground: ").append(call); 1846 call = phone.getBackgroundCall(); 1847 b.append(" Background: ").append(call); 1848 call = phone.getRingingCall(); 1849 b.append(" Ringing: ").append(call); 1850 } 1851 } 1852 b.append("\n}"); 1853 return b.toString(); 1854 } 1855 } 1856