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