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