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