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