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