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