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